diff options
Diffstat (limited to 'netboot/otulip.c')
-rw-r--r-- | netboot/otulip.c | 374 |
1 files changed, 0 insertions, 374 deletions
diff --git a/netboot/otulip.c b/netboot/otulip.c deleted file mode 100644 index ea2b19b..0000000 --- a/netboot/otulip.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - Etherboot DEC Tulip driver - adapted by Ken Yap from - - FreeBSD netboot DEC 21143 driver - - Author: David Sharp - date: Nov/98 - - Known to work on DEC DE500 using 21143-PC chipset. - Even on cards with the same chipset there can be - incompatablity problems with the way media selection - and status LED settings are done. See comments below. - - Some code fragments were taken from verious places, - Ken Yap's etherboot, FreeBSD's if_de.c, and various - Linux related files. DEC's manuals for the 21143 and - SROM format were very helpful. The Linux de driver - development page has a number of links to useful - related information. Have a look at: - ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html - -*/ - -#include "etherboot.h" -#include "nic.h" -#include "pci.h" -#include "cards.h" -#include "otulip.h" - -static unsigned short vendor, dev_id; -static unsigned short ioaddr; -static unsigned int *membase; -static unsigned char srom[1024]; - -#define BUFLEN 1536 /* must be longword divisable */ - /* buffers must be longword aligned */ - -/* transmit descriptor and buffer */ -static struct txdesc txd; - -/* receive descriptor(s) and buffer(s) */ -#define NRXD 4 -static struct rxdesc rxd[NRXD]; -static int rxd_tail = 0; -#ifdef USE_LOWMEM_BUFFER -#define rxb ((char *)0x10000 - NRXD * BUFLEN) -#define txb ((char *)0x10000 - NRXD * BUFLEN - BUFLEN) -#else -static unsigned char rxb[NRXD * BUFLEN]; -static unsigned char txb[BUFLEN]; -#endif - -static unsigned char ehdr[ETH_HLEN]; /* buffer for ethernet header */ - -enum tulip_offsets { - CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28, - CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58, - CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78 }; - - -/***************************************************************************/ -/* 21143 specific stuff */ -/***************************************************************************/ - -/* XXX assume 33MHz PCI bus, this is not very accurate and should be - used only with gross over estimations of required delay times unless - you tune UADJUST to your specific processor and I/O subsystem */ - -#define UADJUST 870 -static void udelay(unsigned long usec) { - unsigned long i; - for (i=((usec*UADJUST)/33)+1; i>0; i--) (void) TULIP_CSR_READ(csr_0); -} - -/* The following srom related code was taken from FreeBSD's if_de.c */ -/* with minor alterations to make it work here. the Linux code is */ -/* better but this was easier to use */ - -static void delay_300ns(void) -{ - int idx; - for (idx = (300 / 33) + 1; idx > 0; idx--) - (void) TULIP_CSR_READ(csr_busmode); -} - -#define EMIT do { TULIP_CSR_WRITE(csr_srom_mii, csr); delay_300ns(); } while (0) - -static void srom_idle(void) -{ - unsigned bit, csr; - - csr = SROMSEL ; EMIT; - csr = SROMSEL | SROMRD; EMIT; - csr ^= SROMCS; EMIT; - csr ^= SROMCLKON; EMIT; - /* - * Write 25 cycles of 0 which will force the SROM to be idle. - */ - for (bit = 3 + SROM_BITWIDTH + 16; bit > 0; bit--) { - csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */ - csr ^= SROMCLKON; EMIT; /* clock high; data valid */ - } - csr ^= SROMCLKOFF; EMIT; - csr ^= SROMCS; EMIT; - csr = 0; EMIT; -} - -static void srom_read(void) -{ - unsigned idx; - const unsigned bitwidth = SROM_BITWIDTH; - const unsigned cmdmask = (SROMCMD_RD << bitwidth); - const unsigned msb = 1 << (bitwidth + 3 - 1); - unsigned lastidx = (1 << bitwidth) - 1; - - srom_idle(); - - for (idx = 0; idx <= lastidx; idx++) { - unsigned lastbit, data, bits, bit, csr; - csr = SROMSEL ; EMIT; - csr = SROMSEL | SROMRD; EMIT; - csr ^= SROMCSON; EMIT; - csr ^= SROMCLKON; EMIT; - - lastbit = 0; - for (bits = idx|cmdmask, bit = bitwidth + 3; bit > 0; bit--, bits <<= 1) - { - const unsigned thisbit = bits & msb; - csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */ - if (thisbit != lastbit) { - csr ^= SROMDOUT; EMIT; /* clock low; invert data */ - } else { - EMIT; - } - csr ^= SROMCLKON; EMIT; /* clock high; data valid */ - lastbit = thisbit; - } - csr ^= SROMCLKOFF; EMIT; - - for (data = 0, bits = 0; bits < 16; bits++) { - data <<= 1; - csr ^= SROMCLKON; EMIT; /* clock high; data valid */ - data |= TULIP_CSR_READ(csr_srom_mii) & SROMDIN ? 1 : 0; - csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */ - } - srom[idx*2] = data & 0xFF; - srom[idx*2+1] = data >> 8; - csr = SROMSEL | SROMRD; EMIT; - csr = 0; EMIT; - } - srom_idle(); -} - -/************************************************************************** -ETH_RESET - Reset adapter -***************************************************************************/ -static void tulip_reset(struct nic *nic) -{ - int x,cnt=2; - - outl(0x00000001, ioaddr + CSR0); - udelay(1000); - /* turn off reset and set cache align=16lword, burst=unlimit */ - outl(0x01A08000, ioaddr + CSR0); - - /* for some reason the media selection does not take - the first time se it is repeated. */ - - while(cnt--) { - /* stop TX,RX processes */ - if (cnt == 1) - outl(0x32404000, ioaddr + CSR6); - else - outl(0x32000040, ioaddr + CSR6); - - /* XXX - media selection is vendor specific and hard coded right - here. This should be fixed to use the hints in the SROM and - allow media selection by the user at runtime. MII support - should also be added. Support for chips other than the - 21143 should be added here as well */ - - /* start set to 10Mbps half-duplex */ - - /* setup SIA */ - outl(0x0, ioaddr + CSR13); /* reset SIA */ - outl(0x7f3f, ioaddr + CSR14); - outl(0x8000008, ioaddr + CSR15); - outl(0x0, ioaddr + CSR13); - outl(0x1, ioaddr + CSR13); - outl(0x2404000, ioaddr + CSR6); - - /* initalize GP */ - outl(0x8af0008, ioaddr + CSR15); - outl(0x50008, ioaddr + CSR15); - - /* end set to 10Mbps half-duplex */ - - if (vendor == PCI_VENDOR_ID_MACRONIX && dev_id == PCI_DEVICE_ID_MX987x5) { - /* do stuff for MX98715 */ - outl(0x01a80000, ioaddr + CSR6); - outl(0xFFFFFFFF, ioaddr + CSR14); - outl(0x00001000, ioaddr + CSR12); - } - - outl(0x0, ioaddr + CSR7); /* disable interrupts */ - - /* construct setup packet which is used by the 21143 to - program its CAM to recognize interesting MAC addresses */ - - memset(&txd, 0, sizeof(struct txdesc)); - txd.buf1addr = &txb[0]; - txd.buf2addr = &txb[0]; /* just in case */ - txd.buf1sz = 192; /* setup packet must be 192 bytes */ - txd.buf2sz = 0; - txd.control = 0x020; /* setup packet */ - txd.status = 0x80000000; /* give ownership to 21143 */ - - /* construct perfect filter frame */ - /* with mac address as first match */ - /* and broadcast address for all others */ - - for(x=0;x<192;x++) txb[x] = 0xff; - txb[0] = nic->node_addr[0]; - txb[1] = nic->node_addr[1]; - txb[4] = nic->node_addr[2]; - txb[5] = nic->node_addr[3]; - txb[8] = nic->node_addr[4]; - txb[9] = nic->node_addr[5]; - outl((unsigned long)&txd, ioaddr + CSR4); /* set xmit buf */ - outl(0x2406000, ioaddr + CSR6); /* start transmiter */ - - udelay(50000); /* wait for the setup packet to be processed */ - - } - - /* setup receive descriptor */ - { - int x; - for(x=0;x<NRXD;x++) { - memset(&rxd[x], 0, sizeof(struct rxdesc)); - rxd[x].buf1addr = &rxb[x * BUFLEN]; - rxd[x].buf2addr = 0; /* not used */ - rxd[x].buf1sz = BUFLEN; - rxd[x].buf2sz = 0; /* not used */ - rxd[x].control = 0x0; - rxd[x].status = 0x80000000; /* give ownership it to 21143 */ - } - rxd[NRXD - 1].control = 0x008; /* Set Receive end of ring on la -st descriptor */ - rxd_tail = 0; - } - - /* tell DC211XX where to find rx descriptor list */ - outl((unsigned long)&rxd[0], ioaddr + CSR3); - /* start the receiver */ - outl(0x2406002, ioaddr + CSR6); - -} - -/************************************************************************** -ETH_TRANSMIT - Transmit a frame -***************************************************************************/ -static const char padmap[] = { - 0, 3, 2, 1}; - -static void tulip_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p) -{ - unsigned long time; - - /* setup ethernet header */ - - memcpy(ehdr, d, ETH_ALEN); - memcpy(&ehdr[ETH_ALEN], nic->node_addr, ETH_ALEN); - ehdr[ETH_ALEN*2] = (t >> 8) & 0xff; - ehdr[ETH_ALEN*2+1] = t & 0xff; - - /* setup the transmit descriptor */ - - memset(&txd, 0, sizeof(struct txdesc)); - - txd.buf1addr = &ehdr[0]; /* ethernet header */ - txd.buf1sz = ETH_HLEN; - - txd.buf2addr = p; /* packet to transmit */ - txd.buf2sz = s; - - txd.control = 0x188; /* LS+FS+TER */ - - txd.status = 0x80000000; /* give it to 21143 */ - - outl(inl(ioaddr + CSR6) & ~0x00004000, ioaddr + CSR6); - outl((unsigned long)&txd, ioaddr + CSR4); - outl(inl(ioaddr + CSR6) | 0x00004000, ioaddr + CSR6); - -/* Wait for transmit to complete before returning. not well tested. - - time = currticks(); - while(txd.status & 0x80000000) { - if (currticks() - time > 20) { - printf("transmit timeout.\n"); - break; - } - } -*/ - -} - -/************************************************************************** -ETH_POLL - Wait for a frame -***************************************************************************/ -static int tulip_poll(struct nic *nic) -{ - if (rxd[rxd_tail].status & 0x80000000) return 0; - - nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16; - - /* copy packet to working buffer */ - /* XXX - this copy could be avoided with a little more work - but for now we are content with it because the optimised - memcpy(, , ) is quite fast */ - - memcpy(nic->packet, rxb + rxd_tail * BUFLEN, nic->packetlen); - - /* return the descriptor and buffer to recieve ring */ - rxd[rxd_tail].status = 0x80000000; - rxd_tail++; - if (rxd_tail == NRXD) rxd_tail = 0; - - return 1; -} - -static void tulip_disable(struct nic *nic) -{ - /* nothing for the moment */ -} - -/************************************************************************** -ETH_PROBE - Look for an adapter -***************************************************************************/ -struct nic *otulip_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci) -{ - int i; - - if (io_addrs == 0 || *io_addrs == 0) - return (0); - vendor = pci->vendor; - dev_id = pci->dev_id; - ioaddr = *io_addrs; - membase = (unsigned int *)pci->membase; - - /* wakeup chip */ - pcibios_write_config_dword(pci->bus,pci->devfn,0x40,0x00000000); - - /* Stop the chip's Tx and Rx processes. */ - /* outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6); */ - /* Clear the missed-packet counter. */ - /* (volatile int)inl(ioaddr + CSR8); */ - - srom_read(); - - for (i=0; i < ETH_ALEN; i++) - nic->node_addr[i] = srom[20+i]; - - printf("Tulip %! at ioaddr %#hX\n", nic->node_addr, ioaddr); - - tulip_reset(nic); - - nic->reset = tulip_reset; - nic->poll = tulip_poll; - nic->transmit = tulip_transmit; - nic->disable = tulip_disable; - return nic; -} |