📄 dec21041.c
字号:
#include <bios/types.h>#include <bios/malloc.h>#include <bios/netdev.h>#include <bios/string.h>#include <bios/pci.h>#include <bios/if_ether.h>#include <bios/stdio.h>struct netdev net_dev_dec_21041;extern const struct trans_ops eth_trans_ops;#define virt_to_bus(x) ((int)(x) + 0x10000000)#define inw(x) pci_io_read_word(nd->io_base + (x))#define outw(w,x) pci_io_write_word((w), nd->io_base + (x))#define inl(x) pci_io_read_long(nd->io_base + (x))#define outl(w,x) pci_io_write_long((w), nd->io_base + (x))#define RECVBUFFERSZ 1600static volatile unsigned int recvdesc[4];static volatile unsigned int transdesc[4];static unsigned short pci_ids[] = { 0x0014, 0x0019 };struct nd_21041_priv { unsigned long csr14; unsigned long csr15; unsigned long csr13; unsigned long csr6; char recvbuffer[RECVBUFFERSZ];};static int nd_21041_probe(void){ struct netdev *nd = &net_dev_dec_21041; struct pci_dev *dev; struct nd_21041_priv *ndp; int i; for (i = 0; i < sizeof(pci_ids) / sizeof(pci_ids[0]); i++) { dev = pci_lookup_vendor_device(NULL, 0x1011, pci_ids[i]); if (!dev) continue; if (pci_enable(dev)) continue; if (pci_set_master(dev)) continue; nd->io_base = dev->bar[0] & ~3; ndp = nd->ptr1 = malloc(sizeof(*ndp)); nd->hw_addr[0] = 0x45; /* E */ nd->hw_addr[1] = 0x42; /* B */ nd->hw_addr[2] = 0x53; /* S */ nd->hw_addr[3] = 0x41; /* A */ nd->hw_addr[4] = 0x44; /* D */ nd->hw_addr[5] = 0x47; /* G */ /* read h/w address */ nd->hw_addr_len = 6; printf(" net: DEC21041 at %04x, ether address 45:42:53:41:44:47\n", nd->io_base); switch (pci_ids[i]) { case 0x0014: /* 21041 */ ndp->csr14 = 0x0000f7fd; ndp->csr15 = 0x00000006; ndp->csr13 = 0x0000ef09; ndp->csr6 = 0x80020000; break; case 0x0019: /* 21143 */ ndp->csr14 = 0x0000ffff; ndp->csr15 = 0x00000008; ndp->csr13 = 0x000e0001; ndp->csr6 = 0x82020000; break; } } return nd->io_base ? 0 : -1;}static int nd_21041_setmedia(struct netdev *nd, media_t media){ return 0;}static int nd_21041_checkmedia(struct netdev *nd){ return 0;}static int nd_21041_open(struct netdev *nd){ struct nd_21041_priv *ndp = nd->ptr1; unsigned int setupframe[3*16]; int i; /* CSR0 - mus mode reg * no transmit poll, 16 lword burst, 8 word cache align, little endian */ outl(0x5006, 0); /* CSR7 - interrupt mask reg * no interrupts thanks */ outl(0, 0x38); /* Disable SIA */ outl(0, 0x68); /* From table 3-64 on p.94 of the 21041 hardware ref manual * Use ef09,f7fd,0006 for 10base2 (Auto Negotiation) - seems to work for b2 * Use ef01,ffff,0008 for 10baseT (Auto Negotiation) - seems to work for bT * Use ef09,0705,0006 for 10base2 (Auto sensing and negotiation disabled) - seems to work for b2 * Hang on - if its auto neg why the difference? * We have to see if there is a link beat and if missing try the other */ /* CSR14 - SIA transmit/receive */ outl(ndp->csr14, 0x70); /* CSR15 - SIA general */ outl(ndp->csr15, 0x78); /* CSR13 connectivity reg * (must do last) */ outl(ndp->csr13, 0x68); for (i = 0; i < 3*8; i += 3) { setupframe[i] = nd->hw_addr[0] | nd->hw_addr[1] << 8; setupframe[i + 1] = nd->hw_addr[2] | nd->hw_addr[3] << 8; setupframe[i + 2] = nd->hw_addr[4] | nd->hw_addr[5] << 8; } transdesc[0] = 0x80000000; /* TDES0 - 21041 owns the descriptor */ transdesc[1] = 0x0b0000c0; /* TDES1 - End of ring, chained 2nd desc, setup, size of frame */ transdesc[2] = virt_to_bus(setupframe); /* TDES2 - buffer 1 address */ transdesc[3] = virt_to_bus(transdesc); /* TDES3 - next descriptor is same descriptor */ outl(virt_to_bus(transdesc), 0x20); /* CSR6 - operating mode * kick the transmitter to process the setup frame * Enable special capture mode, bit17 enable capture mode, * large transmit threshold, enable transmit */ outl(ndp->csr6 | 0xe000, 0x30); while (transdesc[0] & 0x80000000); /* RDES1 - end of ting, second address chained, sizeof buffer */ recvdesc[1] = 0x03000000 | RECVBUFFERSZ; /* RDES2 - buffer address */ recvdesc[2] = virt_to_bus(ndp->recvbuffer); /* RDES3 - next descriptor is same descriptor */ recvdesc[3] = virt_to_bus(recvdesc); /* First/last descriptor, let 21041 own it */ recvdesc[0] = 0x80000300; /* CSR3 - receive list base address reg */ outl(virt_to_bus(recvdesc), 0x18); /* Stop transmitter and start receiver * - As above, but no transmit enable, start receiver */ outl(ndp->csr6 | 0xc002, 0x30); return 0;}static int nd_21041_close(struct netdev *nd){ return 0;}static int nd_21041_status(struct netdev *nd){ return 0;}static int nd_21041_send(struct netdev *nd, void *buffer, int size){ struct nd_21041_priv *ndp = nd->ptr1; transdesc[0] = 0x80000000; transdesc[1] = size | 0x63000000; transdesc[2] = virt_to_bus(buffer); transdesc[3] = virt_to_bus(transdesc); /* CSR4 - transmit list base address */ outl(virt_to_bus(transdesc), 0x20); /* CSR6 - operating mode * setup operating mode and kick transmitter * - enable special capture, bit17 enable capture mode, * large transmit threshold, enable transmit */ outl(ndp->csr6 | 0xe002, 0x30); /* Spin waiting for the end of the transmission */ while (transdesc[0] & 0x80000000); /* CSR6 - operating mode * stop the transmitter and start receiver */ outl(ndp->csr6 | 0xc002, 0x30); return 0;}static int nd_21041_recv(struct netdev *nd, void *buf){ struct nd_21041_priv *ndp = nd->ptr1; int len = 0; switch (recvdesc[0] & 0x80008000) { case 0: len = (recvdesc[0] >> 16) & 0x7fff; memcpy(buf, ndp->recvbuffer, len); case 0x8000: /* error */ /* RDES1 - end of ting, second address chained, sizeof buffer */ recvdesc[1] = 0x03000000 | RECVBUFFERSZ; /* RDES2 - buffer address */ recvdesc[2] = virt_to_bus(ndp->recvbuffer); /* RDES3 - next descriptor is same descriptor */ recvdesc[3] = virt_to_bus(recvdesc); /* First/last descriptor, let 21041 own it */ recvdesc[0] = 0x80000300; default: break; } /* CSR6 - operating mode * make sure that the receiver is running */ outl(ndp->csr6 | 0xc002, 0x30); return len;}static const struct netdev_ops nd_21041_ops = { nd_21041_probe, nd_21041_open, nd_21041_close, nd_21041_status, nd_21041_setmedia, nd_21041_checkmedia, nd_21041_send, nd_21041_recv,};struct netdev net_dev_dec_21041 = { &nd_21041_ops, ð_trans_ops,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -