aboutsummaryrefslogtreecommitdiff
path: root/netboot/otulip.c
diff options
context:
space:
mode:
Diffstat (limited to 'netboot/otulip.c')
-rw-r--r--netboot/otulip.c374
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;
-}