patch-2.1.17 linux/drivers/net/ibmtr.c
Next file: linux/drivers/net/ibmtr.h
Previous file: linux/drivers/net/hydra.c
Back to the patch index
Back to the overall index
- Lines: 707
- Date:
Sat Dec 21 13:16:57 1996
- Orig file:
v2.1.16/linux/drivers/net/ibmtr.c
- Orig date:
Sat Nov 30 12:03:08 1996
diff -u --recursive --new-file v2.1.16/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
@@ -54,11 +54,7 @@
- restructured the READ.LOG logic to prevent the transmit SRB
from being rudely overwritten before the transmit cycle is
complete. (August 15 1996)
-
- Warnings !!!!!!!!!!!!!!
- This driver is only partially sanitized for support of multiple
- adapters. It will almost definitely fail if more than one
- active adapter is identified.
+ - completed multiple adapter support. (November 20 1996)
*/
#ifdef PCMCIA
@@ -85,11 +81,13 @@
/* some 95 OS send many non UI frame; this allow removing the warning */
#define TR_FILTERNONUI 1
+/* use memcpy to read/write frame data instead of for-loop */
+#define USE_MEMCPY 1
+
/* version and credits */
-static const char *version =
-"ibmtr.c: v1.3.57 8/7/94 Peter De Schrijver and Mark Swanson\n"
-" modified 10/3/94 DW Morris, modified at VIA, ECP, France\n"
-" (3/9/95 F Farid and P Andre, 9/7/95 PA and 2/20/95 ML/PA/YD)\n";
+static char *version =
+"ibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n"
+" v2.1.10 11/20/96 Paul Norton <pnorton@cts.com>\n";
static char pcchannelid[]={0x05, 0x00, 0x04, 0x09,
0x04, 0x03, 0x04, 0x0f,
@@ -137,9 +135,11 @@
char *adapter_def(char type)
{
switch (type) {
- case 0xF : return "Adapter/A";
- case 0xE : return "16/4 Adapter/II";
- default : return "adapter";
+ case 0xF : return "PC Adapter | PC Adapter II | Adapter/A";
+ case 0xE : return "16/4 Adapter | 16/4 Adapter/A (long)";
+ case 0xD : return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter";
+ case 0xC : return "Auto 16/4 Adapter";
+ default : return "adapter (unknown type)";
};
};
#endif
@@ -153,11 +153,8 @@
#define TRC_INIT 0x01 /* Trace initialization & PROBEs */
#define TRC_INITV 0x02 /* verbose init trace points */
-/* addresses to scan */
-static short TokBaseAddrs[] = { MMIOStartLocP, MMIOStartLocA };
-
-
-int tok_probe(struct device *dev);
+int ibmtr_probe(struct device *dev);
+static int ibmtr_probe1(struct device *dev, int ioaddr);
unsigned char get_sram_size(struct tok_info *adapt_info);
static int tok_init_card(struct device *dev);
@@ -178,6 +175,8 @@
void tr_readlog(struct device *dev);
static struct timer_list tr_timer={NULL,NULL,0,0L,tok_open_adapter};
+static unsigned int ibmtr_portlist[] = {0xa20, 0xa24, 0};
+static __u32 ibmtr_mem_base = 0xd0000;
#if 0
int DummyCallCount=0;
@@ -204,138 +203,122 @@
printk("\n");
}
-/* tok_probe(): Routine specified in the network device structure
+/* ibmtr_probe(): Routine specified in the network device structure
to probe for an IBM Token Ring Adapter. Routine outline:
I. Interrogate hardware to determine if an adapter exists
and what the speeds and feeds are
II. Setup data structures to control execution based upon
adapter characteristics.
III. Initialize adapter operation
- We expect tok_probe to be called once for each device entry
+ We expect ibmtr_probe to be called once for each device entry
which references it.
*/
+int ibmtr_probe(struct device *dev)
+{
+ int i;
+ int base_addr = dev ? dev->base_addr : 0;
+
+ if (base_addr > 0x1ff) { /* check a single specified location. */
+ if (ibmtr_probe1(dev, base_addr)) {
+#ifndef MODULE
+ tr_freedev(dev);
+#endif
+ return -ENODEV;
+ } else {
+ return 0;
+ }
+ }
+ else if (base_addr != 0) /* Don't probe at all. */
+ return -ENXIO;
-int tok_probe(struct device *dev)
+ for (i = 0; ibmtr_portlist[i]; i++) {
+ int ioaddr = ibmtr_portlist[i];
+ if (check_region(ioaddr, IBMTR_IO_EXTENT))
+ continue;
+ if (ibmtr_probe1(dev, ioaddr)) {
+#ifndef MODULE
+ tr_freedev(dev);
+#endif
+ } else {
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
+static int ibmtr_probe1(struct device *dev, int PIOaddr)
{
unsigned char segment=0, intr=0, irq=0, i=0, j=0, cardpresent=NOTOK,temp=0;
__u32 t_mmio=0;
- short PIOaddr=0, iAddr;
struct tok_info *ti=0;
- static struct tok_info *badti=0; /* if fail after kmalloc, reuse */
-
- static unsigned char Shared_Ram_Base = IBMTR_SHARED_RAM_BASE;
-
- /* this is the major adapter probe loop. For each call to tok_probe,
- we try each remaining entry in TokBaseAddrs[] as a possible
- adapter. Once an entry is rejected or assigned, we zero it to
- avoid duplicate use or worthless trial for the tok probe call*/
-
- for (iAddr=0;
- iAddr < (sizeof(TokBaseAddrs)/sizeof(short))&&PIOaddr==0; iAddr++) {
-
- __u32 cd_chanid;
- unsigned char *tchanid, ctemp;
-
- PIOaddr=TokBaseAddrs[iAddr]; /* address to try */
- TokBaseAddrs[iAddr] = 0; /* (and marked already used */
- if (PIOaddr == 0) continue; /* already tried this addr */
-
- /* Make sure PIO address not already assigned
- elsewhere before we muck with IO address */
- if (check_region(PIOaddr,TR_IO_EXTENT)) {
- if (ibmtr_debug_trace & TRC_INIT)
- DPRINTK("check_region(%4hx,%d) failed.\n", PIOaddr, TR_IO_EXTENT);
- PIOaddr = 0;
- continue; /* clear to flag fail and try next */
- }
- /* Query the adapter PIO base port which will return
- indication of where MMIO was placed (per tech ref
- this assignment is done by BIOS - what is rational for
- where it is?). We also have a coded interrupt address. */
-
- segment = inb(PIOaddr);
- /* out of range values so we'll assume non-existent IO device */
- if (segment < 0x40 || segment > 0xe0) {
- PIOaddr = 0;
- continue; /* clear to flag fail and try next */
- }
-
- /* Compute the linear base address of the MMIO area
- as LINUX doesn't care about segments */
- t_mmio=(((__u32)(segment & 0xfc) << 11) + 0x80000);
- intr = segment & 0x03; /* low bits is coded interrupt # */
- if (ibmtr_debug_trace & TRC_INIT)
- DPRINTK("PIOaddr: %4hx seg/intr: %2x mmio base: %08X intr: %d\n", PIOaddr, (int)segment, t_mmio, (int)intr);
-
- /* Now we will compare expected 'channelid' strings with
- what we is there to learn of ISA/MCA or not TR card */
- /* !!!WARNING:!!!! It seems pretty silly to blunder ahead
- w/o verification that the mmio address we have found
- is valid storage -- perhaps this is tolerable for current
- hardware state??? */
-
- cd_chanid = (CHANNEL_ID + t_mmio); /* for efficiency */
- tchanid=pcchannelid;
- cardpresent=TR_ISA; /* try ISA */
-
- /* suboptimize knowing first byte different */
- ctemp = readb(cd_chanid) & 0x0f;
- if (ctemp != *tchanid) { /* NOT ISA card, try MCA */
- tchanid=mcchannelid;
- cardpresent=TR_MCA;
- if (ctemp != *tchanid) /* Neither ISA nor MCA */
- cardpresent=NOTOK;
- }
+ __u32 cd_chanid;
+ unsigned char *tchanid, ctemp;
+
+#ifndef MODULE
+ dev = init_trdev(dev,0);
+#endif
+
+ /* Query the adapter PIO base port which will return
+ indication of where MMIO was placed. We also have a
+ coded interrupt number. */
+
+ segment = inb(PIOaddr);
+ /* out of range values so we'll assume non-existent IO device */
+ if (segment < 0x40 || segment > 0xe0)
+ return -ENODEV;
+
+ /* Compute the linear base address of the MMIO area
+ as LINUX doesn't care about segments */
+ t_mmio=(((__u32)(segment & 0xfc) << 11) + 0x80000);
+ intr = segment & 0x03; /* low bits is coded interrupt # */
+ if (ibmtr_debug_trace & TRC_INIT)
+ DPRINTK("PIOaddr: %4hx seg/intr: %2x mmio base: %08X intr: %d\n",
+ PIOaddr, (int)segment, t_mmio, (int)intr);
+
+ /* Now we will compare expected 'channelid' strings with
+ what we is there to learn of ISA/MCA or not TR card */
+ cd_chanid = (CHANNEL_ID + t_mmio); /* for efficiency */
+ tchanid=pcchannelid;
+ cardpresent=TR_ISA; /* try ISA */
+
+ /* suboptimize knowing first byte different */
+ ctemp = readb(cd_chanid) & 0x0f;
+ if (ctemp != *tchanid) { /* NOT ISA card, try MCA */
+ tchanid=mcchannelid;
+ cardpresent=TR_MCA;
+ if (ctemp != *tchanid) /* Neither ISA nor MCA */
+ cardpresent=NOTOK;
+ }
- if (cardpresent != NOTOK) { /* know presumed type, try rest of ID */
- for (i=2,j=1; i<=46; i=i+2,j++) {
- if ((readb(cd_chanid+i) & 0x0f) != tchanid[j]) {
- cardpresent=NOTOK; /* match failed, not TR card */
- break;
- }
+ if (cardpresent != NOTOK) { /* know presumed type, try rest of ID */
+ for (i=2,j=1; i<=46; i=i+2,j++) {
+ if ((readb(cd_chanid+i) & 0x0f) != tchanid[j]) {
+ cardpresent=NOTOK; /* match failed, not TR card */
+ break;
}
}
+ }
- /* If we have an ISA board check for the ISA P&P version,
- as it has different IRQ settings */
- if (cardpresent == TR_ISA && (readb(AIPFID + t_mmio)==0x0e))
- cardpresent=TR_ISAPNP;
-
- if (cardpresent == NOTOK) { /* "channel_id" did not match, report */
- if (ibmtr_debug_trace & TRC_INIT) {
- DPRINTK("Channel ID string not found for PIOaddr: %4hx\n", PIOaddr);
- DPRINTK("Expected for ISA: "); PrtChanID(pcchannelid,1);
- DPRINTK(" found: "); HWPrtChanID(cd_chanid,2);
- DPRINTK("Expected for MCA: "); PrtChanID(mcchannelid,1);
- }
- PIOaddr = 0; /* all to know not found yet */
- continue;
+ /* If we have an ISA board check for the ISA P&P version,
+ as it has different IRQ settings */
+ if (cardpresent == TR_ISA && (readb(AIPFID + t_mmio)==0x0e))
+ cardpresent=TR_ISAPNP;
+
+ if (cardpresent == NOTOK) { /* "channel_id" did not match, report */
+ if (ibmtr_debug_trace & TRC_INIT) {
+ DPRINTK("Channel ID string not found for PIOaddr: %4hx\n", PIOaddr);
+ DPRINTK("Expected for ISA: "); PrtChanID(pcchannelid,1);
+ DPRINTK(" found: "); HWPrtChanID(cd_chanid,2);
+ DPRINTK("Expected for MCA: "); PrtChanID(mcchannelid,1);
}
+ return -ENODEV;
+ }
- /* !!!! we could tighten validation by checking the HW Address
- against the 1-s complement.. Move the get HW logic to here */
+ /* Now, allocate some of the pl0 buffers for this driver.. */
+ ti = (struct tok_info *)kmalloc(sizeof(struct tok_info), GFP_KERNEL);
+ if (ti == NULL) return -ENOMEM;
- }
-
- /* The search loop has either completed with a presumed TR adapter
- or none found. Check situation ... march on if possible */
-
- if (PIOaddr == 0) { /* failed to find a valid TR adapter */
- if (ibmtr_debug_trace & TRC_INIT)
- DPRINTK("Unable to assign adapter to device.\n");
- return ENODEV;
- }
-
- /*?? Now, allocate some of the pl0 buffers for this driver.. */
-
- if (!badti) {
- ti = (struct tok_info *)kmalloc(sizeof(struct tok_info), GFP_KERNEL);
- if (ti == NULL) return -ENOMEM;
- } else {
- ti = badti;
- badti = NULL;
- } /*?? dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); */
-
memset(ti, 0, sizeof(struct tok_info));
ti->mmio= t_mmio;
@@ -354,6 +337,7 @@
if (intr==2) irq=6;
if (intr==3) irq=7;
ti->global_int_enable=GLOBAL_INT_ENABLE+((irq==9) ? 2 : irq);
+ ti->adapter_int_enable=PIOaddr+ADAPTINTREL;
ti->sram=0;
#if !TR_NEWFORMAT
DPRINTK("ti->global_int_enable: %04X\n",ti->global_int_enable);
@@ -365,6 +349,7 @@
if (intr==2) irq=10;
if (intr==3) irq=11;
ti->global_int_enable=0;
+ ti->adapter_int_enable=0;
ti->sram=((__u32)(inb(PIOaddr+ADAPTRESETREL) & 0xfe) << 12);
break;
case TR_ISAPNP:
@@ -375,6 +360,7 @@
while(!readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN));
ti->sram=((__u32)readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)<<12);
ti->global_int_enable=PIOaddr+ADAPTINTREL;
+ ti->adapter_int_enable=PIOaddr+ADAPTINTREL;
break;
}
@@ -425,7 +411,7 @@
/* Support paging? What sizes?: F=no, E=16k, D=32k, C=16 & 32k */
ti->shared_ram_paging = readb(ti->mmio + AIPSHRAMPAGE);
- /* Available DHB 4Mb size: F=2048, E=4096, D=4464 */
+ /* Available DHB 4Mb size: F=2048, E=4096, D=4464 */
ti->dhb_size4mb = readb(ti->mmio + AIP4MBDHB);
/* Available DHB 16Mb size: F=2048, E=4096, D=8192, C=16384, B=17960 */
@@ -446,7 +432,7 @@
paging), then only one adapter can be supported. */
/* determine how much of total RAM is mapped into PC space */
- ti->mapped_ram_size=1<<(((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)) >>2) +4);
+ ti->mapped_ram_size=1<<((((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)) >>2) & 0x03) + 4);
ti->page_mask=0;
if (ti->shared_ram_paging == 0xf) { /* No paging in adapter */
ti->mapped_ram_size = ti->avail_shared_ram;
@@ -478,11 +464,13 @@
R/O and I can't find how to select which page size
Also, the above conditional statement sequence is invalid
as page_mask will always be set by the second stmt */
- badti=ti;
+ kfree_s(ti, sizeof(struct tok_info));
+ return -ENODEV;
break;
default:
DPRINTK("Unknown shared ram paging info %01X\n",ti->shared_ram_paging);
- badti=ti; /* bail out if bad code */
+ kfree_s(ti, sizeof(struct tok_info));
+ return -ENODEV;
break;
}
if (ti->page_mask) {
@@ -500,58 +488,59 @@
/* finish figuring the shared RAM address */
if (cardpresent==TR_ISA) {
- static unsigned char ram_bndry_mask[]={0xfe, 0xfc, 0xf8, 0xf0};
- unsigned char new_base, rrr_32, chk_base, rbm;
- rrr_32 = (readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2;
+ static __u32 ram_bndry_mask[]={0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000};
+ __u32 new_base, rrr_32, chk_base, rbm;
+
+ rrr_32 = ((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2) & 0x00000003;
rbm = ram_bndry_mask[rrr_32];
- new_base = (Shared_Ram_Base + (~rbm)) & rbm; /* up to boundary */
- chk_base = new_base + (ti->mapped_ram_size>>3);
- if (chk_base > (IBMTR_SHARED_RAM_BASE+IBMTR_SHARED_RAM_SIZE)) {
+ new_base = (ibmtr_mem_base + (~rbm)) & rbm; /* up to boundary */
+ chk_base = new_base + (ti->mapped_ram_size<<9);
+ if (chk_base > (ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE)) {
DPRINTK("Shared RAM for this adapter (%05x) exceeds driver"
" limit (%05x), adapter not started.\n",
- chk_base<<12, (IBMTR_SHARED_RAM_BASE+
- IBMTR_SHARED_RAM_SIZE)<<12);
- badti=ti;
+ chk_base, ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE);
+ kfree_s(ti, sizeof(struct tok_info));
+ return -ENODEV;
} else { /* seems cool, record what we have figured out */
- ti->sram_base = new_base;
- Shared_Ram_Base = new_base;
+ ti->sram_base = new_base >> 12;
+ ibmtr_mem_base = chk_base;
}
}
- /* dwm: irq and other final setup moved here so if we find other
- unrecognized values OR shared ram conflicts, we can still
- bail out in a rather benign fashion. */
-
- if (badti) return ENODEV;
#if !TR_NEWFORMAT
DPRINTK("Using %dK shared RAM\n",ti->mapped_ram_size/2);
#endif
- if (request_irq (dev->irq = irq, &tok_interrupt,0,"IBM TR", NULL) != 0) {
+ if (request_irq (dev->irq = irq, &tok_interrupt,0,"ibmtr", NULL) != 0) {
DPRINTK("Could not grab irq %d. Halting Token Ring driver.\n",irq);
- badti = ti; /* keep track of unused tok_info */
- return ENODEV;
+ kfree_s(ti, sizeof(struct tok_info));
+ return -ENODEV;
}
irq2dev_map[irq]=dev;
/*?? Now, allocate some of the PIO PORTs for this driver.. */
- request_region(PIOaddr,TR_IO_EXTENT,"ibmtr"); /* record PIOaddr range
+ request_region(PIOaddr,IBMTR_IO_EXTENT,"ibmtr"); /* record PIOaddr range
as busy */
#if !TR_NEWFORMAT
DPRINTK("%s",version); /* As we have passed card identification,
let the world know we're here! */
#else
- printk("%s",version);
- DPRINTK("%s %s found using irq %d, PIOaddr %4hx, %dK shared RAM.\n",
- channel_def[cardpresent-1], adapter_def(ti->adapter_type), irq,
- PIOaddr, ti->mapped_ram_size/2);
+
+ if (version) {
+ printk("%s",version);
+ version = NULL;
+ }
+ DPRINTK("%s %s found\n",
+ channel_def[cardpresent-1], adapter_def(ti->adapter_type));
+ DPRINTK("using irq %d, PIOaddr %hx, %dK shared RAM.\n",
+ irq, PIOaddr, ti->mapped_ram_size/2);
DPRINTK("Hardware address : %02X:%02X:%02X:%02X:%02X:%02X\n",
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
#endif
dev->base_addr=PIOaddr; /* set the value for device */
-
+
trdev_init(dev);
tok_init_card(dev);
@@ -593,7 +582,11 @@
dev->get_stats = NULL;
dev->get_stats = tok_get_stats;
dev->set_multicast_list = NULL;
+
+#ifndef MODULE
tr_setup(dev);
+#endif
+
return 0;
}
@@ -638,6 +631,8 @@
DPRINTK("close adapter failed: %02X\n",
(int)readb(ti->srb + offsetof(struct srb_close_adapter, ret_code)));
+ dev->start = 0;
+ DPRINTK("Adapter closed.\n");
MOD_DEC_USE_COUNT;
return 0;
@@ -647,14 +642,25 @@
{
unsigned char status;
struct tok_info *ti;
- struct device *dev = (struct device *)(irq2dev_map[irq]);
+ struct device *dev;
#if TR_VERBOSE
DPRINTK("Int from tok_driver, dev : %p\n",dev);
#endif
+ dev = (struct device *)(irq2dev_map[irq]);
+ ti = (struct tok_info *) dev->priv;
- ti=(struct tok_info *) dev->priv;
-
+ /* Disable interrupts till processing is finished */
+ dev->interrupt=1;
+ writeb((~INT_ENABLE), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
+
+ /* Reset interrupt for ISA boards */
+ if (ti->adapter_int_enable)
+ outb(0,ti->adapter_int_enable);
+ else
+ outb(0,ti->global_int_enable);
+
+
switch (ti->do_tok_int) {
case NOT_FIRST:
@@ -663,15 +669,6 @@
the extra levels of logic and call depth for the
original solution. */
- dev->interrupt=1;
-
- /* Disable interrupts till processing is finished */
- writeb((~INT_ENABLE), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
-
- /* Reset interrupt for ISA boards */
- if (ti->global_int_enable)
- outb(0, ti->global_int_enable);
-
status=readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_ODD);
#ifdef PCMCIA
/* Check if the PCMCIA card was pulled. */
@@ -1022,19 +1019,13 @@
ti=(struct tok_info *) dev->priv;
- writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
-
- /* Reset interrupt for ISA boards */
- if (ti->global_int_enable) outb(0,ti->global_int_enable);
-
ti->do_tok_int=NOT_FIRST;
#ifndef TR_NEWFORMAT
DPRINTK("Initial tok int received\n");
#endif
- /* we assign the address for ISA devices; set RRR even to D000 for
- shared RAM address */
+ /* we assign the shared-ram address for ISA devices */
if(!ti->sram) {
writeb(ti->sram_base, ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN);
ti->sram=((__u32)ti->sram_base << 12);
@@ -1042,6 +1033,9 @@
ti->init_srb=ti->sram
+ntohs((unsigned short)readw(ti->mmio+ ACA_OFFSET + WRBR_EVEN));
SET_PAGE(ntohs((unsigned short)readw(ti->mmio+ACA_OFFSET + WRBR_EVEN)));
+
+ dev->mem_start = ti->sram;
+ dev->mem_end = ti->sram + (ti->mapped_ram_size<<9) - 1;
#if TR_VERBOSE
{
@@ -1067,7 +1061,7 @@
DPRINTK("encoded addr (%04X,%04X,%08X): ", hw_encoded_addr,
ntohs(hw_encoded_addr), encoded_addr);
#else
- DPRINTK("Initial interrupt : shared RAM located at %08X.\n", encoded_addr);
+ DPRINTK("Initial interrupt : shared RAM located at %08x.\n", ti->sram);
#endif
ti->auto_ringspeedsave=readb(ti->init_srb
@@ -1258,17 +1252,27 @@
/* header length including rif is computed above, now move the data
and set fields appropriately. */
+#if USE_MEMCPY
+ memcpy_toio(dhb, ti->current_skb->data, hdr_len);
+#else
for (i=0; i<hdr_len; i++)
writeb(*(unsigned char *)(ti->current_skb->data +i), dhb++);
+#endif
writeb(hdr_len, ti->asb + offsetof(struct asb_xmit_resp, hdr_length));
writew(htons(ti->current_skb->len-sizeof(struct trh_hdr)+hdr_len),
ti->asb + offsetof(struct asb_xmit_resp, frame_length));
/* now copy the actual packet data next to hdr */
+#if USE_MEMCPY
+ memcpy_toio(dhb + hdr_len,
+ ti->current_skb->data + sizeof(struct trh_hdr),
+ ti->current_skb->len - sizeof(struct trh_hdr));
+#else
for (i=0; i<ti->current_skb->len-sizeof(struct trh_hdr); i++)
writeb(*(unsigned char *)(ti->current_skb->data +sizeof(struct trh_hdr)+i),
dhb+i);
+#endif
writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
dev->tbusy=0;
@@ -1386,9 +1390,12 @@
skb->dev=dev;
data=skb->data;
+#if USE_MEMCPY
+ memcpy_fromio(data, rbuffer + offsetof(struct rec_buf, data), lan_hdr_len);
+#else
for (i=0; i<lan_hdr_len; i++)
data[i]=readb(rbuffer + offsetof(struct rec_buf, data)+i);
-
+#endif
if (lan_hdr_len<sizeof(struct trh_hdr))
memset(data+lan_hdr_len, 0, sizeof(struct trh_hdr)-lan_hdr_len);
@@ -1405,9 +1412,12 @@
#if TR_VERBOSE
DPRINTK("rbuffer_len: %d, data: %p\n", rbuffer_len, data);
#endif
-
+#if USE_MEMCPY
+ memcpy_fromio(data, rbuffer + offsetof(struct rec_buf, data) + lan_hdr_len, rbuffer_len);
+#else
for (i=0; i<rbuffer_len; i++)
data[i]=readb(rbuffer+ offsetof(struct rec_buf, data)+lan_hdr_len+i);
+#endif
data+=rbuffer_len;
while (readw(rbuffer + offsetof(struct rec_buf, buf_ptr))) {
@@ -1446,12 +1456,7 @@
ticks_waited=jiffies - dev->trans_start;
if (ticks_waited<TR_BUSY_INTERVAL) return 1;
- DPRINTK("Arrg. Transmitter busy for more than 50 msec. "
- "Donald resets adapter, but resetting\n"
- "the IBM tokenring adapter takes a long time."
- " It might not even help when the\n"
- "ring is very busy, so we just wait a little longer "
- "and hope for the best.\n");
+ DPRINTK("Arrg. Transmitter busy.\n");
dev->trans_start+=5; /* we fake the transmission start time... */
return 1;
}
@@ -1502,42 +1507,55 @@
#ifdef MODULE
-
-static char devicename[9] = { 0, };
-static struct device dev_ibmtr = {
- devicename, /* device name is inserted by linux/drivers/net/net_init.c */
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, tok_probe };
-
-static int io = 0xa20;
-static char *device = NULL;
+/* 3COM 3C619C supports 8 interrupts, 32 I/O ports */
+static struct device* dev_ibmtr[IBMTR_MAX_ADAPTERS];
+static int io[IBMTR_MAX_ADAPTERS] = {0xa20,0xa24};
+static int irq[IBMTR_MAX_ADAPTERS] = {0,0};
+static int mem[IBMTR_MAX_ADAPTERS] = {0,0};
int init_module(void)
{
- if (device)
- strcpy(dev_ibmtr.name,device);
- else if (!dev_ibmtr.name[0]) strcpy(dev_ibmtr.name,"tr0");
-
- if (io == 0)
- printk("ibmtr: You should not use auto-probing with insmod!\n");
- dev_ibmtr.base_addr = io;
- dev_ibmtr.irq = 0;
-
- if (register_netdev(&dev_ibmtr) != 0) {
- printk("ibmtr: No adapters were found.\n");
- return -EIO;
+ int i;
+ for (i = 0; io[i] && (i<IBMTR_MAX_ADAPTERS); i++) {
+ irq[i] = 0;
+ mem[i] = 0;
+ dev_ibmtr[i] = NULL;
+ dev_ibmtr[i] = init_trdev(dev_ibmtr[i], 0);
+ if (dev_ibmtr[i] == NULL)
+ return -ENOMEM;
+
+ dev_ibmtr[i]->base_addr = io[i];
+ dev_ibmtr[i]->irq = irq[i];
+ dev_ibmtr[i]->mem_start = mem[i];
+ dev_ibmtr[i]->init = &ibmtr_probe;
+
+ if (register_trdev(dev_ibmtr[i]) != 0) {
+ kfree_s(dev_ibmtr[i], sizeof(struct dev));
+ dev_ibmtr[i] = NULL;
+ if (i == 0) {
+ printk("ibmtr: register_trdev() returned non-zero.\n");
+ return -EIO;
+ } else {
+ return 0;
+ }
+ }
}
return 0;
}
void cleanup_module(void)
{
- unregister_netdev(&dev_ibmtr);
-
- /* If we don't do this, we can't re-insmod it later. */
- free_irq(dev_ibmtr.irq, NULL);
- irq2dev_map[dev_ibmtr.irq] = NULL;
- release_region(dev_ibmtr.base_addr, TR_IO_EXTENT);
+ int i;
+
+ for (i = 0; i < IBMTR_MAX_ADAPTERS; i++)
+ if (dev_ibmtr[i]) {
+ unregister_trdev(dev_ibmtr[i]);
+ free_irq(dev_ibmtr[i]->irq, NULL);
+ irq2dev_map[dev_ibmtr[i]->irq] = NULL;
+ release_region(dev_ibmtr[i]->base_addr, IBMTR_IO_EXTENT);
+ kfree_s(dev_ibmtr[i]->priv, sizeof(struct tok_info));
+ kfree_s(dev_ibmtr[i], sizeof(struct dev));
+ dev_ibmtr[i] = NULL;
+ }
}
#endif /* MODULE */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov