mirror of
https://git.savannah.gnu.org/git/grub.git
synced 2026-10-21 14:59:34 +00:00
add missing files.
This commit is contained in:
1 parent
9fe0449a36
commit
ef1679fa92
17 files changed
+8030
No files matched your search
+380
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
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 "tulip.h"
|
||||
|
||||
static unsigned short vendor, dev_id;
|
||||
static unsigned short ioaddr;
|
||||
static unsigned int *membase;
|
||||
static unsigned long devfn;
|
||||
static unsigned char srom[1024];
|
||||
|
||||
#define BUFLEN 1600 /* must be longword divisable */
|
||||
/* buffers must be longword aligned */
|
||||
|
||||
/* transmit descriptor and buffer */
|
||||
static struct txrxdesc txd;
|
||||
static unsigned char txb[BUFLEN];
|
||||
|
||||
/* receive descriptor(s) and buffer(s) */
|
||||
#define NRXD 4
|
||||
static struct txrxdesc rxd[NRXD];
|
||||
static int rxd_tail = 0;
|
||||
static unsigned char rxb[NRXD][BUFLEN];
|
||||
|
||||
static unsigned char ehdr[ETHER_HDR_SIZE]; /* 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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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;
|
||||
unsigned long csr6,csr15;
|
||||
|
||||
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 txrxdesc));
|
||||
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 txrxdesc));
|
||||
rxd[x].buf1addr = &rxb[x][0];
|
||||
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, char *d, unsigned int t, unsigned int s, char *p)
|
||||
{
|
||||
unsigned int len;
|
||||
int pad;
|
||||
int status;
|
||||
unsigned char c;
|
||||
unsigned long time;
|
||||
|
||||
/* setup ethernet header */
|
||||
|
||||
memcpy(ehdr, d, ETHER_ADDR_SIZE);
|
||||
memcpy(&ehdr[ETHER_ADDR_SIZE], nic->node_addr, ETHER_ADDR_SIZE);
|
||||
ehdr[ETHER_ADDR_SIZE*2] = (t >> 8) & 0xff;
|
||||
ehdr[ETHER_ADDR_SIZE*2+1] = t & 0xff;
|
||||
|
||||
/* setup the transmit descriptor */
|
||||
|
||||
memset(&txd, 0, sizeof(struct txrxdesc));
|
||||
|
||||
txd.buf1addr = &ehdr[0]; /* ethernet header */
|
||||
txd.buf1sz = ETHER_HDR_SIZE;
|
||||
|
||||
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)
|
||||
{
|
||||
/* common variables */
|
||||
unsigned short type = 0;
|
||||
int x;
|
||||
|
||||
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][0], 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 *tulip_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(0,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 < 6; i++)
|
||||
nic->node_addr[i] = srom[20+i];
|
||||
|
||||
printf("Tulip %b:%b:%b:%b:%b:%b at ioaddr 0x%x\n",
|
||||
srom[20],srom[21],srom[22],srom[23],srom[24],srom[25],
|
||||
ioaddr);
|
||||
|
||||
tulip_reset(nic);
|
||||
|
||||
nic->reset = tulip_reset;
|
||||
nic->poll = tulip_poll;
|
||||
nic->transmit = tulip_transmit;
|
||||
nic->disable = tulip_disable;
|
||||
return nic;
|
||||
}
|
||||
Reference in new issue
Block a user