Messages in this thread Patch in this message | | | Date | Wed, 26 May 1999 22:13:00 +0000 | From | Bruce Korb <> | Subject | patch for eepro.c :-[I had to fix it ]-: |
| |
For some inexplicable reason, not only was the P&P stuff stripped out, but my card's io address was removed from the list of addresses to check!! Yes, I could have booted DOS, run the SOFTSET2 program and changed the io addr to one of the ones I found in the linux/drivers/net/eepro.c file, but good grief!! Even still, I did that to disable P&P and that wound up making the card unidentifiable to the driver. So, finally, I located the old floppy where the 0.10e version was located. That version did not work, of course, so I merged its stuff with the _alternate_ 0.10c path. It was confusing, but I have it all working.
My card is:
Intel EtherExpress Pro/10+ ISA with P&P
It was waaaaaaaaaaaaaaaaay too much work!! Some of the diffs are due to better formatting in the "old" 0.10e version vs. the "new" 0.10c version.--- eepro.c.orig Sun Nov 15 10:33:02 1998 +++ eepro.c.new Wed May 26 15:11:56 1999 @@ -23,13 +23,20 @@ This is a compatibility hardware problem. Versions: - - 0.10c Some cosmetic changes. (9/28/98, BCH) - - 0.10b Should work now with (some) Pro/10+. At least for - me (and my two cards) it does. _No_ guarantee for - function with non-Pro/10+ cards! (don't have any) - (RMC, 9/11/96) + 0.10f Some cosmetic changes. (9/28/98, BCH - reapplied 5/25/99, BK) + 0.10e Rick Bressler notified me that ifconfig up;ifconfig down fails + because the irq is lost somewhere. Fixed that by moving + request_irq and free_irq to eepro_open and eepro_close respectiveley. + 0.10d Ugh! Now Wakeup works. Was seriously broken in my first attempt. + I'll need to find a way to specify an ioport other than + the default one in the PnP case. PnP definitively sucks. + And, yes, this is not the noly reason. + 0.10c PnP Wakeup Test for 595FX. uncomment #define PnPWakeup; + to use. + 0.10b Should work now with (some) Pro/10+. At least for + me (and my two cards) it does. _No_ guarantee for + function with non-Pro/10+ cards! (don't have any) + (RMC, 9/11/96) 0.10 Added support for the Etherexpress Pro/10+. The IRQ map was changed significantly from the old @@ -72,8 +79,8 @@ */ -static const char *version = - "eepro.c: v0.10c 9/28/98 Bao C. Ha (bao@hacom.net)\n"; +static const char eepro_version[] = + "eepro.c: v0.10f 9/3/96 Bao C. Ha (bao.ha@srs.gov)\n"; #include <linux/module.h> @@ -123,7 +130,13 @@ /* A zero-terminated list of I/O addresses to be probed. */ static unsigned int eepro_portlist[] = - { 0x300, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0}; + { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0}; +/* note: 0x300 is default, the 595FX supports ALL IO Ports + from 0x000 to 0x3F0, some of which are reserved in PCs */ + +/* To try the (not-really PnP Wakeup: */ + +#define PnPWakeup /* use 0 for production, 1 for verification, >2 for debug */ @@ -173,6 +186,86 @@ #define SA3_ADDR2 0x00 #define SA3_ADDR3 0xc9 +#define GetBit(x,y) ((x & (1<<y))>>y) + +/* EEPROM Word 0: */ +#define ee_PnP 0 /* Plug 'n Play enable bit */ +#define ee_Word1 1 /* Word 1? */ +#define ee_BusWidth 2 /* 8/16 bit */ +#define ee_FlashAddr 3 /* Flash Address */ +#define ee_FlashMask 0x7 /* Mask */ +#define ee_AutoIO 6 /* */ +#define ee_reserved0 7 /* =0! */ +#define ee_Flash 8 /* Flash there? */ +#define ee_AutoNeg 9 /* Auto Negotiation enabled? */ +#define ee_IO0 10 /* IO Address LSB */ +#define ee_IO0Mask 0x /*...*/ +#define ee_IO1 15 /* IO MSB */ + +/* EEPROM Word 1: */ +#define ee_IntSel 0 /* Interrupt */ +#define ee_IntMask 0x7 +#define ee_LI 3 /* Link Integrity 0= enabled */ +#define ee_PC 4 /* Polarity Correction 0= enabled */ +#define ee_TPE_AUI 5 /* PortSelection 1=TPE */ +#define ee_Jabber 6 /* Jabber prevention 0= enabled */ +#define ee_AutoPort 7 /* Auto Port Selection 1= Disabled */ +#define ee_SMOUT 8 /* SMout Pin Control 0= Input */ +#define ee_PROM 9 /* Flash EPROM / PROM 0=Flash */ +#define ee_reserved1 10 /* .. 12 =0! */ +#define ee_AltReady 13 /* Alternate Ready, 0=normal */ +#define ee_reserved2 14 /* =0! */ +#define ee_Duplex 15 + +/* Word2,3,4: */ +#define ee_IA5 0 /*bit start for individual Addr Byte 5 */ +#define ee_IA4 8 /*bit start for individual Addr Byte 5 */ +#define ee_IA3 0 /*bit start for individual Addr Byte 5 */ +#define ee_IA2 8 /*bit start for individual Addr Byte 5 */ +#define ee_IA1 0 /*bit start for individual Addr Byte 5 */ +#define ee_IA0 8 /*bit start for individual Addr Byte 5 */ + +/* Word 5: */ +#define ee_BNC_TPE 0 /* 0=TPE */ +#define ee_BootType 1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */ +#define ee_BootTypeMask 0x3 +#define ee_NumConn 3 /* Number of Connections 0= One or Two */ +#define ee_FlashSock 4 /* Presence of Flash Socket 0= Present */ +#define ee_PortTPE 5 +#define ee_PortBNC 6 +#define ee_PortAUI 7 +#define ee_PowerMgt 10 /* 0= disabled */ +#define ee_CP 13 /* Concurrent Processing */ +#define ee_CPMask 0x7 + +/* Word 6: */ +#define ee_Stepping 0 /* Stepping info */ +#define ee_StepMask 0x0F +#define ee_BoardID 4 /* Manucaturer Board ID, reserved */ +#define ee_BoardMask 0x0FFF + +/* Word 7: */ +#define ee_INT_TO_IRQ 0 /* int to IRQ Mapping = 0x1EB8 for Pro/10+ */ +#define ee_FX_INT2IRQ 0x1EB8 /* the _only_ mapping allowed for FX chips */ + +/*..*/ +#define ee_SIZE 0x40 /* total EEprom Size */ +#define ee_Checksum 0xBABA /* initial and final value for adding checksum */ + + +/* Card identification via EEprom: */ +#define ee_addr_vendor 0x10 /* Word offset for EISA Vendor ID */ +#define ee_addr_id 0x11 /* Word offset for Card ID */ +#define ee_addr_SN 0x12 /* Serial Number */ +#define ee_addr_CRC_8 0x14 /* CRC over last thee Bytes */ + + +#define ee_vendor_intel0 0x25 /* Vendor ID Intel */ +#define ee_vendor_intel1 0xD4 +#define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */ +#define ee_id_eepro10p1 0x31 + + /* Index to functions, as function prototypes. */ extern int eepro_probe(struct device *dev); @@ -346,12 +439,39 @@ #else -int +int eepro_probe(struct device *dev) { int i; int base_addr = dev ? dev->base_addr : 0; +#ifdef PnPWakeup + + /* Wakeup: */ + #define WakeupPort 0x279 + #define WakeupSeq {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\ + 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\ + 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\ + 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43} + + { + unsigned short int WS[32]=WakeupSeq; + + if (check_region(WakeupPort, 2)==0) { + if (net_debug>3) + printk("Waking UP\n"); + + outb_p(0,WakeupPort); + outb_p(0,WakeupPort); + for (i=0; i<32; i++) { + outb_p(WS[i],WakeupPort); + if (net_debug>3) printk(": %#x ",WS[i]); + } + if (net_debug>3) printk("\n"); + } else printk("Checkregion Failed!\n"); + } +#endif + if (base_addr > 0x1ff) /* Check a single specified location. */ return eepro_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ @@ -370,11 +490,65 @@ } #endif +#if NET_DEBUG > 3 +void +printEEPROMInfo(short ioaddr) +{ + unsigned short Word; + int i,j; + + for (i=0, j=ee_Checksum; i<ee_SIZE; i++) + j+=read_eeprom(ioaddr,i); + printk("Checksum: %#x\n",j&0xffff); + + Word=read_eeprom(ioaddr, 0); + printk("Word0:\n"); + printk(" Plug 'n Pray: %d\n",GetBit(Word,ee_PnP)); + printk(" Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 ); + printk(" AutoNegotiation: %d\n",GetBit(Word,ee_AutoNeg)); + printk(" IO Address: %#x\n", (Word>>ee_IO0)<<4); + + Word=read_eeprom(ioaddr, 1); + printk("Word1:\n"); + printk(" INT: %d\n", Word & ee_IntMask); + printk(" LI: %d\n", GetBit(Word,ee_LI)); + printk(" PC: %d\n", GetBit(Word,ee_PC)); + printk(" TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI)); + printk(" Jabber: %d\n", GetBit(Word,ee_Jabber)); + printk(" AutoPort: %d\n", GetBit(!Word,ee_Jabber)); + printk(" Duplex: %d\n", GetBit(Word,ee_Duplex)); + + Word=read_eeprom(ioaddr, 5); + printk(" Word5:\n"); + printk(" BNC: %d\n",GetBit(Word,ee_BNC_TPE)); + printk(" NumConnectors: %d\n",GetBit(Word,ee_NumConn)); + printk("Has "); + if (GetBit(Word,ee_PortTPE)) printk("TPE "); + if (GetBit(Word,ee_PortBNC)) printk("BNC "); + if (GetBit(Word,ee_PortAUI)) printk("AUI "); + printk("port(s) \n"); + + Word=read_eeprom(ioaddr, 6); + printk("Word6:\n"); + printk(" Stepping: %d\n",Word & ee_StepMask); + printk(" BoardID: %d\n",Word>>ee_BoardID); + + Word=read_eeprom(ioaddr, 7); + printk("Word7:\n"); + printk(" INT to IRQ:\n"); + + for (i=0, j=0; i<15; i++) + if (GetBit(Word,i)) printk("INT%d -> IRQ %d; ",j++,i); + + printk("\n"); +} +#endif + /* This is the real probe routine. Linux has a history of friendly device probes on the ISA bus. A good device probes avoids doing writes, and verifies that the correct device exists and functions. */ -int +int eepro_probe1(struct device *dev, short ioaddr) { unsigned short station_addr[6], id, counter; @@ -405,22 +579,28 @@ station_addr[2] = read_eeprom(ioaddr, 4); /* Check the station address for the manufacturer's code */ - - if ((station_addr[2] == 0x00aa) && (station_addr[1]!= 0x00c9)) { +#if NET_DEBUG > 3 + if (net_debug>3) + printEEPROMInfo(ioaddr); +#endif + if ((station_addr[2] == 0x00aa) && (station_addr[1] != 0x00c9)) { eepro = 1; printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", dev->name, ioaddr); - } else - if ( (station_addr[2] == 0x00a0) - || ((station_addr[2] == 0x00aa) && (station_addr[1] == 0x00c9) )) { + } + + else if ( (station_addr[2] == 0x00a0) + || ( (station_addr[2] == 0x00aa) + && (station_addr[1] == 0x00c9) )) { eepro = 2; printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", - dev->name, ioaddr); + dev->name, ioaddr); } + else { eepro = 0; printk("%s: Intel 82595-based lan card at %#x,", - dev->name, ioaddr); + dev->name, ioaddr); } /* Fill in the 'dev' fields. */ @@ -497,9 +677,6 @@ dev->name); } - if (net_debug) - printk(version); - /* Grab the region so we can find another board if autoIRQ fails. */ request_region(ioaddr, EEPRO_IO_EXTENT, "eepro"); @@ -522,10 +699,13 @@ outb(RESET_CMD, ioaddr); /* RESET the 82595 */ + if (net_debug) + printk("EEPRO Initialized\n%s", eepro_version); + return 0; } else return ENODEV; - } + } else if (net_debug > 3) printk ("EtherExpress Pro probed failed!\n"); return ENODEV; @@ -552,20 +732,20 @@ /* Enable the interrupt line. */ temp_reg = inb(ioaddr + REG1); - outb(temp_reg | INT_ENABLE, ioaddr + REG1); - + outb(temp_reg | INT_ENABLE, ioaddr + REG1); + outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */ /* clear all interrupts */ - outb(ALL_MASK, ioaddr + STATUS_REG); + outb(ALL_MASK, ioaddr + STATUS_REG); /* Let EXEC event to interrupt */ - outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG); + outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG); do { outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ temp_reg = inb(ioaddr + INT_NO_REG); - outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG); + outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ if (request_irq (*irqp, NULL, 0, "bogus", NULL) != EBUSY) { /* Twinkle the interrupt, and check if it's seen */ @@ -573,8 +753,10 @@ outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */ if (*irqp == autoirq_report(2) && /* It's a good IRQ line */ - (request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", NULL) == 0)) + (request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", + NULL) == 0)) break; + /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); } @@ -783,25 +965,25 @@ if (dev->tbusy) { /* If we get here, some higher level has decided we are broken. There should really be a "kick me" function call instead. */ - + int tickssofar = jiffies - dev->trans_start; - + if (tickssofar < 40) return 1; - + if (net_debug > 1) printk("%s: transmit timed out, %s?\n", dev->name, "network cable problem"); - + lp->stats.tx_errors++; - + /* Try to restart the adaptor. */ outb(SEL_RESET_CMD, ioaddr); - + /* We are supposed to wait for 2 us after a SEL_RESET */ SLOW_DOWN_IO; SLOW_DOWN_IO; - + /* Do I also need to flush the transmit buffers here? YES? */ lp->tx_start = lp->tx_end = rcv_ram; lp->tx_last = 0; @@ -810,18 +992,18 @@ dev->trans_start = jiffies; outb(RCV_ENABLE_CMD, ioaddr); } - + /* If some higher layer thinks we've missed an tx-done interrupt we are passed NULL. Caution: dev_tint() handles the cli()/sti() itself. */ - + if (skb == NULL) { dev_tint(dev); return 0; } - + /* Block a timer-based transmit from overlapping. */ - + if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { @@ -830,12 +1012,12 @@ hardware_send_packet(dev, buf, length); dev->trans_start = jiffies; } - + dev_kfree_skb (skb, FREE_WRITE); - + /* You might need to clean up and record Tx statistics here. */ /* lp->stats.tx_aborted_errors++; */ - + if (net_debug > 5) printk("eepro: exiting eepro_send_packet routine.\n"); @@ -858,35 +1040,40 @@ printk ("eepro_interrupt(): irq %d for unknown device.\n", irq); return; } - + dev->interrupt = 1; ioaddr = dev->base_addr; - + do { status = inb(ioaddr + STATUS_REG); if (status & RX_INT) { if (net_debug > 4) printk("eepro: packet received interrupt.\n"); + /* Acknowledge the RX_INT */ outb(RX_INT, ioaddr + STATUS_REG); + /* Get the received packets */ eepro_rx(dev); } + else if (status & TX_INT) { if (net_debug > 4) printk("eepro: packet transmit interrupt.\n"); + /* Acknowledge the TX_INT */ outb(TX_INT, ioaddr + STATUS_REG); + /* Process the status of transmitted packets */ eepro_transmit_interrupt(dev); } } while ((boguscount-- > 0) && (status & 0x06)); - + dev->interrupt = 0; - + if (net_debug > 5) printk("eepro: exiting eepro_interrupt routine.\n"); @@ -903,39 +1090,39 @@ dev->tbusy = 1; dev->start = 0; - + outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */ - + /* Disable the physical interrupt line. */ temp_reg = inb(ioaddr + REG1); outb(temp_reg & 0x7f, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ - + /* Flush the Tx and disable Rx. */ outb(STOP_RCV_CMD, ioaddr); - + lp->tx_start = lp->tx_end = rcv_ram ; lp->tx_last = 0; - + /* Mask all the interrupts. */ outb(ALL_MASK, ioaddr + INT_MASK_REG); - + /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); - + /* Reset the 82595 */ outb(RESET_CMD, ioaddr); - + /* release the interrupt */ free_irq(dev->irq, NULL); irq2dev_map[dev->irq] = 0; - + /* Update the statistics here. What statistics? */ /* We are supposed to wait for 200 us after a RESET */ SLOW_DOWN_IO; SLOW_DOWN_IO; /* May not be enough? */ MOD_DEC_USE_COUNT; - + return 0; } @@ -958,7 +1145,7 @@ short ioaddr = dev->base_addr; unsigned short mode; struct dev_mc_list *dmi=dev->mc_list; - + if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63) { /* @@ -976,7 +1163,7 @@ outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ printk("%s: promiscuous mode enabled.\n", dev->name); } - + else if (dev->mc_count==0 ) { outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ @@ -986,7 +1173,7 @@ outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */ } - + else { unsigned short status, *eaddrs; @@ -1007,7 +1194,7 @@ outw(0, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); outw(6*(dev->mc_count + 1), ioaddr + IO_PORT); - + for (i = 0; i < dev->mc_count; i++) { eaddrs=(unsigned short *)dmi->dmi_addr; @@ -1016,17 +1203,17 @@ outw(*eaddrs++, ioaddr + IO_PORT); outw(*eaddrs++, ioaddr + IO_PORT); } - + eaddrs = (unsigned short *) dev->dev_addr; outw(eaddrs[0], ioaddr + IO_PORT); outw(eaddrs[1], ioaddr + IO_PORT); outw(eaddrs[2], ioaddr + IO_PORT); outw(lp->tx_end, ioaddr + XMT_BAR); outb(MC_SETUP, ioaddr); - + /* Update the transmit queue */ i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1); - + if (lp->tx_start != lp->tx_end) { /* update the next address and the chain bit in the @@ -1041,17 +1228,17 @@ else { lp->tx_start = lp->tx_end = i ; } - + /* Acknowledge that the MC setup is done */ do { /* We should be doing this in the eepro_interrupt()! */ SLOW_DOWN_IO; SLOW_DOWN_IO; - + if (inb(ioaddr + STATUS_REG) & 0x08) { i = inb(ioaddr); outb(0x08, ioaddr + STATUS_REG); - + if (i & 0x20) { /* command ABORTed */ printk("%s: multicast setup failed.\n", dev->name); @@ -1063,7 +1250,7 @@ } } } while (++boguscount < 100); - + /* Re-enable RX and TX interrupts */ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); @@ -1127,47 +1314,48 @@ if (net_debug > 5) printk("eepro: entering hardware_send_packet routine.\n"); - + while (boguscount-- > 0) { - + /* Disable RX and TX interrupts. Necessary to avoid corruption of the HOST_ADDRESS_REG by interrupt service routines. */ outb(ALL_MASK, ioaddr + INT_MASK_REG); - + if (dev->interrupt == 1) { /* Enable RX and TX interrupts */ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); continue; } - + /* determine how much of the transmit buffer space is available */ if (lp->tx_end > lp->tx_start) tx_available = XMT_RAM - (lp->tx_end - lp->tx_start); else if (lp->tx_end < lp->tx_start) tx_available = lp->tx_start - lp->tx_end; else tx_available = XMT_RAM; - + if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) /* No space available ??? */ { eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */ + /* Enable RX and TX interrupts */ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); continue; } - + last = lp->tx_end; end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; + if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */ - + if ((RAM_SIZE - last) <= XMT_HEADER) { /* Arrrr!!!, must keep the xmt header together, several days were lost to chase this one down. */ last = rcv_ram; end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; } - else end = rcv_ram + (end - RAM_SIZE); } @@ -1176,20 +1364,20 @@ outw(0, ioaddr + IO_PORT); outw(end, ioaddr + IO_PORT); outw(length, ioaddr + IO_PORT); - + if (lp->version == LAN595) outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1); - + else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */ unsigned short temp = inb(ioaddr + INT_MASK_REG); outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG); outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2); outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG); } - + /* A dummy read to flush the DRAM write pipeline */ status = inw(ioaddr + IO_PORT); - + if (lp->tx_start == lp->tx_end) { outw(last, ioaddr + XMT_BAR); outb(XMT_CMD, ioaddr); @@ -1203,31 +1391,32 @@ outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); outw(last, ioaddr + IO_PORT); } - + outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); status = inw(ioaddr + IO_PORT); outw(status | CHAIN_BIT, ioaddr + IO_PORT); - + /* Continue the transmit command */ outb(RESUME_XMT_CMD, ioaddr); } lp->tx_last = last; lp->tx_end = end; - + /* Enable RX and TX interrupts */ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); if (dev->tbusy) { dev->tbusy = 0; } - + if (net_debug > 5) printk("eepro: exiting hardware_send_packet routine.\n"); - + return; } + dev->tbusy = 1; - + if (net_debug > 5) printk("eepro: exiting hardware_send_packet routine.\n"); } @@ -1246,68 +1435,68 @@ /* Set the read pointer to the start of the RCV */ outw(rcv_car, ioaddr + HOST_ADDRESS_REG); - + rcv_event = inw(ioaddr + IO_PORT); while (rcv_event == RCV_DONE) { rcv_status = inw(ioaddr + IO_PORT); rcv_next_frame = inw(ioaddr + IO_PORT); rcv_size = inw(ioaddr + IO_PORT); - + if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) { - + /* Malloc up new buffer. */ struct sk_buff *skb; rcv_size &= 0x3fff; skb = dev_alloc_skb(rcv_size+5); - + if (skb == NULL) { printk("%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; break; } - + skb->dev = dev; skb_reserve(skb,2); - + if (lp->version == LAN595) insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1); - + else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */ unsigned short temp = inb(ioaddr + INT_MASK_REG); outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG); insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), (rcv_size + 3) >> 2); outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG); } - + skb->protocol = eth_type_trans(skb,dev); netif_rx(skb); lp->stats.rx_packets++; } - + else { /* Not sure will ever reach here, I set the 595 to discard bad received frames */ lp->stats.rx_errors++; - + if (rcv_status & 0x0100) lp->stats.rx_over_errors++; - + else if (rcv_status & 0x0400) lp->stats.rx_frame_errors++; - + else if (rcv_status & 0x0800) lp->stats.rx_crc_errors++; - + printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size); } - + if (rcv_status & 0x1000) lp->stats.rx_length_errors++; - + if (--boguscount == 0) break; - + rcv_car = lp->rx_start + RCV_HEADER + rcv_size; lp->rx_start = rcv_next_frame; outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG); @@ -1315,9 +1504,9 @@ } if (rcv_car == 0) rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff; - + outw(rcv_car - 1, ioaddr + RCV_STOP); - + if (net_debug > 5) printk("eepro: exiting eepro_rx routine.\n"); } @@ -1331,17 +1520,17 @@ short xmt_status; while (lp->tx_start != lp->tx_end) { - + outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); xmt_status = inw(ioaddr+IO_PORT); - + if ((xmt_status & TX_DONE_BIT) == 0) break; - + xmt_status = inw(ioaddr+IO_PORT); lp->tx_start = inw(ioaddr+IO_PORT); dev->tbusy = 0; mark_bh(NET_BH); - + if (xmt_status & 0x2000) lp->stats.tx_packets++; else { @@ -1351,15 +1540,15 @@ printk("%s: XMT status = %#x\n", dev->name, xmt_status); } - + if (xmt_status & 0x000f) { lp->stats.collisions += (xmt_status & 0x000f); } - + if ((xmt_status & 0x0040) == 0x0) { lp->stats.tx_heartbeat_errors++; } - + if (--boguscount == 0) break; } @@ -1373,11 +1562,17 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, eepro_probe }; -static int io = 0x200; + +#ifdef PnPWakeup +static int io = 0x210; /*: default for PnP enabled FX chips */ +/* static int SetIO = 0x210; */ +#else +static int io = 0x200; /* Why? */ +#endif static int irq = 0; static int mem = (RCV_RAM/1024); /* Size of the rx buffer in KB */ -int +int init_module(void) { if (io == 0) | |