diff -ur --new-file old/linux/Documentation/Configure.help new/linux/Documentation/Configure.help --- old/linux/Documentation/Configure.help Mon Oct 14 18:12:42 1996 +++ new/linux/Documentation/Configure.help Mon Oct 14 18:13:09 1996 @@ -670,6 +670,14 @@ say "386" or "486" here even if running on a Pentium or PPro machine. If you don't know what to do, say "386". +Support for big physical area reservation +CONFIG_BIGPHYS_AREA + Enables kernel support for reserving large areas of physical memory + at boot-time for use by certain device drivers (such as video + framegrabbers, etc.) which require it. To use this feature, boot + the kernel with the boot-time option 'bigphysarea=nnn' where + 'nnn' is the number of pages (a page is usually 4K) to reserve. + Compile the kernel into the ELF object format CONFIG_ELF_KERNEL ELF (Executable and Linkable Format) is a format for libraries and diff -ur --new-file old/linux/arch/i386/config.in new/linux/arch/i386/config.in --- old/linux/arch/i386/config.in Mon Oct 14 18:12:42 1996 +++ new/linux/arch/i386/config.in Mon Oct 14 18:13:09 1996 @@ -43,6 +43,8 @@ 486 CONFIG_M486 \ Pentium CONFIG_M586 \ PPro CONFIG_M686" Pentium +# Added by M. Welsh +bool 'Support for big physical area reservation' CONFIG_BIGPHYS_AREA endmenu source drivers/block/Config.in diff -ur --new-file old/linux/drivers/atm/atmtcp.c new/linux/drivers/atm/atmtcp.c --- old/linux/drivers/atm/atmtcp.c Mon Oct 14 18:12:42 1996 +++ new/linux/drivers/atm/atmtcp.c Mon Oct 14 18:13:09 1996 @@ -259,7 +259,8 @@ NULL, /* no send_oam */ NULL, /* no phy_put */ NULL, /* no phy_get */ - NULL /* no feedback */ + NULL, /* no feedback */ + NULL /* no change_qos */ }; diff -ur --new-file old/linux/drivers/atm/eni.c new/linux/drivers/atm/eni.c --- old/linux/drivers/atm/eni.c Mon Oct 14 18:12:43 1996 +++ new/linux/drivers/atm/eni.c Mon Oct 14 18:13:09 1996 @@ -1144,14 +1144,17 @@ struct eni_vcc *eni_vcc; unsigned long size,mem; int tx_ind,pcr,order; + int unlimited; eni_dev = ENI_DEV(vcc->dev); eni_vcc = ENI_VCC(vcc); eni_vcc->tx = NULL; if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; eni_vcc->txing = 0; - if (vcc->qos.txtp.traffic_class != ATM_UBR) - size = vcc->qos.txtp.max_sdu*3; /* @@@ improve */ + unlimited = vcc->qos.txtp.traffic_class == ATM_UBR && + (!vcc->qos.txtp.max_pcr || vcc->qos.txtp.max_pcr == ATM_MAX_PCR || + vcc->qos.txtp.max_pcr >= ATM_OC3_PCR); + if (!unlimited) size = vcc->qos.txtp.max_sdu*3; /* @@@ improve */ else { if (eni_dev->ubr) { eni_vcc->tx = eni_dev->ubr; @@ -1165,14 +1168,13 @@ mem = eni_alloc_mem(eni_dev,&size); if (!mem) return -ENOBUFS; if ((tx_ind = alloc_tx(eni_dev,&pcr,vcc->qos.txtp.min_pcr, - vcc->qos.txtp.max_pcr,vcc->qos.txtp.traffic_class == ATM_UBR)) < 0) - { + vcc->qos.txtp.max_pcr,unlimited)) < 0) { eni_free_mem(eni_dev,mem,size); return tx_ind; } - if (vcc->qos.txtp.traffic_class == ATM_UBR) - eni_dev->ubr = &eni_dev->tx[tx_ind]; + if (unlimited) eni_dev->ubr = &eni_dev->tx[tx_ind]; else eni_dev->tx_bw -= pcr; + if (pcr > ATM_OC3_PCR) pcr = ATM_OC3_PCR; vcc->qos.txtp.min_pcr = vcc->qos.txtp.max_pcr = pcr; eni_dev->tx[tx_ind].send = (volatile unsigned long *) mem; eni_dev->tx[tx_ind].words = size >> 2; @@ -1881,7 +1883,8 @@ NULL, /* no send_oam */ eni_phy_put, eni_phy_get, - NULL /* no feedback */ + NULL, /* no feedback */ + NULL /* no change_qos */ }; diff -ur --new-file old/linux/drivers/atm/tneta1570.c new/linux/drivers/atm/tneta1570.c --- old/linux/drivers/atm/tneta1570.c Mon Oct 14 18:12:43 1996 +++ new/linux/drivers/atm/tneta1570.c Mon Oct 14 18:13:09 1996 @@ -1,11 +1,34 @@ -/* drivers/atm/tneta1570.c - ti tneta1570 atm driver */ - -/* Written 1996 by Rolf Fiedler (rolf.fiedler@infotech.tu-chemnitz.de) - * based on the atm drivers by Werner Almesberger, EPFL LRC - */ +/* drivers/atm/tneta1570.c - ti tneta1570 atm driver + * + * Copyright (c) 1996 University of Technology Chemnitz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Written 1996 by Rolf Fiedler (atm@infotech.tu-chemnitz.de) + * + * 08/08/1996 adapted to axp, phy access, 64 bit bus access + * some minor bugs in dma allocation,segring overflow, + * timeout,... removed + * (paetz@infotech.tu-chemnitz.de) + * 10/01/1996 bug in dma channel allocattion fixed (multiple channels) + * +*/ #include /* for extended debugging options */ +#include #include #include #include @@ -19,6 +42,7 @@ #include /* for xtime */ #include #include +#include #include #include #include @@ -27,10 +51,10 @@ #include "suni.h" #define SLOW_DOWN_FACTOR 8 - +#define TNETA1570_TIMEOUT 5*HZ /* * KNOWN BUGS: - * + * OAM support ??? , various vci/vpis * doesn't work a bit */ @@ -40,11 +64,14 @@ static void dequeue_AAL0(struct atm_dev *dev); /* dequeue AAL0 cells */ static void dequeue_AAL5(struct atm_dev *dev); /* dequeue AAL5 cells */ static int alloc_dma(struct atm_vcc *vcc); +static unsigned char tneta1570_phy_get(struct atm_dev *,unsigned long); +static void tneta1570_phy_put(struct atm_dev *,unsigned char, unsigned long); + #if 0 -#define DPRINTK printk +#define DPRINTK(format,args...) printk(format,args...) #else -#define DPRINTK (void) +#define DPRINTK(format,args...) #endif #ifndef CONFIG_ATM_TNETA1570_DEBUG @@ -149,7 +176,23 @@ return ptr; } - +/*------------------------------ utopia phy dummies ------------------------ */ +static int utopia_start(struct atm_dev *dev) +{return 0;} +static void utopia_int(struct atm_dev *dev) +{} +static int utopia_ioctl(struct atm_dev *dev, unsigned cmd, unsigned long arg) +{return 0;} +static const struct atmphy_ops utopia_ops = { + utopia_start, + utopia_ioctl, + utopia_int +}; +int utopia_init(struct atm_dev *dev) +{ + dev->phy = &utopia_ops; + return 0; +} /*----------------------------------- RX ------------------------------------*/ @@ -162,7 +205,7 @@ */ static int alloc_dma(struct atm_vcc *vcc) { - unsigned char unsorted[MAX_VPI], sorted[MAX_VPI]; + unsigned char sorted[0x78]; unsigned int x; int i; struct tneta1570_dev *tneta1570_dev; @@ -172,44 +215,31 @@ tneta1570_dev = TNETA1570_DEV(vcc->dev); x = tneta1570_dev->rx_vpi_vci[vcc->vpi]; - if(x != 0) { x = 0x7fff & (x >> 16); return x + vcc->vci - 0x800; /* idx = value - offset */ } else { + for(i=0;i<0x78;i++) + sorted[i]=0x00; /* create a new vpi entry */ /* first, find dma channel range */ - for(i=0; irx_vpi_vci[i] & OWN) { - x = tneta1570_dev->rx_vpi_vci[i]; - unsorted[i] = 0x7f & (x >> 24); - } else { - unsorted[i] = 0; - } - sorted[i] = 0; + x = tneta1570_dev->rx_vpi_vci[i]; + sorted[(0x7f & (x >> 24))-8]=1; + } } - for(i=0; irx_vpi_vci[vcc->vpi] = OWN | ((i+8)<<24) | (MAX_VCI); + if(i == 0x78) return 0; + tneta1570_dev->rx_vpi_vci[vcc->vpi]=OWN|((i+8)<<24)|(MAX_VCI); return 256*i + vcc->vci; } } -/* - * let the protocol have a look at the buffer - */ -static unsigned long tneta1570_fetch(struct atm_vcc *vcc, int i) -{ - return 0; /* not implemented yet */ -} /* * interrupt driven dequeue for rx buffer @@ -232,16 +262,26 @@ NULLCHECK(tneta1570_dev); /* find here completion ring entries */ - EVENT(">completion ring post: %08x, %d\n", + DPRINTK(">completion ring post: %08x, %d\n", (unsigned int)&RX_CMPL_R_IRQ(tneta1570_dev).atm_header, tneta1570_dev->rxcmpl_ring_idx_irq); - while(!(RX_CMPL_R_IRQ(tneta1570_dev).control & OWN)) { + if((RX_CMPL_R_IRQ(tneta1570_dev).error & BUFFER_STARV)) { + printk(DEV_LABEL " rx starvation error \n"); + cli(); + RX_CMPL_R_IRQ(tneta1570_dev).control = OWN; + tneta1570_dev->rxcmpl_ring_idx_irq++; + tneta1570_dev->rxcmpl_ring_idx_irq %= RXCMPLR_SZ_IRQ; + sti(); + continue; + } + cli(); if((RX_CMPL_R_IRQ(tneta1570_dev).control & 0xff) == 0) { dequeue_OAM(dev); } else { if((RX_CMPL_R_IRQ(tneta1570_dev).error & AAL5_IND)) { - dequeue_AAL5(dev); + if((RX_CMPL_R_IRQ(tneta1570_dev).buf_ptr & (1<<31))) + dequeue_AAL5(dev); } else { dequeue_AAL0(dev); @@ -250,10 +290,13 @@ RX_CMPL_R_IRQ(tneta1570_dev).control = OWN; tneta1570_dev->rxcmpl_ring_idx_irq++; tneta1570_dev->rxcmpl_ring_idx_irq %= RXCMPLR_SZ_IRQ; + sti(); } return ; } + + static void dequeue_OAM(struct atm_dev *dev) /* dequeue AAL0 cells */ { struct tneta1570_dev * tneta1570_dev; @@ -264,27 +307,27 @@ NULLCHECK(dev); tneta1570_dev = TNETA1570_DEV(dev); NULLCHECK(tneta1570_dev); + -/* if(vcc->push_oam) printk(" PushOAM is present.\n"); */ - - p = (unsigned int *)(RX_CMPL_R_IRQ(tneta1570_dev).buf_ptr << 2); - skb = (struct sk_buff *)(*(p-1)); /* get skb */ - + + p = (unsigned int *)bus_to_virt(RX_CMPL_R_IRQ(tneta1570_dev).buf_ptr << 2); + skb = (struct sk_buff *)phys_to_virt(*(p-1)); /* get skb */ + /* get new buffer before dequeueing old */ new_skb = alloc_skb(MAX_AAL0_PDU+RX_HDR, GFP_ATOMIC); if(new_skb == NULL) { /* add just received buffer to free list, drop pdu :-( */ - fbr = tneta1570_dev->free_buf_ptr[0].buf_ptr; - fbr[tneta1570_dev->oam_fbr_idx] = OWN | ((int)p >> 2); + fbr = bus_to_virt((unsigned long)tneta1570_dev->free_buf_ptr[0].buf_ptr); + fbr[tneta1570_dev->oam_fbr_idx] = OWN | (virt_to_bus(p) >> 2); tneta1570_dev->oam_fbr_idx++; tneta1570_dev->oam_fbr_idx %= AAL0_BUFS; return; } /* add newly allocated buffer to free list */ - fbr = tneta1570_dev->free_buf_ptr[0].buf_ptr; - fbr[tneta1570_dev->oam_fbr_idx] = OWN | ((unsigned int)(new_skb->data+4) >> 2); + fbr = bus_to_virt((unsigned long)tneta1570_dev->free_buf_ptr[0].buf_ptr); + fbr[tneta1570_dev->oam_fbr_idx] = OWN | (virt_to_bus(new_skb->data+4) >> 2); *(struct sk_buff **)(new_skb->data) = new_skb; tneta1570_dev->oam_fbr_idx++; tneta1570_dev->oam_fbr_idx %= AAL0_BUFS; @@ -299,11 +342,11 @@ skb->len = 52; /* should check for multiple buffers @@@@ */ skb->tail = skb->data + skb->len; - - if (/* vcc->push */ 1) { + + if (/*vcc->push*/1) { dev_kfree_skb(skb, GFP_ATOMIC); - printk(" Don't know how to call push !\n"); - /* vcc->push(vcc,skb); */ +/* printk(DEV_LABEL " Don't know how to call push !\n"); */ +/* vcc->push(vcc,skb); */ } else { dev_kfree_skb(skb, GFP_ATOMIC); printk(DEV_LABEL "(itf %d) No push in protocol.\n", @@ -325,8 +368,8 @@ tneta1570_dev = TNETA1570_DEV(dev); NULLCHECK(tneta1570_dev); - p = (unsigned int *)(RX_CMPL_R_IRQ(tneta1570_dev).buf_ptr << 2); - skb = (struct sk_buff *)(*(p-1)); /* get skb */ + p = (unsigned int *)bus_to_virt(RX_CMPL_R_IRQ(tneta1570_dev).buf_ptr << 2); + skb = (struct sk_buff *)phys_to_virt(*(p-1)); /* get skb */ vcc = skb->atm.vcc; NULLCHECK(vcc); @@ -339,8 +382,8 @@ if(new_skb == NULL) { /* add just received buffer to free list, drop pdu :-( */ v = RX_CMPL_R_IRQ(tneta1570_dev).control; - fbr = tneta1570_dev->free_buf_ptr[0xff & v].buf_ptr; - fbr[tneta1570_vcc->fbr_idx] = OWN | ((int)p >> 2); + fbr = bus_to_virt((unsigned long)tneta1570_dev->free_buf_ptr[0xff & v].buf_ptr); + fbr[tneta1570_vcc->fbr_idx] = OWN | (virt_to_bus(p) >> 2); tneta1570_vcc->fbr_idx++; tneta1570_vcc->fbr_idx %= AAL0_BUFS; return; @@ -349,8 +392,8 @@ /* add newly allocated buffer to free list */ v = RX_CMPL_R_IRQ(tneta1570_dev).control; - fbr = tneta1570_dev->free_buf_ptr[0xff & v].buf_ptr; - fbr[tneta1570_vcc->fbr_idx] = OWN | ((unsigned int)(new_skb->data+4) >> 2); + fbr = bus_to_virt((unsigned long)tneta1570_dev->free_buf_ptr[0xff & v].buf_ptr); + fbr[tneta1570_vcc->fbr_idx] = OWN | (virt_to_bus(new_skb->data+4) >> 2); *(struct sk_buff **)(new_skb->data) = new_skb; new_skb->atm.vcc = vcc; /* link vcc info */ tneta1570_vcc->fbr_idx++; @@ -384,7 +427,7 @@ static void dequeue_AAL5(struct atm_dev *dev) /* dequeue AAL5 PDU */ { struct tneta1570_dev *tneta1570_dev; - struct tneta1570_vcc * tneta1570_vcc; + struct tneta1570_vcc *tneta1570_vcc; struct atm_vcc *vcc; struct sk_buff *skb, *new_skb; unsigned int *p, v, *fbr; @@ -393,9 +436,8 @@ NULLCHECK(dev); tneta1570_dev = TNETA1570_DEV(dev); NULLCHECK(tneta1570_dev); - - p = (unsigned int *)(RX_CMPL_R_IRQ(tneta1570_dev).buf_ptr << 2); - skb = (struct sk_buff *)(*(p-1)); /* get skb */ + p = (unsigned int *)bus_to_virt(RX_CMPL_R_IRQ(tneta1570_dev).buf_ptr << 2); + skb = (struct sk_buff *)phys_to_virt(*(p-1)); /* get skb */ DPRINTK(" p %08x, skb %08x, head %08x, err %08x, sop %08x, trailer %08x, idx %08x", p, skb, @@ -414,21 +456,34 @@ /* get new buffer before dequeueing old * if error in peek drop pdu */ - new_skb = vcc->peek(vcc, MAX_AAL5_PDU+RX_HDR, NULL); - if(new_skb == NULL) { + new_skb=NULL; + + if((RX_CMPL_R_IRQ(tneta1570_dev).error & CRC_ERROR)) { + DPRINTK(DEV_LABEL " rx crc error.\n\n"); + } + if((RX_CMPL_R_IRQ(tneta1570_dev).error & RX_TIMEOUT)) { + DPRINTK(DEV_LABEL " rx time out.\n"); + } + if((RX_CMPL_R_IRQ(tneta1570_dev).error & PAKET_OVERFLOW)) { + DPRINTK(DEV_LABEL " rx packet overflow.\n"); + } + if(!(RX_CMPL_R_IRQ(tneta1570_dev).error & (CRC_ERROR | RX_TIMEOUT | PAKET_OVERFLOW))) + new_skb = vcc->peek(vcc, MAX_AAL5_PDU+RX_HDR, NULL); + if(new_skb == NULL) { /* add just received buffer to free list :-( */ v = RX_CMPL_R_IRQ(tneta1570_dev).control; - fbr = tneta1570_dev->free_buf_ptr[0xff & v].buf_ptr; - fbr[tneta1570_vcc->fbr_idx] = OWN | ((int)p >> 2); + fbr = bus_to_virt((unsigned long)tneta1570_dev->free_buf_ptr[(0xffff & v)].buf_ptr); + fbr[tneta1570_vcc->fbr_idx] = OWN | (virt_to_bus(p) >> 2); tneta1570_vcc->fbr_idx++; tneta1570_vcc->fbr_idx %= AAL5_BUFS; return; } /* add newly allocated buffer to free list */ - + v = RX_CMPL_R_IRQ(tneta1570_dev).control; - fbr = tneta1570_dev->free_buf_ptr[v].buf_ptr; - fbr[tneta1570_vcc->fbr_idx] = OWN | ((unsigned int)(new_skb->data+4) >> 2); + fbr = bus_to_virt((unsigned long)tneta1570_dev->free_buf_ptr[(v & 0xffff)].buf_ptr); + v=virt_to_bus(new_skb->data+4); + fbr[tneta1570_vcc->fbr_idx] = OWN | (v >> 2); *(struct sk_buff **)(new_skb->data) = new_skb; new_skb->atm.vcc = vcc; /* link context info */ tneta1570_vcc->fbr_idx++; @@ -465,7 +520,7 @@ static int start_rx(struct atm_dev *dev) { int i; - unsigned int x; + unsigned long x; unsigned int *ptr; struct sk_buff *buf; struct tneta1570_dev *tneta1570_dev; @@ -484,7 +539,7 @@ return -ENOMEM; } /* align completion-ring with irq to its size */ - x = (unsigned int)(&tneta1570_dev->rxcmpl_ring[RXCMPLR_SZ_IRQ]); + x = (unsigned long)(&tneta1570_dev->rxcmpl_ring[RXCMPLR_SZ_IRQ]); tneta1570_dev->rxcmplringptr_irq = (struct tneta_rx_compl *) (x & (~(RXCMPLR_SZ_IRQ*sizeof(struct tneta_rx_compl) - 1))); /* the rest is for the completion ring w/o irq */ @@ -508,24 +563,24 @@ SAR_REG_SHORT(tneta1570_dev, TNETA_S_RXCOMPLSIZEI) = RXCMPLR_SZ_IRQ-1; SAR_REG_SHORT(tneta1570_dev, TNETA_S_RXCOMPLSIZE) = RXCMPLR_SZ_NOI-1; - SAR_REG_WORD(tneta1570_dev, TNETA_RXCOMPLNOI) = (unsigned int)tneta1570_dev->rxcmplringptr_noi; - SAR_REG_WORD(tneta1570_dev, TNETA_RXCOMPLIRQ) = (unsigned int)tneta1570_dev->rxcmplringptr_irq; + SAR_REG_WORD(tneta1570_dev, TNETA_RXCOMPLNOI) = (unsigned int)virt_to_bus(tneta1570_dev->rxcmplringptr_noi); + SAR_REG_WORD(tneta1570_dev, TNETA_RXCOMPLIRQ) = (unsigned int)virt_to_bus(tneta1570_dev->rxcmplringptr_irq); /* init dma 0,1,2 for oam */ /* alloc memory for oam fbr & buffers */ - ptr = kmalloc(AAL0_BUFS*sizeof(struct tneta_rx_fbrptr), GFP_KERNEL); + ptr = kmalloc(AAL0_BUFS*4, GFP_KERNEL); if(ptr == NULL) printk(DEV_LABEL "PANIC on start rx \n"); for(i=0; idata) = buf; /* link */ - ptr[i] = OWN | ((unsigned int)(buf->data + 4) >> 2); + ptr[i] = OWN | ((unsigned int)virt_to_bus(buf->data + 4) >> 2); } tneta1570_dev->oam_fbr_idx = 0; /* oam cells use fbr 0 */ - tneta1570_dev->free_buf_ptr[0].buf_ptr = ptr; + tneta1570_dev->free_buf_ptr[0].buf_ptr = (unsigned int)virt_to_bus(ptr); tneta1570_dev->free_buf_ptr[0].buf_size = FBR_AAL0_32; tneta1570_dev->rx_dma_state[0].control = RX_DMA_CONTROL_AAL0; @@ -590,7 +645,7 @@ if(vcc->aal == ATM_AAL0) { /* alloc memory for fbr & buffers */ - ptr = kmalloc(AAL0_BUFS*sizeof(struct tneta_rx_fbrptr), + ptr = kmalloc(AAL0_BUFS*4, GFP_KERNEL); if(ptr == NULL) printk(DEV_LABEL "PANIC on open rx \n"); for(i=0; idata) = skb; /* link */ skb->atm.vcc = vcc; /* link vcc info */ - ptr[i] = OWN | ((unsigned int)(skb->data+4) >> 2); + ptr[i] = OWN | ((unsigned int)virt_to_bus(skb->data+4) >> 2); } tneta1570_vcc->fbr_idx = 0; - - tneta1570_dev->free_buf_ptr[fbr_idx].buf_ptr = ptr; + tneta1570_dev->free_buf_ptr[fbr_idx].buf_ptr = virt_to_bus(ptr); tneta1570_dev->free_buf_ptr[fbr_idx].buf_size = FBR_AAL0_32; - + tneta1570_dev->rx_dma_state[dma_idx].control = RX_DMA_CONTROL_AAL0; tneta1570_dev->rx_dma_state[dma_idx].AAL0_cells = MAX_AAL0_CELLS; tneta1570_dev->rx_dma_state[dma_idx].rx_timeout = RX_TIME_OUT; @@ -613,7 +667,7 @@ } else if(vcc->aal == ATM_AAL5) { /* alloc memory for fbr & buffers */ - ptr = kmalloc(AAL5_BUFS*sizeof(struct tneta_rx_fbrptr), + ptr = kmalloc(AAL5_BUFS*4, GFP_KERNEL); if(ptr == NULL) printk(DEV_LABEL "PANIC on open rx \n"); for(i=0; idata) = skb; /* link */ skb->atm.vcc = vcc; /* link vcc info */ - ptr[i] = OWN | ((unsigned int)(skb->data+4) >> 2); + ptr[i] = OWN | ((unsigned int)virt_to_bus(skb->data+4) >> 2); } tneta1570_vcc->fbr_idx = 0; - - tneta1570_dev->free_buf_ptr[fbr_idx].buf_ptr = ptr; + tneta1570_dev->free_buf_ptr[fbr_idx].buf_ptr = virt_to_bus(ptr); tneta1570_dev->free_buf_ptr[fbr_idx].buf_size = FBR_AAL5_16; tneta1570_dev->rx_dma_state[dma_idx].control = RX_DMA_CONTROL_AAL5; @@ -671,7 +724,7 @@ while(tneta1570_dev->rx_dma_state[dma_idx].control & OWN); tneta1570_dev->rx_dma_state[dma_idx].dma_on_idx = 0; /* off */ /* mark as empty */ - ptr = tneta1570_dev->free_buf_ptr[fbr_idx].buf_ptr; + ptr = bus_to_virt((unsigned long)tneta1570_dev->free_buf_ptr[fbr_idx].buf_ptr); tneta1570_dev->free_buf_ptr[fbr_idx].buf_ptr = 0; /* mark fbr free */ x = tneta1570_dev->free_buf_ptr[fbr_idx].buf_size; x = x >> 10; /* ring size */ @@ -680,8 +733,8 @@ x = 16 * x; for(i=0; ifree = 1; /* ???? */ kfree_skb(skb, FREE_READ); } @@ -707,7 +760,8 @@ static int start_tx(struct atm_dev *dev) { int i; - unsigned int x, *seg_ring, *seg_ring_mptr; + unsigned int *seg_ring, *seg_ring_mptr; + unsigned long x; struct tneta1570_dev *tneta1570_dev; EVENT(">start_tx\n",0,0); @@ -722,7 +776,7 @@ } DPRINTK("TX_CMPL_R->%08x", tneta1570_dev->txcmpl_ring); /* align completion-ring with irq to its size */ - x = (unsigned int)(&tneta1570_dev->txcmpl_ring[TXCMPLR_SZ_IRQ]); + x = (unsigned long)(&tneta1570_dev->txcmpl_ring[TXCMPLR_SZ_IRQ]); tneta1570_dev->txcmplringptr_irq = (unsigned int *)(x & (~(TXCMPLR_SZ_IRQ*4 - 1))); /* the rest is for the completion ring w/o irq */ if((tneta1570_dev->txcmplringptr_irq - TXCMPLR_SZ_NOI) > tneta1570_dev->txcmpl_ring) { @@ -747,7 +801,7 @@ dev->number); return -ENOMEM; } - x = (unsigned int)(seg_ring_mptr + TX_SEG_RING_SIZE); + x = (unsigned long)(seg_ring_mptr + TX_SEG_RING_SIZE); seg_ring = (unsigned int *)(x & ~(TX_SEG_RING_SIZE * 4 - 1)); for(i=0; itxcmplringptr_noi; - SAR_REG_WORD(tneta1570_dev, TNETA_TXCOMPLIRQ) = (unsigned int)tneta1570_dev->txcmplringptr_irq; + SAR_REG_WORD(tneta1570_dev, TNETA_TXCOMPLNOI) = (unsigned int)virt_to_bus((void*)tneta1570_dev->txcmplringptr_noi); + SAR_REG_WORD(tneta1570_dev, TNETA_TXCOMPLIRQ) = (unsigned int)virt_to_bus((void*)tneta1570_dev->txcmplringptr_irq); SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) |= TNETA_R0_TX_ENABLE; @@ -780,7 +834,7 @@ static int open_tx(struct atm_vcc *vcc) { int scheduler_idx, i; - unsigned int x; + unsigned long x; struct tneta1570_dev *tneta1570_dev; struct tneta1570_vcc *tneta1570_vcc; @@ -800,7 +854,7 @@ return -ENOMEM; } /* align seg-ring to its size */ - x = (unsigned int)(tneta1570_vcc->seg_ring_mptr + TX_SEG_RING_SIZE); + x = (unsigned long)(tneta1570_vcc->seg_ring_mptr + TX_SEG_RING_SIZE); tneta1570_vcc->seg_ring = (unsigned int *)(x & ~(TX_SEG_RING_SIZE * 4 - 1)); EVENT("> seg ring is at phy %x\n", (unsigned int)tneta1570_vcc->seg_ring,0); @@ -851,8 +905,14 @@ tneta1570_dev = TNETA1570_DEV(vcc->dev); tneta1570_vcc = TNETA1570_VCC(vcc); + current->timeout=jiffies+TNETA1570_TIMEOUT; while(tneta1570_vcc->txing) { - sleep_on(&tneta1570_vcc->tx_wait); /* wait for tx to drain */ + interruptible_sleep_on(&tneta1570_vcc->tx_wait); /* wait for tx to drain */ + if(!current->timeout){ + printk(DEV_LABEL " timed out while closing (%d)\n", + tneta1570_vcc->txing); + break; + } } /* remove ptr to segmentation ring */ @@ -871,9 +931,9 @@ */ static int do_tx(struct sk_buff * skb) { - struct atm_vcc *vcc; - struct tneta1570_dev *tneta1570_dev; - struct tneta1570_vcc *tneta1570_vcc; + struct atm_vcc *vcc=0; + struct tneta1570_dev *tneta1570_dev=0; + struct tneta1570_vcc *tneta1570_vcc=0; unsigned int seg_ring_entry, i; unsigned int *buffer; @@ -884,7 +944,9 @@ tneta1570_dev = TNETA1570_DEV(vcc->dev); NULLCHECK(tneta1570_dev); tneta1570_vcc = TNETA1570_VCC(vcc); - if ((unsigned long) skb->data & 2) { + if(tneta1570_vcc->txing>=TX_SEG_RING_SIZE-1) + interruptible_sleep_on(&tneta1570_vcc->tx_wait); + if ((unsigned long) skb->data & TNETA_ALIGN) { printk(DEV_LABEL "(itf %d): VCI %d has mis-aligned TX data\n", vcc->dev->number,vcc->vci); dev_kfree_skb(skb,FREE_WRITE); @@ -919,7 +981,7 @@ buffer[6+i] = ((unsigned int *)skb->data)[i]; buffer[2] = AAL5_PDU_INT | (0xffff & skb->len); } - buffer[1] = (unsigned int)skb; + buffer[1] = (unsigned int)virt_to_bus(skb); buffer[0] = 0; /* push size */ EVENT(">data copied\n",0,0); } else { /* push skb and put header in front of sdu */ @@ -938,10 +1000,10 @@ buffer[2] = AAL5_PDU_INT | (0xffff & (skb->len-24)); buffer[0] = 24; /* push size */ } - buffer[1] = (unsigned int)skb; /* store skb ptr for dequeue */ + buffer[1] = (unsigned int)virt_to_bus(skb); /* store skb ptr for dequeue */ } - seg_ring_entry = ((unsigned int)(&buffer[2]) >> 2) | OWN; + seg_ring_entry = ((unsigned int)virt_to_bus(&buffer[2]) >> 2) | OWN; tneta1570_vcc->seg_ring[tneta1570_vcc->seg_ring_idx] = seg_ring_entry; DPRINTK(">zippered up"); DPRINTK(">sched %d," @@ -957,10 +1019,11 @@ &buffer[2], buffer[2], buffer[4]); /* index to seg.ring entry for next SDU */ + cli(); /*@@@ restore flags ??*/ tneta1570_vcc->seg_ring_idx++; tneta1570_vcc->seg_ring_idx %= TX_SEG_RING_SIZE; - tneta1570_vcc->txing++; + sti(); return 0; } @@ -983,16 +1046,16 @@ NULLCHECK(dev); tneta1570_dev = TNETA1570_DEV(dev); NULLCHECK(tneta1570_dev); - + cli(); /* find here completion ring entries */ EVENT(">completion ring post: %08x, %d\n", TX_CMPL_R_IRQ(tneta1570_dev), tneta1570_dev->txcmpl_ring_idx_irq); while(!(TX_CMPL_R_IRQ(tneta1570_dev) & OWN)) { - p = (unsigned int *)(TX_CMPL_R_IRQ(tneta1570_dev) << 2); + p = (unsigned int *)bus_to_virt(TX_CMPL_R_IRQ(tneta1570_dev) << 2); TX_CMPL_R_IRQ(tneta1570_dev) = OWN; tneta1570_dev->txcmpl_ring_idx_irq++; tneta1570_dev->txcmpl_ring_idx_irq %= TXCMPLR_SZ_IRQ; - skb = (struct sk_buff *)(*(p-1)); /* get skb */ + skb = (struct sk_buff *)bus_to_virt(*(p-1)); /* get skb */ v = *(p-2); /* get skb push size */ if(v==0) { /* free copy area */ @@ -1008,9 +1071,10 @@ vcc->stats->tx++; TNETA1570_VCC(vcc)->txing--; - wake_up(&(TNETA1570_VCC(vcc)->tx_wait)); + wake_up_interruptible(&(TNETA1570_VCC(vcc)->tx_wait)); dma_complete++; }; +sti(); } @@ -1032,13 +1096,18 @@ { struct atm_dev *dev; struct tneta1570_dev *tneta1570_dev; - unsigned long reason; + unsigned int reason; EVENT(">tneta_int\n",0,0); dev = dev_id; tneta1570_dev = TNETA1570_DEV(dev); while ( (reason = 0x3ff & SAR_REG_WORD(tneta1570_dev, TNETA_STATUS)) ) { DPRINTK(DEV_LABEL ": int 0x%08x\n",reason); + if (reason & TNETA_R1_RX_IRR) { + DPRINTK(DEV_LABEL " Unknown PDU %d.%d\n", + (SAR_REG_WORD(tneta1570_dev,TNETA_RXUNKNOWN) & 0x3f00) >> 16, + SAR_REG_WORD(tneta1570_dev,TNETA_RXUNKNOWN) & 0x0ff); + } /* unknown cell received */ if (reason & TNETA_R1_RX_FREEZE) { EVENT("INT: RX Freeze - RX ring overflow\n",0,0); } /* ? */ @@ -1108,7 +1177,8 @@ static int tneta1570_init(struct atm_dev *dev) { struct tneta1570_dev *tneta1570_dev; - unsigned int real_base,base; + unsigned long base; + unsigned int real_base; unsigned short command; unsigned char revision; int error,i,last; @@ -1175,22 +1245,22 @@ dev->number,pcibios_strerror(error)); return error; } - printk(DEV_LABEL "(itf %d): rev.%d,base=0x%x,irq=%d,",dev->number, - revision,real_base,tneta1570_dev->irq); - if (!(base = (unsigned long) vremap(real_base,tneta1570_dev->pci_map_size))) { + printk(DEV_LABEL "(itf %d): rev.%d,irq=%d,",dev->number, + revision,tneta1570_dev->irq); + if (!(base = (unsigned long) vremap((unsigned long)real_base+TNETA1570_MEM_OFFSET,tneta1570_dev->pci_map_size))) { printk(DEV_LABEL "(itf %d): can't set up page mapping\n", dev->number); return error; } tneta1570_dev->base_diff = real_base-base; - tneta1570_dev->reg = (volatile unsigned int *) (base+TNETA_REG_BASE_OFFSET); - tneta1570_dev->scheduler = (volatile unsigned long *) (base+TNETA_SCHED_TABLE); - tneta1570_dev->ram = (volatile unsigned long *) (base+TNETA_SCHED_TABLE); + tneta1570_dev->reg = (volatile unsigned int *) (base+TNETA_REG_BASE_OFFSET); + tneta1570_dev->scheduler = (volatile unsigned int *) (base+TNETA_SCHED_TABLE); + tneta1570_dev->ram = (volatile unsigned int *) (base+TNETA_SCHED_TABLE); tneta1570_dev->free_buf_ptr = (volatile struct tneta_rx_fbrptr *) (base+TNETA_FREE_BUFFER_POINTERS); - tneta1570_dev->rx_vpi_vci = (volatile unsigned long *) (base+TNETA_RX_VPIVCI_DMA_POINTERS); + tneta1570_dev->rx_vpi_vci = (volatile unsigned int *) (base+TNETA_RX_VPIVCI_DMA_POINTERS); tneta1570_dev->tx_dma_state = (volatile struct tneta_tx_dma_state_table *) (base+TNETA_TX_DMA_STATE_TABLE); tneta1570_dev->rx_dma_state = (volatile struct tneta_rx_dma_state_table *) (base+TNETA_RX_DMA_STATE_TABLE); - tneta1570_dev->phy = (volatile unsigned long *) (base+TNETA_SUNI_OFFSET); + tneta1570_dev->phy = (volatile unsigned int *) (base+TNETA_SUNI_OFFSET); tneta1570_dev->txcmpl_ring_idx_noi = 0; tneta1570_dev->txcmpl_ring_idx_irq = 0; @@ -1222,7 +1292,9 @@ if(i>RESERVED_UL || iram[i] = 0; - printk("mem=%dkB\n",tneta1570_dev->mem >> 10); + (tneta1570_dev->reg[TNETA_STATUS] & 0x00000400)? + printk("mem=%dkB,mode=64 bit,",tneta1570_dev->mem >> 10): + printk("mem=%dkB,mode=32 bit,",tneta1570_dev->mem >> 10); /* reset SAR */ reset_sar(tneta1570_dev); @@ -1230,8 +1302,8 @@ for(i=0; iRESERVED_UL || iram[i] = 0; - /* TODO: check for non-SUNI, check for TAXI ? */ - return suni_init(dev); + + return 0; } @@ -1239,6 +1311,7 @@ { struct tneta1570_dev *tneta1570_dev; int error; + unsigned char phy; EVENT(">tneta1570_start\n",0,0); tneta1570_dev = TNETA1570_DEV(dev); @@ -1259,13 +1332,19 @@ return error; } - /* bring suni up */ - error = dev->phy->start(dev); - if (error) return error; - + if((phy=tneta1570_phy_get(dev,0))==0x30) { + printk("pm5346,rev.%d \n",phy&0x0f); + suni_init(dev); + } else { + printk("utopia,rev.%d \n",phy&0x0f); + utopia_init(dev); + } + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) = TNETA_R0_STANDARD_MODE; SAR_REG_WORD(tneta1570_dev, TNETA_INT_MASK) = TNETA_R2_STANDARD_INTS; + error = dev->phy->start(dev); + if (error) return error; error = start_tx(dev); if (error) return error; error = start_rx(dev); @@ -1292,16 +1371,6 @@ } -/* trying to find a connection identifier */ -/* - * not implemented yet - */ -static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci) -{ - return 0; -} - - static int tneta1570_open(struct atm_vcc *vcc,short vpi,int vci) { struct tneta1570_dev *tneta1570_dev; @@ -1313,13 +1382,8 @@ vcc->alloc_tx = tneta1570_alloc_tx; /* set my skb_alloc function */ tneta1570_dev = TNETA1570_DEV(vcc->dev); -#if 0 /* set to 0 to test atm_find_ci (get_ci usually is faster) */ - error = get_ci(vcc,&vpi,&vci); /* get connection id */ - if (error) return error; -#else error = atm_find_ci(vcc,&vpi,&vci); /* get connection id */ if (error) return error; -#endif vcc->vpi = vpi; vcc->vci = vci; if (vcc->aal != ATM_AAL0 && vcc->aal != ATM_AAL5) return -EINVAL; @@ -1345,9 +1409,73 @@ static int tneta1570_ioctl(struct atm_dev *dev,unsigned int cmd,unsigned long arg) { - if (cmd == 12345678) dump(dev); - if (!dev->phy->ioctl) return -EINVAL; - return dev->phy->ioctl(dev,cmd,arg); + struct tneta1570_dev *tneta1570_dev; + + tneta1570_dev = TNETA1570_DEV(dev); + printk(DEV_LABEL "ioctl \n"); + switch (cmd) { + case TNETA_LOOP: + if(arg) + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) |= + TNETA_R0_LOOP; + else + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) &= + ~TNETA_R0_LOOP; + return 0; + case TNETA_INVHEC: + if(arg) + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) |= + TNETA_R0_TX_HECERR; + else + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) &= + ~TNETA_R0_TX_HECERR; + return 0; + case TNETA_ENTX: + if(arg) + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) |= + TNETA_R0_TX_ENABLE; + else + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) &= + ~TNETA_R0_TX_ENABLE; + return 0; + case TNETA_ENRX: + if(arg) + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) |= + TNETA_R0_RX_ENABLE; + else + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) &= + ~TNETA_R0_RX_ENABLE; + return 0; + case TNETA_BP: + if(arg) + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) |= + TNETA_R0_PERBUFFER; + else + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) &= + ~TNETA_R0_PERBUFFER; + return 0; + case TNETA_RAT: + if(arg) + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) |= + TNETA_R0_RAT_ENABL; + else + SAR_REG_WORD(tneta1570_dev, TNETA_CONFIG) &= + ~TNETA_R0_RAT_ENABL; + return 0; + case TNETA_RXUNKN: + return(SAR_REG_SHORT(tneta1570_dev, TNETA_UNKNOWN_P)); + case TNETA_HECERR: + return(SAR_REG_SHORT(tneta1570_dev, TNETA_S_HEC_ERR)); + case TNETA_AAL5DISC: + return(SAR_REG_SHORT(tneta1570_dev, TNETA_S_AAL_DISCARD)); + case TNETA_RXCELL: + return(SAR_REG_WORD(tneta1570_dev, TNETA_CELL_RXC)); + case TNETA_TXCELL: + return(SAR_REG_WORD(tneta1570_dev, TNETA_CELL_TXC)); + default: + if (!dev->phy->ioctl) return -EINVAL; + return dev->phy->ioctl(dev,cmd,arg); + } } @@ -1391,20 +1519,13 @@ return do_tx(skb); } -/* Scatter/Gather send, build vector and send from user space - * not yet implemented - */ -static int tneta1570_sg_send(struct atm_vcc *vcc,unsigned long start, - unsigned long size) -{ - return vcc->aal == ATM_AAL5 && !((start | size) & 3); - /* don't tolerate misalignment */ -} - static void tneta1570_phy_put(struct atm_dev *dev,unsigned char value, unsigned long addr) { + int i=0; + TNETA1570_DEV(dev)->phy[addr+TNETA_SUNI_RDREQ]=0; + while(i++<20 && !(TNETA1570_DEV(dev)->phy[addr+TNETA_SUNI_RDREQ] & 0x10)); TNETA1570_DEV(dev)->phy[addr] = value; } @@ -1413,10 +1534,12 @@ static unsigned char tneta1570_phy_get(struct atm_dev *dev,unsigned long addr) { volatile unsigned tmp; /* force 32 bit access */ - + int i=0; /* set address */ TNETA1570_DEV(dev)->phy[addr+TNETA_SUNI_RDREQ]=0; - /* read the bugger */ + while(i++<20 && !(TNETA1570_DEV(dev)->phy[addr+TNETA_SUNI_RDREQ] & 0x10)); + TNETA1570_DEV(dev)->phy[addr+TNETA_SUNI_RDREQ]=i=0; + while(i++<20 && !(TNETA1570_DEV(dev)->phy[addr+TNETA_SUNI_RDREQ] & 0x08)); tmp=TNETA1570_DEV(dev)->phy[addr]; return (unsigned char)(0xff & tmp); @@ -1435,7 +1558,8 @@ NULL, /* no send_oam ???? */ tneta1570_phy_put, tneta1570_phy_get, - NULL /* no feedback */ + NULL, /* no feedback */ + NULL /* no change_qos */ }; @@ -1457,6 +1581,11 @@ PCI_DEVICE_ID_TI_TNETA1570, index, &tneta1570_dev->bus, + &tneta1570_dev->dev_fn) + || !pcibios_find_device(PCI_VENDOR_ID_TI, + PCI_DEVICE_ID_TI_TNETA1575, + index, + &tneta1570_dev->bus, &tneta1570_dev->dev_fn)) { dev = atm_dev_register(DEV_LABEL,&ops,0); @@ -1477,3 +1606,20 @@ } return index; } + +#ifdef MODULE + +int init_module(void) +{ + if (!tneta1570_detect()) { + printk(DEV_LABEL ": no adapter found\n"); + return -ENXIO; + } + MOD_INC_USE_COUNT; + return 0; +} +void cleanup_module(void){ + +/* not yet */ +} +#endif diff -ur --new-file old/linux/drivers/atm/tneta1570.h new/linux/drivers/atm/tneta1570.h --- old/linux/drivers/atm/tneta1570.h Mon Oct 14 18:12:43 1996 +++ new/linux/drivers/atm/tneta1570.h Mon Oct 14 18:13:09 1996 @@ -29,14 +29,29 @@ #ifndef PCI_VENDOR_ID_TI #define PCI_VENDOR_ID_TI 0x104c #endif -#ifndef PCI_DEVICE_ID_TI_TNETA1570 +#ifndef PCI_DEVICE_ID_TI_TNETA1570 #define PCI_DEVICE_ID_TI_TNETA1570 0xa001 #endif +#ifndef PCI_DEVICE_ID_TI_TNETA1575 +#define PCI_DEVICE_ID_TI_TNETA1575 0xa102 +#endif + -#define KERNEL_OFFSET 0xc0000000 /* kernel 0 is at linear 0xc0000000 */ -#define DEV_LABEL "tneta1570" +#define DEV_LABEL "tneta157x" #define RAM_INCREMENT 1024 /* check in 4 kB increments */ +#ifdef CONFIG_ALPHA_CIA +#define TNETA1570_MEM_OFFSET CIA_DENSE_MEM +#define TNETA_ALIGN 7 +#elif CONFIG_ALPHA_LCA +#define TNETA1570_MEM_OFFSET LCA_DENSE_MEM +#define TNETA_ALIGN 7 +#else +#define TNETA1570_MEM_OFFSET 0 +#define TNETA_ALIGN 3 +#endif + + /*---------------------------------------------------------*/ /* transmit DMA state table, in control memory */ @@ -79,11 +94,18 @@ #define RX_HDR 20 #define MAX_FBR_ENTRIES 256 struct tneta_rx_fbrptr { - unsigned int * buf_ptr; + unsigned int buf_ptr; unsigned int buf_size; }; -#define AAL5_IND (1<<26) +#define AAL5_IND (1<<26) +#define PAKET_OVERFLOW (1<<31) +#define CRC_ERROR (1<<30) +#define BUFFER_STARV (1<<29) +#define RX_TIMEOUT (1<<28) +#define RX_ABORT (1<<27) +#define RX_ERRORCOND 0xf000 + struct tneta_rx_compl { unsigned int atm_header; unsigned int error; @@ -154,20 +176,21 @@ struct atm_dev *more; /* other TNETA devices */ /*-------------------------------- general information */ - volatile unsigned long *ram; /* base of phy device */ - volatile unsigned long *scheduler; /* base of scheduler table */ + volatile unsigned int *ram; /* base of phy device */ + volatile unsigned int *scheduler; /* base of scheduler table */ volatile unsigned int *reg; /* base of sar regs device */ volatile struct tneta_rx_fbrptr *free_buf_ptr; /* free buffer pointers */ - volatile unsigned long *rx_vpi_vci; /* rx vpi vci table */ + volatile unsigned int *rx_vpi_vci; /* rx vpi vci table */ volatile struct tneta_tx_dma_state_table *tx_dma_state; /* tx dma state table */ volatile struct tneta_rx_dma_state_table *rx_dma_state; /* rx dma state table */ - volatile unsigned long *phy; /* base of phy device */ + volatile unsigned int *phy; /* base of phy device */ int mem; /* RAM on board (in bytes) */ void * base; /* board base address */ unsigned long base_diff; /* virtual - phy base address */ unsigned int pci_map_size; /* pci map size of board */ unsigned char irq; /* IRQ */ + unsigned char chiptype; /* 1570 = 0, 1575 = 1 */ unsigned char bus; /* PCI stuff */ unsigned char dev_fn; }; @@ -178,6 +201,34 @@ /*---------------------------------------------------------*/ +#include + +#define TNETA_LOOP _IOW('a',ATMIOC_SARPRV+1,int) + /* set/reset tneta loopback mode*/ +#define TNETA_INVHEC _IOW('a',ATMIOC_SARPRV+2,long) + /* set/reset inverse HEC generation */ +#define TNETA_ENTX _IOW('a',ATMIOC_SARPRV+3,long) + /* enable/disab txing */ +#define TNETA_ENRX _IOW('a',ATMIOC_SARPRV+4,long) + /* enable/disabable rxing */ +#define TNETA_BP _IOW('a',ATMIOC_SARPRV+5,long) + /* intr per paket or per buffer ring */ +#define TNETA_RAT _IOW('a',ATMIOC_SARPRV+6,int) + /* enable/disable rx aging timer*/ +#define TNETA_RXUNKN _IOR('a',ATMIOC_SARPRV+7,unsigned long) + /* header of an unknown received cell */ +#define TNETA_HECERR _IOR('a',ATMIOC_SARPRV+8, unsigned long) + /* number of HEC errors received */ +#define TNETA_AAL5DISC _IOR('a',ATMIOC_SARPRV+9, unsigned long) + /* number of AAL 5 pdus discarded by tneta */ +#define TNETA_RXCELL _IOR('a',ATMIOC_SARPRV+10, unsigned long) + /* number of cells received */ +#define TNETA_TXCELL _IOR('a',ATMIOC_SARPRV+11, unsigned long) + /* number of cells transmitted */ + + + + /* * Directly Addressable Registers, memory mapped */ @@ -200,9 +251,25 @@ #define TNETA_CELL_RXC 10 /* ATM Cells RX'd # */ #define TNETA_CELL_TXC 11 /* ATM Cells TX'd # */ #define TNETA_S_TXM_RXM 24 /* 12L TX FIFO & RX FIFO max occupancy */ +#define TNETA_TXM_RXM 12 /* TX FIFO & RX FIFO for 1575 */ #define TNETA_S_VCIM 25 /* 12H VCI mask */ #define TNETA_S_SCHEDSIZE 26 /* 13L scheduler-table-size register */ +#define TNETA_SCHEDSIZE 13 /* scheduler-table-size register 1575 only */ #define TNETA_RESET 14 /* software reset register */ +#define TNETA_TXQUEUE 15 /* TX queue register 1575 only*/ +#define TNETA_RXCOMPLCNT 16 /* RX compl ring count 1575 only */ +#define TNETA_SIDEFBR1CNT 17 /* sideband free buffer ring cnt 1575 only */ +#define TNETA_SIDEFBR2CNT 18 /* sideband free buffer ring cnt1575 only */ +#define TNETA_RXTRES 19 /* rx compl ring threshold 1575 only */ +#define TNETA_SIDERXTRES 20 /* sideband free buffer ring thresh 1575 only */ +#define TNETA_SIDEFBR1PTR 21 /* sideband free buffer ring ptr 1575 only */ +#define TNETA_SIDEFBR2PTR 22 /* sideband free buffer ring ptr 1575 only */ +#define TNETA_SIDEFBR1SIZE 23 /* sideband free buffer ring size 1575 only */ +#define TNETA_SIDEFBR2SIZE 24 /* sideband free buffer ring size 1575 only */ +#define TNETA_CHNLADD1 25 /* channel add/del register 1 1575 only */ +#define TNETA_CHNLADD2 26 /* channel add/del register 2 1575 only */ +#define TNETA_TXPAUSE 27 /* transmit pause 1575 only */ +#define TNETA_DMACOUNT 28 /* dma channel count 1575 only */ #define TNETA_TXCOMPLNOI 128 /* TX completion ring W/O interrupt pointer */ #define TNETA_TXCOMPLIRQ 129 /* TX completion ring W/ interrupt pointer */ @@ -210,7 +277,12 @@ #define TNETA_RXCOMPLIRQ 131 /* RX completion ring W/ interrupt pointer */ /* configuration register bits */ -#define TNETA_R0_UNI 0x2000 +#define TNETA_R0_TXBLOCK 0x40000 /* block txing 1575 only */ +#define TNETA_R0_ENBBUS 0x20000 /* enable bus reports 1575 only */ +#define TNETA_R0_NOPOLLTX 0x10000 /* enable performance tx 1575 only */ +#define TNETA_R0_NOPOLLRX 0x8000 /* enable performance rx 1575 only */ +#define TNETA_R0_COPRO 0x4000 /* coprocessor present 1575 only */ +#define TNETA_R0_UNI 0x2000 /* uni / nni */ #define TNETA_R0_MAX_RETRY (0xf << 9) /* 1111 max retry master */ #define TNETA_R0_LOOP 0x0100 /* set to loop-back (reset!, no enable) */ #define TNETA_R0_TX_HECERR 0x0080 /* force HEC error */ @@ -220,9 +292,16 @@ #define TNETA_R0_ENDIAN (0x0 << 3) /* 00 little endian */ #define TNETA_R0_PERBUFFER 0x002 #define TNETA_R0_RAT_ENABL 0x001 /* enable reass. aging timer */ -#define TNETA_R0_STANDARD_MODE (TNETA_R0_UNI) +#define TNETA_R0_STANDARD_MODE 0x00002000 /* status register bits */ + +#define TNETA_R1_LOCALBUS 0x8000 /* local bus interrupt ? 1575 only */ +#define TNETA_R1_COPRO 0x4000 /* copro interrupt ? 1575 only */ +#define TNETA_R1_SIDE1 0x2000 /* rx sideband 1 interrupt? 1575 only */ +#define TNETA_R1_SIDE2 0x1000 /* rx sideband 2 interrupt? 1575 only */ +#define TNETA_R1_RXCOMP 0x800 /* rx compl half inter. ? 1575 only */ +#define TNETA_R1_RXHALF 0x400 /* Rx fifo half full 1575 only */ #define TNETA_R1_PCI_MODE 0x400 /* 32/64 bit */ #define TNETA_R1_RX_FREEZE 0x200 /* rx ring overflow */ #define TNETA_R1_TX_FREEZE 0x100 /* tx ring overflow */ @@ -236,6 +315,7 @@ #define TNETA_R1_CP_TX 0x001 /* packet segmentation completed */ #define TNETA_R2_STANDARD_INTS (TNETA_R1_RX_FREEZE | \ TNETA_R1_TX_FREEZE | \ + TNETA_R1_RX_IRR | \ TNETA_R1_CP_RX | \ TNETA_R1_CP_TX) /* control memory map offsets */ @@ -254,7 +334,7 @@ #define TNETA_SUNI_RD_D_AV (0x10) #define OWN (0x1 << 31) /* own bit, set to 1 if owned by tneta1570 */ -#define SEG_PTR(x) (0x3fffff00 & ((unsigned int)x >> 2)) +#define SEG_PTR(x) (0x3fffff00 & ((unsigned int)virt_to_bus(x) >> 2)) #define BUF_PTR(x) (((unsigned int)x >> 2) & 0x3fffffff) /* pointer to tx data buffer header, aligned to 4 byte */ diff -ur --new-file old/linux/drivers/atm/zatm.c new/linux/drivers/atm/zatm.c --- old/linux/drivers/atm/zatm.c Mon Oct 14 18:12:43 1996 +++ new/linux/drivers/atm/zatm.c Mon Oct 14 18:13:09 1996 @@ -1077,7 +1077,7 @@ struct zatm_vcc *zatm_vcc; unsigned long flags,*loop; unsigned short chan; - int pcr; + int pcr,unlimited; DPRINTK("open_tx_first\n"); zatm_dev = ZATM_DEV(vcc->dev); @@ -1094,17 +1094,19 @@ restore_flags(flags); DPRINTK("chan is %d\n",chan); if (!chan) return -EAGAIN; - if (vcc->qos.txtp.traffic_class == ATM_UBR && zatm_dev->ubr != -1) - zatm_vcc->shaper = zatm_dev->ubr; + unlimited = vcc->qos.txtp.traffic_class == ATM_UBR && + (!vcc->qos.txtp.max_pcr || vcc->qos.txtp.max_pcr == ATM_MAX_PCR || + vcc->qos.txtp.max_pcr >= ATM_OC3_PCR); + if (unlimited && zatm_dev->ubr != -1) zatm_vcc->shaper = zatm_dev->ubr; else { - if (vcc->qos.txtp.traffic_class == ATM_UBR) - vcc->qos.txtp.max_sdu = ATM_MAX_AAL5_PDU; + if (unlimited) vcc->qos.txtp.max_sdu = ATM_MAX_AAL5_PDU; if ((zatm_vcc->shaper = alloc_shaper(vcc->dev,&pcr, - vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr, - vcc->qos.txtp.traffic_class == ATM_UBR)) < 0) { + vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,unlimited)) + < 0) { close_tx(vcc); return zatm_vcc->shaper; } + if (pcr > ATM_OC3_PCR) pcr = ATM_OC3_PCR; vcc->qos.txtp.min_pcr = vcc->qos.txtp.max_pcr = pcr; } zatm_vcc->tx_chan = chan; @@ -1773,7 +1775,8 @@ NULL, /* no send_oam */ zatm_phy_put, zatm_phy_get, - zatm_feedback + zatm_feedback, + NULL /* no change_qos */ }; diff -ur --new-file old/linux/include/linux/arequipa.h new/linux/include/linux/arequipa.h --- old/linux/include/linux/arequipa.h Mon Oct 14 18:12:44 1996 +++ new/linux/include/linux/arequipa.h Mon Oct 14 18:13:12 1996 @@ -8,15 +8,6 @@ #include -/* - * Arequipa is identified by a so-called "Vendor-Specific Application - * identifier" in the Q.2931 B-HLI IE. That identifier consists of three - * bytes with the OUI, followed by four bytes assigned by the organization - * owning the OUI. - */ - -#define EPFL_OUI "\x00\x60\xD7" -#define AREQUIPA_HLT_VS_ID EPFL_OUI "\x01\x00\x00\x01" #define AREQUIPA_PRESET _IO('a',ATMIOC_AREQUIPA) #define AREQUIPA_INCOMING _IO('a',ATMIOC_AREQUIPA+1) diff -ur --new-file old/linux/include/linux/atm.h new/linux/include/linux/atm.h --- old/linux/include/linux/atm.h Mon Oct 14 18:12:43 1996 +++ new/linux/include/linux/atm.h Mon Oct 14 18:13:09 1996 @@ -135,7 +135,6 @@ #define ATM_MAX_PCR -1 /* maximum available PCR */ -#define class traffic_class /* backward compatibility */ struct atm_trafprm { unsigned char traffic_class; /* traffic class (ATM_UBR, ...) */ int max_pcr; /* maximum PCR in cells per second */ diff -ur --new-file old/linux/include/linux/atmarp.h new/linux/include/linux/atmarp.h --- old/linux/include/linux/atmarp.h Mon Oct 14 18:12:43 1996 +++ new/linux/include/linux/atmarp.h Mon Oct 14 18:13:10 1996 @@ -33,6 +33,7 @@ #define ATF_NULL 0x040 /* use NULL encapsulation */ #define ATF_ARPSRV 0x080 /* entry describes ARP server */ +#define ATF_DEFQOS 0x100 /* entry defines default QOS */ #define MAX_ATMARP_SIZE (sizeof(struct atmarphdr)-1+2*(ATM_E164_LEN+ \ diff -ur --new-file old/linux/include/linux/atmdev.h new/linux/include/linux/atmdev.h --- old/linux/include/linux/atmdev.h Mon Oct 14 18:12:43 1996 +++ new/linux/include/linux/atmdev.h Mon Oct 14 18:13:09 1996 @@ -63,6 +63,8 @@ /* get AAL layer statistics */ #define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc) /* get AAL layer statistics and zero */ +#define ATM_SETSC _IOW('a',ATMIOC_SPECIAL+1,int) + /* enable or disable single-copy */ /* for ATM_GETTYPE */ #define ATM_ITFTYP_LEN 8 /* maximum length of interface type name */ @@ -83,6 +85,10 @@ char vci_bits; /* 1..16, ATM_CI_MAX (-1) for maximum */ }; +/* for ATM_SETSC; actually taken from the ATM_VF number space */ + +#define ATM_SC_RX 1024 /* enable RX single-copy */ +#define ATM_SC_TX 2048 /* enable TX single-copy */ #define ATM_BACKLOG_DEFAULT 32 /* if we get more, we're likely to time out anyway */ @@ -119,6 +125,9 @@ to be available */ #define ATM_VF_AQREL 256 /* Arequipa socket is being released */ #define ATM_VF_AQINUSE 512 /* socket is available for Arequipa use */ +#define ATM_VF_SCRX ATM_SC_RX /* 1024; allow single-copy in the RX dir. */ +#define ATM_VF_SCTX ATM_SC_TX /* 2048; allow single-copy in the TX dir. */ + struct atm_vcc { unsigned short flags; /* VCC flags (ATM_VF_*) */ @@ -225,6 +234,7 @@ unsigned char (*phy_get)(struct atm_dev *dev,unsigned long addr); void (*feedback)(struct atm_vcc *vcc,struct sk_buff *skb, unsigned long start,unsigned long dest,int len); + int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos); }; diff -ur --new-file old/linux/include/linux/atmsap.h new/linux/include/linux/atmsap.h --- old/linux/include/linux/atmsap.h Mon Oct 14 18:12:43 1996 +++ new/linux/include/linux/atmsap.h Mon Oct 14 18:13:09 1996 @@ -1,6 +1,6 @@ /* atmsap.h - ATM Service Access Point addressing definitions */ -/* Written 1995 by Werner Almesberger, EPFL LRC */ +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */ #ifndef _LINUX_ATMSAP_H @@ -75,11 +75,6 @@ #define ATM_IMD_EXTENDED 2 /* extended mode of operation */ /* END_IMD */ -/* - * Selected ISO/IEC TR 9577 Network Layer Protocol Identifiers (NLPID) - */ - -#define NLPID_IEEE802_1_SNAP 0x80 /* IEEE 802.1 SNAP */ /* * SAP structures diff -ur --new-file old/linux/include/linux/bigphysarea.h new/linux/include/linux/bigphysarea.h --- old/linux/include/linux/bigphysarea.h Thu Jan 1 01:00:00 1970 +++ new/linux/include/linux/bigphysarea.h Mon Oct 14 18:13:12 1996 @@ -0,0 +1,25 @@ +/* linux/mm/bigphysarea.h, M. Welsh (mdw@cs.cornell.edu) + * Copyright (c) 1996 by Matt Welsh. + * + * This is a set of routines which allow you to reserve a large (?) + * amount of physical memory at boot-time, which can be allocated/deallocated + * by drivers. This memory is intended to be used for devices such as + * video framegrabbers which need a lot of physical RAM (above the amount + * allocated by kmalloc). This is by no means efficient or recommended; + * to be used only in extreme circumstances. + * + */ + +#ifndef __LINUX_BIGPHYSAREA_H +#define __LINUX_BIGPHYSAREA_H + +#include + +extern caddr_t bigphysarea; + +extern void bigphysarea_setup(char *str, int *ints); +extern unsigned long bigphysarea_init(unsigned long mem_start, unsigned long mem_end); +extern caddr_t bigphysarea_alloc(int size); +extern void bigphysarea_free(caddr_t addr, int size); + +#endif __LINUX_BIGPHYSAREA_H diff -ur --new-file old/linux/init/main.c new/linux/init/main.c --- old/linux/init/main.c Mon Oct 14 18:12:43 1996 +++ new/linux/init/main.c Mon Oct 14 18:13:10 1996 @@ -177,6 +177,9 @@ #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD) extern void ipc_init(void); #endif +#ifdef CONFIG_BIGPHYS_AREA +extern void bigphysarea_setup(char *str, int *ints); +#endif /* * Boot command-line arguments @@ -411,6 +414,9 @@ #ifdef CONFIG_BAYCOM { "baycom=", baycom_setup }, #endif +#ifdef CONFIG_BIGPHYS_AREA + { "bigphysarea=", bigphysarea_setup }, +#endif { "scon=", serial_console_setup }, { 0, 0 } }; @@ -802,6 +808,9 @@ memory_start = console_init(memory_start,memory_end); #ifdef CONFIG_PCI memory_start = pci_init(memory_start,memory_end); +#endif +#ifdef CONFIG_BIGPHYS_AREA + memory_start = bigphysarea_init(memory_start,memory_end); #endif memory_start = kmalloc_init(memory_start,memory_end); sti(); diff -ur --new-file old/linux/kernel/ksyms.c new/linux/kernel/ksyms.c --- old/linux/kernel/ksyms.c Mon Oct 14 18:12:42 1996 +++ new/linux/kernel/ksyms.c Mon Oct 14 18:13:09 1996 @@ -66,6 +66,9 @@ #ifdef CONFIG_ATM #include #endif +#ifdef CONFIG_BIGPHYS_AREA +#include +#endif extern char *get_options(char *str, int *ints); extern void set_device_ro(int dev,int flag); @@ -144,6 +147,13 @@ X(remap_page_range), X(high_memory), X(update_vm_cache), + +#ifdef CONFIG_BIGPHYS_AREA + /* Large physical area memory management */ + X(bigphysarea_alloc), + X(bigphysarea_free), + X(bigphysarea), +#endif /* filesystem internal functions */ X(getname), diff -ur --new-file old/linux/mm/Makefile new/linux/mm/Makefile --- old/linux/mm/Makefile Fri Mar 22 11:56:56 1996 +++ new/linux/mm/Makefile Mon Oct 14 18:13:12 1996 @@ -12,4 +12,8 @@ kmalloc.o vmalloc.o \ swap.o vmscan.o page_io.o page_alloc.o swap_state.o swapfile.o +ifeq ($(CONFIG_BIGPHYS_AREA),y) + O_OBJS += bigphysarea.o +endif + include $(TOPDIR)/Rules.make diff -ur --new-file old/linux/mm/bigphysarea.c new/linux/mm/bigphysarea.c --- old/linux/mm/bigphysarea.c Thu Jan 1 01:00:00 1970 +++ new/linux/mm/bigphysarea.c Mon Oct 14 18:13:12 1996 @@ -0,0 +1,113 @@ +/* linux/mm/bigphysarea.c, M. Welsh (mdw@cs.cornell.edu) + * Copyright (c) 1996 by Matt Welsh. + * + * This is a set of routines which allow you to reserve a large (?) + * amount of physical memory at boot-time, which can be allocated/deallocated + * by drivers. This memory is intended to be used for devices such as + * video framegrabbers which need a lot of physical RAM (above the amount + * allocated by kmalloc). This is by no means efficient or recommended; + * to be used only in extreme circumstances. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int bigphysarea_pages = 0; +static unsigned char *bigphysarea_map; +caddr_t bigphysarea; + +#define BIGPHYS_FREE 0 +#define BIGPHYS_INUSE 1 + +void bigphysarea_setup(char *str, int *ints) { + if (ints[0] != 1) { + printk("bigphysarea_setup: Usage: bigphysarea=\n"); + } else { + bigphysarea_pages = ints[1]; + } +} + +unsigned long bigphysarea_init(unsigned long mem_start, unsigned long mem_end) { + int ncp, i; + + if (bigphysarea_pages == 0) return mem_start; + + ncp = (bigphysarea_pages / PAGE_SIZE) + 1; + bigphysarea_map = (caddr_t)((mem_start + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1)); + bigphysarea = bigphysarea_map + (ncp * PAGE_SIZE); + + printk("bigphysarea: Allocated %d pages at 0x%lx.\n", + bigphysarea_pages, (unsigned long)bigphysarea); + + for (i = 0; i < bigphysarea_pages; i++) { + bigphysarea_map[i] = BIGPHYS_FREE; + } + + return (unsigned long)(bigphysarea + (bigphysarea_pages * PAGE_SIZE)); +} + +caddr_t bigphysarea_alloc(int size) { + int i, j, n; + + n = (size / PAGE_SIZE) + 1; + + i = 0; + +try_again: + /* Get the first unallocated page */ + for (; i < bigphysarea_pages; i++) { + if (bigphysarea_map[i] == BIGPHYS_FREE) break; + } + if (i == bigphysarea_pages) return NULL; + + /* Check out the region */ + for (j = i; (j < bigphysarea_pages) && (j < (i + n)); j++) { + if (bigphysarea_map[i] != BIGPHYS_FREE) break; + } + + if (j == (i + n)) { + /* Got it */ + for (j = i; (j < (i + n)); j++) { + bigphysarea_map[j] = BIGPHYS_INUSE; + } + return bigphysarea + (i * PAGE_SIZE); + } + + /* Try again ... */ + i = j; + goto try_again; + +} + +void bigphysarea_free(caddr_t addr, int size) { + int i, j; + int n = (size / PAGE_SIZE) + 1; + + i = (((unsigned int)addr - (unsigned int)bigphysarea)/PAGE_SIZE); + for (j = 0; j < n; j++) { + if (bigphysarea_map[i+j] != BIGPHYS_INUSE) return; + bigphysarea_map[i+j] = BIGPHYS_FREE; + } +} diff -ur --new-file old/linux/net/atm/arequipa.c new/linux/net/atm/arequipa.c --- old/linux/net/atm/arequipa.c Mon Oct 14 18:12:43 1996 +++ new/linux/net/atm/arequipa.c Mon Oct 14 18:13:10 1996 @@ -283,6 +283,7 @@ { int error; + if (upper->state == TCP_LISTEN) return -EPROTO; if (!aqd) { printk(KERN_ERR "arequipa_preset: no Arequipa demon\n"); return -EUNATCH; diff -ur --new-file old/linux/net/atm/atmarp.c new/linux/net/atm/atmarp.c --- old/linux/net/atm/atmarp.c Mon Oct 14 18:12:43 1996 +++ new/linux/net/atm/atmarp.c Mon Oct 14 18:13:09 1996 @@ -429,7 +429,8 @@ memcpy_fromfs(&req,arg,sizeof(struct atmarpreq)); if (req.arp_pa.sa_family != AF_INET) return -EPFNOSUPPORT; ip = &((struct sockaddr_in *) &req.arp_pa)->sin_addr.s_addr; - if (!(*ip & ~dev->pa_mask) && !(req.arp_flags & ATF_ARPSRV)) + if (!(*ip & ~dev->pa_mask) && !(req.arp_flags & (ATF_ARPSRV | + ATF_DEFQOS))) return -EINVAL; switch (cmd) { case SIOCSARP: @@ -495,9 +496,9 @@ dev->name = PRIV(dev)->name; sprintf(dev->name,"atm%d",number); dev->init = clip_init; - if (register_netdev(dev)) return -EIO; /* free dev ? */ PRIV(dev)->number = number; PRIV(dev)->table = NULL; + if (register_netdev(dev)) return -EIO; /* free dev ? */ PRIV(dev)->next = clip_devs; clip_devs = dev; DPRINTK("registered (net:%s)\n",dev->name); diff -ur --new-file old/linux/net/atm/common.c new/linux/net/atm/common.c --- old/linux/net/atm/common.c Mon Oct 14 18:12:43 1996 +++ new/linux/net/atm/common.c Mon Oct 14 18:13:09 1996 @@ -71,7 +71,7 @@ vcc->upper = NULL; vcc->sock = sock; #endif - vcc->flags = 0; + vcc->flags = ATM_VF_SCRX | ATM_VF_SCTX; vcc->dev = NULL; vcc->family = sock->ops->family; vcc->alloc_tx = alloc_tx; @@ -382,23 +382,27 @@ DPRINTK("RcvM %d -= %d\n",vcc->rx_inuse,skb->truesize); atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->rx_inuse); #ifdef CONFIG_MMU_HACKS - mmucp_tofs((unsigned long) buff,eff_len,skb,(unsigned long) skb->data); -#else + if (vcc->flags & ATM_VF_SCRX) + mmucp_tofs((unsigned long) buff,eff_len,skb, + (unsigned long) skb->data); + else +#endif + { #ifdef DUMP_PACKETS - if (vcc->vci==5 || vcc->vci >32) { - char buf[300]; - int i; + if (vcc->vci==5 || vcc->vci >32) { + char buf[300]; + int i; - for(i=0;i<99 && i < skb->len;i++) { - sprintf(buf+i*3,"%2.2x ", - 0xff&skb->data[i]); - } - printk("recv %d:%s\n",vcc->vci,buf); - } + for(i=0;i<99 && i < skb->len;i++) { + sprintf(buf+i*3,"%2.2x ", + 0xff&skb->data[i]); + } + printk("recv %d:%s\n",vcc->vci,buf); + } #endif - memcpy_tofs(buff,skb->data,eff_len); - kfree_skb(skb,FREE_READ); -#endif + memcpy_tofs(buff,skb->data,eff_len); + kfree_skb(skb,FREE_READ); + } return eff_len; } @@ -424,8 +428,8 @@ if (!size) return 0; /* verify_area is done by net/socket.c */ #ifdef CONFIG_MMU_HACKS - if (vcc->dev->ops->sg_send && vcc->dev->ops->sg_send(vcc, - (unsigned long) buff,size)) { + if ((vcc->flags & ATM_VF_SCTX) && vcc->dev->ops->sg_send && + vcc->dev->ops->sg_send(vcc,(unsigned long) buff,size)) { int res,max_iov; max_iov = 2+size/PAGE_SIZE; @@ -569,10 +573,12 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) { struct atm_dev *dev; + struct atm_vcc *vcc; unsigned long eff_arg; int rsize,wsize,len; int error; + vcc = ATM_SD(sock); rsize = wsize = 0; switch (cmd) { case ATM_GETNAMES: @@ -594,29 +600,35 @@ buffer),&buf->length); } case SIOCGSTAMP: /* borrowed from IP */ - if (!ATM_SD(sock)->timestamp.tv_sec) return -ENOENT; - ATM_SD(sock)->timestamp.tv_sec += - ATM_SD(sock)->timestamp.tv_usec/1000000; - ATM_SD(sock)->timestamp.tv_usec %= 1000000; + if (!vcc->timestamp.tv_sec) return -ENOENT; + vcc->timestamp.tv_sec += vcc->timestamp.tv_usec/1000000; + vcc->timestamp.tv_usec %= 1000000; error = verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct timeval)); if (error) return error; - memcpy_tofs((void *) arg,&ATM_SD(sock)->timestamp, + memcpy_tofs((void *) arg,&vcc->timestamp, sizeof(struct timeval)); return 0; + case ATM_SETSC: + if (arg & ~(ATM_VF_SCRX | ATM_VF_SCTX)) return -EINVAL; + /* @@@ race condition - should split flags into + "volatile" and non-volatile part */ + vcc->flags = (vcc->flags & ~(ATM_VF_SCRX | + ATM_VF_SCTX)) | arg; + return 0; case ATMSIGD_CTRL: if (!suser()) return -EPERM; - error = sigd_attach(ATM_SD(sock)); + error = sigd_attach(vcc); if (!error) sock->state = SS_CONNECTED; return error; #ifdef CONFIG_ATM_CLIP case CLIP_PVC: if (!suser()) return -EPERM; - return atm_init_clip(ATM_SD(sock)); + return atm_init_clip(vcc); case CLIP_NULENCAP: case CLIP_LLCENCAP: if (!suser()) return -EPERM; - return clip_ioctl(ATM_SD(sock)->proto_data,NULL,cmd); + return clip_ioctl(vcc->proto_data,NULL,cmd); /* rather crude hack ... */ #endif #ifdef CONFIG_ATM_ATMARP @@ -625,18 +637,18 @@ return clip_create(arg); case ATMARPD_CTRL: if (!suser()) return -EPERM; - error = atm_init_atmarp(ATM_SD(sock)); + error = atm_init_atmarp(vcc); if (!error) sock->state = SS_CONNECTED; return error; case ATMARP_MKIP: if (!suser()) return -EPERM; - return atmarp_mkip(ATM_SD(sock),arg); + return atmarp_mkip(vcc,arg); case ATMARP_SETENTRY: if (!suser()) return -EPERM; - return atmarp_setentry(ATM_SD(sock),arg); + return atmarp_setentry(vcc,arg); case ATMARP_ENCAP: if (!suser()) return -EPERM; - return atmarp_encap(ATM_SD(sock),arg); + return atmarp_encap(vcc,arg); #endif #ifdef CONFIG_AREQUIPA case AREQUIPA_PRESET: @@ -654,7 +666,7 @@ return arequipa_incoming(sock); case AREQUIPA_CTRL: if (!suser()) return -EPERM; - error = arequipad_attach(ATM_SD(sock)); + error = arequipad_attach(vcc); if (!error) sock->state = SS_CONNECTED; return error; case AREQUIPA_CLS3RD: @@ -665,15 +677,15 @@ #ifdef CONFIG_ATM_LANE case ATMLEC_CTRL: if (!suser()) return -EPERM; - error = lecd_attach(ATM_SD(sock), (int)arg); + error = lecd_attach(vcc, (int)arg); if (error >=0) sock->state = SS_CONNECTED; return error; case ATMLEC_MCAST: if (!suser()) return -EPERM; - return lec_mcast_attach(ATM_SD(sock), (int)arg); + return lec_mcast_attach(vcc, (int)arg); case ATMLEC_DATA: if (!suser()) return -EPERM; - return lec_vcc_attach(ATM_SD(sock), (void*)arg); + return lec_vcc_attach(vcc, (void*)arg); #endif case ATM_GETTYPE: wsize = -1; /* special - don't check length */ @@ -787,10 +799,7 @@ char *optval,int optlen) { struct atm_vcc *vcc; - int error; - error = verify_area(VERIFY_READ,optval,optlen); - if (error) return -EINVAL; vcc = ATM_SD(sock); if (level == SOL_SOCKET) { unsigned long value; @@ -833,7 +842,7 @@ (vcc->qos.rxtp.min_pcr || vcc->qos.rxtp.max_pcr))) printk(KERN_WARNING "Warning: " - "semantics of ATM_UBR will change " + "semantics of ATM_UBR have changed " "with min/max_pcr != 0\n"); vcc->flags |= ATM_VF_HASQOS; return 0; diff -ur --new-file old/linux/net/atm/pvc.c new/linux/net/atm/pvc.c --- old/linux/net/atm/pvc.c Mon Oct 14 18:12:43 1996 +++ new/linux/net/atm/pvc.c Mon Oct 14 18:13:09 1996 @@ -105,7 +105,21 @@ static int pvc_setsockopt(struct socket *sock,int level,int optname, char *optval,int optlen) { - /* put PVC-specific code here */ + struct atm_vcc *vcc; + int error; + + error = verify_area(VERIFY_READ,optval,optlen); + if (error) return -EINVAL; + vcc = ATM_SD(sock); + if (level == SOL_ATM && optname == SO_ATMQOS && + sock->state == SS_CONNECTED) { + struct atm_qos qos; + + if (optlen != sizeof(struct atm_qos)) return -EINVAL; + if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP; + memcpy_fromfs(&qos,optval,optlen); + return vcc->dev->ops->change_qos(vcc,&qos); + } return atm_setsockopt(sock,level,optname,optval,optlen); } diff -ur --new-file old/linux/net/atm/svc.c new/linux/net/atm/svc.c --- old/linux/net/atm/svc.c Mon Oct 14 18:12:43 1996 +++ new/linux/net/atm/svc.c Mon Oct 14 18:13:09 1996 @@ -552,6 +552,10 @@ static int svc_setsockopt(struct socket *sock,int level,int optname, char *optval,int optlen) { + int error; + + error = verify_area(VERIFY_READ,optval,optlen); + if (error) return -EINVAL; /* stuff for SVCs */ return atm_setsockopt(sock,level,optname,optval,optlen); } diff -ur --new-file old/linux/net/ipv4/af_inet.c new/linux/net/ipv4/af_inet.c --- old/linux/net/ipv4/af_inet.c Mon Oct 14 18:12:43 1996 +++ new/linux/net/ipv4/af_inet.c Mon Oct 14 18:13:10 1996 @@ -541,6 +541,9 @@ { struct sock *sk = (struct sock *) sock->data; +#ifdef CONFIG_AREQUIPA + if (sk->aq_route && sk->ip_route_cache == sk->aq_route) return -EPROTO; +#endif if(inet_autobind(sk)!=0) return -EAGAIN; .