Warning, cross-references for /kernel/drivers/net/pcnet.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include "drivers/pci/pci.h"
0021 #include "drivers/net/pcnet.h"
0022 #include "arch/i386.h"
0023 #include "util/printf.h"
0024 #include "smp/smp.h"
0025 #include "smp/apic.h"
0026 #include "mem/physical.h"
0027 #include "mem/virtual.h"
0028 #include "kernel.h"
0029
0030 #define DEBUG_PCNET
0031
0032 #ifdef DEBUG_PCNET
0033 #define DLOG(fmt,...) DLOG_PREFIX("PCnet",fmt,##__VA_ARGS__)
0034 #else
0035 #define DLOG(fmt,...) ;
0036 #endif
0037
0038
0039
0040
0041
0042 #define NUM_RX_BUFFERS_LOG2 2
0043
0044 #define RX_RING_SIZE (1 << NUM_RX_BUFFERS_LOG2)
0045 #define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
0046 #define RX_RING_LEN_BITS ((NUM_RX_BUFFERS_LOG2) << 29)
0047 #define RX_RING_BUF_SIZE MAX_FRAME_SIZE
0048 #define TX_RING_BUF_SIZE MAX_FRAME_SIZE
0049
0050 #define PCNET_VECTOR 0x4B
0051
0052
0053
0054 #define CSR4_FEATURES 0x915
0055
0056
0057
0058
0059
0060
0061
0062 struct pcnet_init_block {
0063
0064 uint16 mode;
0065 uint8 _reserved1:4;
0066 uint8 rlen:4;
0067 uint8 _reserved2:4;
0068 uint8 tlen:4;
0069 uint8 phys_addr[ETH_ADDR_LEN];
0070 uint16 _reserved3;
0071 uint32 filter[2];
0072 uint32 rx_ring;
0073 uint32 tx_ring;
0074 } PACKED;
0075
0076 struct pcnet_rx_head {
0077
0078 union {
0079 uint32 raw;
0080 uint32 rbadr;
0081 } rmd0;
0082 union {
0083 uint32 raw;
0084 struct {
0085 sint16 buf_length;
0086 uint16 _reserved:4;
0087 uint16 bam:1;
0088 uint16 lafm:1;
0089 uint16 pam:1;
0090 uint16 bpe:1;
0091 uint16 enp:1;
0092 uint16 stp:1;
0093 uint16 buff:1;
0094 uint16 crc:1;
0095 uint16 oflo:1;
0096 uint16 fram:1;
0097 uint16 err:1;
0098 uint16 own:1;
0099 };
0100 } rmd1;
0101 union {
0102 uint32 raw;
0103 struct {
0104 uint16 msg_length;
0105 uint8 rpc;
0106 uint8 rcc;
0107 };
0108 } rmd2;
0109 uint32 _reserved;
0110 } PACKED;
0111
0112 struct pcnet_tx_head {
0113
0114 union {
0115 uint32 raw;
0116 uint32 tbadr;
0117 } rmd0;
0118 union {
0119 uint32 raw;
0120 struct {
0121 sint16 buf_length;
0122 uint16 _reserved:7;
0123 uint16 bpe:1;
0124 uint16 enp:1;
0125 uint16 stp:1;
0126
0127 uint16 flags:5;
0128 uint16 own:1;
0129 };
0130 } rmd1;
0131 union {
0132 uint32 raw;
0133 } rmd2;
0134 uint32 _reserved;
0135 } PACKED;
0136
0137 struct pcnet_interface {
0138 struct pcnet_rx_head rx_ring[RX_RING_SIZE];
0139 struct pcnet_tx_head tx_ring;
0140 struct pcnet_init_block init_block;
0141 uint8 rbuf[RX_RING_SIZE][RX_RING_BUF_SIZE] ALIGNED(16);
0142 uint8 tbuf[TX_RING_BUF_SIZE] ALIGNED(16);
0143 sint32 rx_idx;
0144 } PACKED;
0145
0146
0147
0148
0149 static struct { uint16 vendor, device; } compatible_ids[] = {
0150 { 0x1022, 0x2000 },
0151 { 0xFFFF, 0xFFFF }
0152 };
0153
0154
0155
0156 static uint device_index, io_base, irq_line, irq_pin, version;
0157
0158 static struct pcnet_interface* card;
0159 static uint card_phys, frame_count;
0160
0161
0162 #define V2P(ty,p) ((ty)((((uint) (p)) - ((uint) card))+card_phys))
0163
0164 #define P2V(ty,p) ((ty)((((uint) (p)) - card_phys)+((uint) card)))
0165
0166 static uint8 eth_addr[ETH_ADDR_LEN];
0167
0168
0169
0170
0171
0172 #define ETH (io_base+0x00)
0173 #define DATA (io_base+0x10)
0174 #define ADDR (io_base+0x12)
0175 #define RESET (io_base+0x14)
0176 #define BUS (io_base+0x16)
0177
0178
0179
0180 static bool
0181 probe (void)
0182 {
0183 uint i;
0184
0185
0186 outw (inw (RESET), RESET);
0187
0188
0189 outw (0, ADDR); (void) inw (ADDR);
0190 if (inw (DATA) != 4) {
0191 DLOG ("expected STOP bit set");
0192 return FALSE;
0193 }
0194
0195
0196 outw (20, ADDR); (void) inw (ADDR);
0197 outw (inw (BUS) | 0x102, BUS);
0198 outw (20, ADDR); (void) inw (ADDR);
0199 if ((inw (BUS) & 0x1FF) != 0x102) {
0200 DLOG ("SSIZE!=1 and SWSTYLE!=2 (BCR20=%p)", inw (BUS));
0201 return FALSE;
0202 }
0203
0204
0205 outw (88, ADDR);
0206 if (inw (ADDR) != 88) {
0207 DLOG ("Unsupported (ancient) chip");
0208 return FALSE;
0209 } else {
0210 version = inw (DATA);
0211 outw (89, ADDR); (void) inw (ADDR);
0212 version |= inw (DATA) << 16;
0213
0214 if ((version & 0xfff) != 3) {
0215 DLOG ("malformed version %p", version);
0216 return FALSE;
0217 }
0218
0219 version >>= 12;
0220 if (version != 0x2621) {
0221 DLOG ("version=%p is not supported", version);
0222 return FALSE;
0223 }
0224 }
0225
0226
0227 outw (4, ADDR); (void) inw (ADDR);
0228 outw (CSR4_FEATURES, DATA);
0229
0230
0231 outw (0, ADDR); (void) inw (ADDR);
0232
0233
0234 for (i=0; i< ETH_ADDR_LEN; i++)
0235 eth_addr[i] = inb (ETH+i);
0236
0237
0238 outw (2, ADDR); (void) inw (ADDR);
0239 outw (inw (BUS) | 2, BUS);
0240
0241 DLOG ("version=%p eth_addr=%.02x:%.02x:%.02x:%.02x:%.02x:%.02x",
0242 version,
0243 eth_addr[0], eth_addr[1], eth_addr[2],
0244 eth_addr[3], eth_addr[4], eth_addr[5]);
0245
0246 return TRUE;
0247 }
0248
0249 static void
0250 reset (void)
0251 {
0252 uint i, phys_init;
0253
0254 (void) inw (RESET);
0255
0256
0257 outw (2, ADDR); (void) inw (ADDR);
0258 outw (inw (BUS) | 2, BUS);
0259
0260
0261 for (i=0; i<ETH_ADDR_LEN; i++)
0262 card->init_block.phys_addr[i] = eth_addr[i];
0263
0264
0265 for (i=0; i<RX_RING_SIZE; i++) {
0266 card->rx_ring[i].rmd1.buf_length = -RX_RING_BUF_SIZE;
0267 card->rx_ring[i].rmd0.rbadr = V2P (uint32, card->rbuf[i]);
0268 card->rx_ring[i].rmd1.own = 1;
0269 }
0270 card->tx_ring.rmd1.buf_length = -TX_RING_BUF_SIZE;
0271 card->tx_ring.rmd0.tbadr = V2P (uint32, card->tbuf);
0272
0273 card->rx_idx = 0;
0274 card->init_block.mode = 0;
0275 card->init_block.filter[0] = card->init_block.filter[1] = 0;
0276
0277
0278 card->init_block.rx_ring = V2P (uint32, card->rx_ring);
0279 card->init_block.tx_ring = V2P (uint32, &card->tx_ring);
0280 card->init_block.rlen = NUM_RX_BUFFERS_LOG2;
0281 card->init_block.tlen = 0;
0282
0283 phys_init = V2P (uint, &card->init_block);
0284
0285 DLOG ("phys_init=%p rx_ring=%p tx_ring=%p rbuf[0]=%p tbuf=%p",
0286 phys_init, card->init_block.rx_ring, card->init_block.tx_ring,
0287 V2P (uint, card->rbuf[0]), V2P (uint, card->tbuf));
0288
0289 outw (0, ADDR); (void) inw (ADDR);
0290 outw (4, DATA);
0291
0292
0293
0294
0295 outw (1, ADDR); (void) inw (ADDR);
0296 outw ((uint16) phys_init, DATA);
0297
0298
0299 outw (2, ADDR); (void) inw (ADDR);
0300 outw ((uint16) (phys_init >> 16), DATA);
0301
0302
0303 outw (4, ADDR); (void) inw (ADDR);
0304 outw (CSR4_FEATURES, DATA);
0305
0306 outw (0, ADDR); (void) inw (ADDR);
0307 outw (1, DATA);
0308
0309
0310 for (i=10000; i > 0; i--)
0311 if (inw (DATA) & 0x100)
0312 break;
0313 if (i <= 0)
0314 DLOG ("reset: INIT timed out");
0315
0316 outw (0x142, DATA);
0317
0318
0319 DLOG ("reset: complete. CSR0=%p", inw (DATA));
0320 }
0321
0322 extern sint
0323 pcnet_transmit (uint8* buf, sint len)
0324 {
0325 DLOG ("pcnet_transmit (%p, %d)", buf, len);
0326 if (card->tx_ring.rmd1.own != 0) {
0327
0328 return 0;
0329 } else if (len > MAX_FRAME_SIZE) {
0330
0331 return -1;
0332 } else {
0333
0334 memcpy (card->tbuf, buf, len);
0335
0336 card->tx_ring.rmd1.buf_length = -len;
0337
0338 card->tx_ring.rmd2.raw = 0;
0339
0340 card->tx_ring.rmd1.stp = card->tx_ring.rmd1.enp = 1;
0341
0342 card->tx_ring.rmd1.own = 1;
0343
0344 outw (0, ADDR); (void) inw (ADDR);
0345 outw (0x48, DATA);
0346 }
0347 return len;
0348 }
0349
0350 static void
0351 pcnet_drop_packet (uint8* packet, uint len)
0352 {
0353 DLOG ("dropping packet (%p, %d)", packet, len);
0354 }
0355
0356 static ethernet_device pcnet_ethdev;
0357
0358 static void
0359 pcnet_poll (void)
0360 {
0361 uint32 entry;
0362 uint32* ptr;
0363
0364 entry = card->rx_idx & RX_RING_MOD_MASK;
0365
0366 while (card->rx_ring[entry].rmd1.own == 0) {
0367 if (card->rx_ring[entry].rmd1.enp == 1 &&
0368 card->rx_ring[entry].rmd1.stp == 1) {
0369
0370 ptr = P2V (uint32*, card->rx_ring[entry].rmd0.rbadr);
0371
0372 DLOG (" recv entry=%d rmd1=%p msglen=%x",
0373 entry, card->rx_ring[entry].rmd1.raw,
0374 card->rx_ring[entry].rmd2.msg_length);
0375 DLOG (" %.08X %.08X %.08X %.08X",
0376 ptr[0], ptr[1], ptr[2], ptr[3]);
0377
0378
0379 if (pcnet_ethdev.recv_func)
0380 pcnet_ethdev.recv_func (&pcnet_ethdev, (uint8*)ptr,
0381 card->rx_ring[entry].rmd2.msg_length);
0382 else
0383 pcnet_drop_packet ((uint8*)ptr, card->rx_ring[entry].rmd2.msg_length);
0384 } else {
0385
0386 DLOG (" recv error not full packet entry=%d rmd1=%p",
0387 entry, card->rx_ring[entry].rmd1.raw);
0388 }
0389
0390
0391 card->rx_ring[entry].rmd1.raw &= 0x030fffff;
0392
0393 card->rx_ring[entry].rmd2.raw = 0;
0394
0395 card->rx_ring[entry].rmd1.buf_length = -RX_RING_BUF_SIZE;
0396
0397 card->rx_ring[entry].rmd1.own = 1;
0398
0399
0400 entry = (++card->rx_idx) & RX_RING_MOD_MASK;
0401 }
0402 }
0403
0404 static void
0405 handle_rint (void)
0406 {
0407 DLOG ("IRQ: RINT rx_ring=%.01x %p %.01x %p %.01x %p %.01x %p",
0408 card->rx_ring[0].rmd1.own, card->rx_ring[0].rmd0.rbadr,
0409 card->rx_ring[1].rmd1.own, card->rx_ring[1].rmd0.rbadr,
0410 card->rx_ring[2].rmd1.own, card->rx_ring[2].rmd0.rbadr,
0411 card->rx_ring[3].rmd1.own, card->rx_ring[3].rmd0.rbadr);
0412
0413 pcnet_poll ();
0414 }
0415
0416 static void
0417 handle_tint (void)
0418 {
0419 DLOG ("IRQ: TINT tx_ring=%.01x %p",
0420 card->tx_ring.rmd1.own, card->tx_ring.rmd0.tbadr);
0421 }
0422
0423 static uint32
0424 pcnet_irq_handler (uint8 vec)
0425 {
0426 uint16 csr0;
0427 lock_kernel ();
0428
0429 outw (0, ADDR); (void) inw (ADDR);
0430 csr0 = inw (DATA);
0431
0432 DLOG ("IRQ: vec=%.02X csr0=%.04X", vec, csr0);
0433
0434
0435 outw (csr0 & ~0x004f, DATA);
0436
0437 if (csr0 & 0x8000) {
0438 if (csr0 & 0x1000)
0439 DLOG ("IRQ: missed packet");
0440 if (csr0 & 0x2000)
0441 DLOG ("IRQ: collision detected");
0442 }
0443
0444 if (csr0 & 0x400)
0445 handle_rint ();
0446 if (csr0 & 0x200)
0447 handle_tint ();
0448
0449
0450 outw (0, ADDR); (void) inw (ADDR);
0451 outw (0x7940, DATA);
0452
0453 DLOG ("IRQ: finished. csr0=%.04X", inw (DATA));
0454
0455 unlock_kernel ();
0456 return 0;
0457 }
0458
0459 extern bool
0460 pcnet_get_hwaddr (uint8 addr[ETH_ADDR_LEN])
0461 {
0462 uint i;
0463 for (i=0;i<ETH_ADDR_LEN;i++)
0464 addr[i] = eth_addr[i];
0465 return TRUE;
0466 }
0467
0468 extern bool
0469 pcnet_init (void)
0470 {
0471 uint i;
0472
0473 if (mp_ISA_PC) {
0474 DLOG ("Cannot operate without PCI support");
0475 goto abort;
0476 }
0477
0478 for (i=0; compatible_ids[i].vendor != 0xFFFF; i++)
0479 if (pci_find_device (compatible_ids[i].vendor, compatible_ids[i].device,
0480 0xFF, 0xFF, 0, &device_index))
0481 break;
0482 else
0483 device_index = ~0;
0484
0485 if (device_index == (uint)(~0)) {
0486 DLOG ("Unable to detect compatible device.");
0487 goto abort;
0488 }
0489
0490 DLOG ("Found device_index=%d sizeof (pcnet_interface)=%d",
0491 device_index, sizeof (struct pcnet_interface));
0492
0493 if (!pci_decode_bar (device_index, 0, NULL, &io_base, NULL)) {
0494 DLOG ("Invalid PCI configuration or BAR0 not found");
0495 goto abort;
0496 }
0497
0498 if (io_base == 0) {
0499 DLOG ("Memory-mapped I/O not implemented");
0500 goto abort;
0501 }
0502
0503 DLOG ("Using io_base=%.04X", io_base);
0504
0505 if (!pci_get_interrupt (device_index, &irq_line, &irq_pin)) {
0506 DLOG ("Unable to get IRQ");
0507 goto abort;
0508 }
0509
0510 DLOG ("Using IRQ line=%.02X pin=%X", irq_line, irq_pin);
0511
0512
0513 frame_count = sizeof (struct pcnet_interface) >> 12;
0514 if (sizeof (struct pcnet_interface) & 0xFFF)
0515 frame_count++;
0516
0517
0518 card_phys = alloc_phys_frames (frame_count);
0519
0520 if (card_phys == -1) {
0521 DLOG ("Unable to allocate physical memory");
0522 goto abort;
0523 }
0524
0525
0526 card = (struct pcnet_interface *)
0527 map_contiguous_virtual_pages (card_phys | 3, frame_count);
0528
0529 if (card == NULL) {
0530 DLOG ("Unable to allocate virtual memory");
0531 goto abort_phys;
0532 }
0533
0534
0535 memset (card, 0, sizeof (struct pcnet_interface));
0536
0537 DLOG ("DMA region at virt=%p phys=%p count=%d", card, card_phys, frame_count);
0538
0539 if (!probe ()) {
0540 DLOG ("probe failed");
0541 goto abort_virt;
0542 }
0543
0544
0545 pci_irq_t irq;
0546 pci_device pdev;
0547 if (!pci_get_device (device_index, &pdev)) {
0548 DLOG ("pci_get_device");
0549 goto abort_virt;
0550 }
0551
0552 if (pci_irq_find (pdev.bus, pdev.slot, irq_pin, &irq)) {
0553
0554 DLOG ("Found PCI routing entry irq.gsi=0x%x", irq.gsi);
0555 if (!pci_irq_map_handler (&irq, pcnet_irq_handler, 0x01,
0556 IOAPIC_DESTINATION_LOGICAL,
0557 IOAPIC_DELIVERY_FIXED)) {
0558 DLOG ("Failed to map IRQ");
0559 goto abort_virt;
0560 }
0561 irq_line = irq.gsi;
0562 } else {
0563 DLOG ("Unable to find PCI routing entry");
0564 goto abort_virt;
0565 }
0566
0567 reset ();
0568
0569
0570 pcnet_ethdev.recv_func = NULL;
0571 pcnet_ethdev.send_func = pcnet_transmit;
0572 pcnet_ethdev.get_hwaddr_func = pcnet_get_hwaddr;
0573 pcnet_ethdev.poll_func = pcnet_poll;
0574
0575 if (!net_register_device (&pcnet_ethdev)) {
0576 DLOG ("registration failed");
0577 goto abort_virt;
0578 }
0579
0580 return TRUE;
0581 abort_virt:
0582 unmap_virtual_pages (card, frame_count);
0583 abort_phys:
0584 free_phys_frames (card_phys, frame_count);
0585 abort:
0586 return FALSE;
0587 }
0588
0589
0590
0591 #include "module/header.h"
0592
0593 static const struct module_ops mod_ops = {
0594 .init = pcnet_init
0595 };
0596
0597 DEF_MODULE (net___pcnet, "pcnet network driver", &mod_ops, {"net___ethernet", "pci"});
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608