1 /* 2 * rtl8169.c 3 * 4 * This file contains a ethernet device driver for Realtek rtl8169 based 5 * ethernet cards. 6 * 7 */ 8 9 #include <minix/drivers.h> 10 #include <minix/netdriver.h> 11 12 #include <machine/pci.h> 13 #include <assert.h> 14 15 #include "rtl8169.h" 16 17 #define VERBOSE 0 /* display message during init */ 18 19 #define RE_DTCC_VALUE 600 /* DTCC Update once every 10 minutes */ 20 21 #define RX_CONFIG_MASK 0xff7e1880 /* Clears the bits supported by chip */ 22 23 #define RE_INTR_MASK (RL_IMR_TDU | RL_IMR_FOVW | RL_IMR_PUN | RL_IMR_RDU | \ 24 RL_IMR_TER | RL_IMR_TOK | RL_IMR_RER | RL_IMR_ROK) 25 26 #define RL_ENVVAR "RTLETH" /* Configuration */ 27 28 typedef struct re_desc 29 { 30 u32_t status; /* command/status */ 31 u32_t vlan; /* VLAN */ 32 u32_t addr_low; /* low 32-bits of physical buffer address */ 33 u32_t addr_high; /* high 32-bits of physical buffer address */ 34 } re_desc; 35 36 typedef struct re_dtcc 37 { 38 u32_t TxOk_low; /* low 32-bits of Tx Ok packets */ 39 u32_t TxOk_high; /* high 32-bits of Tx Ok packets */ 40 u32_t RxOk_low; /* low 32-bits of Rx Ok packets */ 41 u32_t RxOk_high; /* high 32-bits of Rx Ok packets */ 42 u32_t TxEr_low; /* low 32-bits of Tx errors */ 43 u32_t TxEr_high; /* high 32-bits of Tx errors */ 44 u32_t RxEr; /* Rx errors */ 45 u16_t MissPkt; /* Missed packets */ 46 u16_t FAE; /* Frame Alignment Error packets (MII only) */ 47 u32_t Tx1Col; /* Tx Ok packets with 1 collision before Tx */ 48 u32_t TxMCol; /* Tx Ok packets with 2..15 collisions */ 49 u32_t RxOkPhy_low; /* low 32-bits of Rx Ok packets for us */ 50 u32_t RxOkPhy_high; /* high 32-bits of Rx Ok packets for us */ 51 u32_t RxOkBrd_low; /* low 32-bits of Rx Ok broadcast packets */ 52 u32_t RxOkBrd_high; /* high 32-bits of Rx Ok broadcast packets */ 53 u32_t RxOkMul; /* Rx Ok multicast packets */ 54 u16_t TxAbt; /* Tx abort packets */ 55 u16_t TxUndrn; /* Tx underrun packets */ 56 } re_dtcc; 57 58 typedef struct re { 59 port_t re_base_port; 60 int re_irq; 61 int re_mode; 62 int re_link_up; 63 int re_got_int; 64 int re_send_int; 65 int re_report_link; 66 int re_need_reset; 67 int re_tx_alive; 68 u32_t re_mac; 69 const char *re_model; 70 71 /* Rx */ 72 int re_rx_head; 73 struct { 74 phys_bytes ret_buf; 75 char *v_ret_buf; 76 } re_rx[N_RX_DESC]; 77 78 re_desc *re_rx_desc; /* Rx descriptor buffer */ 79 phys_bytes p_rx_desc; /* Rx descriptor buffer physical */ 80 81 /* Tx */ 82 int re_tx_head; 83 struct { 84 int ret_busy; 85 phys_bytes ret_buf; 86 char *v_ret_buf; 87 } re_tx[N_TX_DESC]; 88 re_desc *re_tx_desc; /* Tx descriptor buffer */ 89 phys_bytes p_tx_desc; /* Tx descriptor buffer physical */ 90 int re_tx_busy; /* how many Tx descriptors are busy? */ 91 92 int re_hook_id; /* IRQ hook id at kernel */ 93 phys_bytes dtcc_buf; /* Dump Tally Counter buffer physical */ 94 re_dtcc *v_dtcc_buf; /* Dump Tally Counter buffer */ 95 u32_t dtcc_counter; /* DTCC update counter */ 96 u32_t interrupts; 97 } re_t; 98 99 static re_t re_state; 100 101 static unsigned my_inb(u16_t port) 102 { 103 u32_t value; 104 int s; 105 if ((s = sys_inb(port, &value)) != OK) 106 printf("RTL8169: warning, sys_inb failed: %d\n", s); 107 return value; 108 } 109 static unsigned my_inw(u16_t port) 110 { 111 u32_t value; 112 int s; 113 if ((s = sys_inw(port, &value)) != OK) 114 printf("RTL8169: warning, sys_inw failed: %d\n", s); 115 return value; 116 } 117 static unsigned my_inl(u16_t port) 118 { 119 u32_t value; 120 int s; 121 if ((s = sys_inl(port, &value)) != OK) 122 printf("RTL8169: warning, sys_inl failed: %d\n", s); 123 return value; 124 } 125 #define rl_inb(port, offset) (my_inb((port) + (offset))) 126 #define rl_inw(port, offset) (my_inw((port) + (offset))) 127 #define rl_inl(port, offset) (my_inl((port) + (offset))) 128 129 static void my_outb(u16_t port, u8_t value) 130 { 131 int s; 132 133 if ((s = sys_outb(port, value)) != OK) 134 printf("RTL8169: warning, sys_outb failed: %d\n", s); 135 } 136 static void my_outw(u16_t port, u16_t value) 137 { 138 int s; 139 140 if ((s = sys_outw(port, value)) != OK) 141 printf("RTL8169: warning, sys_outw failed: %d\n", s); 142 } 143 static void my_outl(u16_t port, u32_t value) 144 { 145 int s; 146 147 if ((s = sys_outl(port, value)) != OK) 148 printf("RTL8169: warning, sys_outl failed: %d\n", s); 149 } 150 #define rl_outb(port, offset, value) (my_outb((port) + (offset), (value))) 151 #define rl_outw(port, offset, value) (my_outw((port) + (offset), (value))) 152 #define rl_outl(port, offset, value) (my_outl((port) + (offset), (value))) 153 154 static int rl_init(unsigned int instance, netdriver_addr_t *addr, 155 uint32_t *caps, unsigned int *ticks); 156 static int rl_probe(re_t *rep, unsigned int skip); 157 static void rl_init_buf(re_t *rep); 158 static void rl_init_hw(re_t *rep, netdriver_addr_t *addr, 159 unsigned int instance); 160 static void rl_reset_hw(re_t *rep); 161 static void rl_confaddr(re_t *rep, netdriver_addr_t *addr, 162 unsigned int instance); 163 static void rl_set_hwaddr(const netdriver_addr_t *addr); 164 static void rl_stop(void); 165 static void rl_rec_mode(re_t *rep); 166 static void rl_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list, 167 unsigned int mcast_count); 168 static ssize_t rl_recv(struct netdriver_data *data, size_t max); 169 static int rl_send(struct netdriver_data *data, size_t size); 170 static unsigned int rl_get_link(uint32_t *media); 171 static void rl_intr(unsigned int mask); 172 static void rl_check_ints(re_t *rep); 173 static void rl_do_reset(re_t *rep); 174 #if VERBOSE 175 static void rl_report_link(re_t *rep); 176 static void dump_phy(const re_t *rep); 177 #endif 178 static void rl_handler(re_t *rep); 179 static void rl_tick(void); 180 181 static const struct netdriver rl_table = { 182 .ndr_name = "re", 183 .ndr_init = rl_init, 184 .ndr_stop = rl_stop, 185 .ndr_set_mode = rl_set_mode, 186 .ndr_set_hwaddr = rl_set_hwaddr, 187 .ndr_recv = rl_recv, 188 .ndr_send = rl_send, 189 .ndr_get_link = rl_get_link, 190 .ndr_intr = rl_intr, 191 .ndr_tick = rl_tick 192 }; 193 194 /*===========================================================================* 195 * main * 196 *===========================================================================*/ 197 int main(int argc, char *argv[]) 198 { 199 env_setargs(argc, argv); 200 201 netdriver_task(&rl_table); 202 203 return 0; 204 } 205 206 /*===========================================================================* 207 * rl_init * 208 *===========================================================================*/ 209 static int rl_init(unsigned int instance, netdriver_addr_t *addr, 210 uint32_t *caps, unsigned int *ticks) 211 { 212 /* Initialize the rtl8169 driver. */ 213 re_t *rep; 214 215 /* Initialize driver state. */ 216 rep = &re_state; 217 memset(rep, 0, sizeof(*rep)); 218 219 /* Try to find a matching device. */ 220 if (!rl_probe(rep, instance)) 221 return ENXIO; 222 223 /* Claim buffer memory now. */ 224 rl_init_buf(&re_state); 225 226 /* Initialize the device we found. */ 227 rl_init_hw(rep, addr, instance); 228 229 *caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST | NDEV_CAP_HWADDR; 230 *ticks = sys_hz(); 231 return OK; 232 } 233 234 /*===========================================================================* 235 * rl_stop * 236 *===========================================================================*/ 237 static void rl_stop(void) 238 { 239 re_t *rep; 240 241 rep = &re_state; 242 243 rl_outb(rep->re_base_port, RL_CR, RL_CR_RST); 244 } 245 246 static void mdio_write(u16_t port, int regaddr, int value) 247 { 248 int i; 249 250 rl_outl(port, RL_PHYAR, 251 0x80000000 | (regaddr & 0x1F) << 16 | (value & 0xFFFF)); 252 253 for (i = 20; i > 0; i--) { 254 /* 255 * Check if the RTL8169 has completed writing to the specified 256 * MII register 257 */ 258 if (!(rl_inl(port, RL_PHYAR) & 0x80000000)) 259 break; 260 else 261 micro_delay(50); 262 } 263 } 264 265 static int mdio_read(u16_t port, int regaddr) 266 { 267 int i, value = -1; 268 269 rl_outl(port, RL_PHYAR, (regaddr & 0x1F) << 16); 270 271 for (i = 20; i > 0; i--) { 272 /* 273 * Check if the RTL8169 has completed retrieving data from 274 * the specified MII register 275 */ 276 if (rl_inl(port, RL_PHYAR) & 0x80000000) { 277 value = (int)(rl_inl(port, RL_PHYAR) & 0xFFFF); 278 break; 279 } else 280 micro_delay(50); 281 } 282 return value; 283 } 284 285 static void rtl8169_update_stat(re_t *rep) 286 { 287 static u64_t last_miss = 0, last_coll = 0; 288 u64_t miss, coll; 289 port_t port; 290 int i; 291 292 port = rep->re_base_port; 293 294 /* Dump Tally Counter Command */ 295 rl_outl(port, RL_DTCCR_HI, 0); /* 64 bits */ 296 rl_outl(port, RL_DTCCR_LO, rep->dtcc_buf | RL_DTCCR_CMD); 297 for (i = 0; i < 1000; i++) { 298 if (!(rl_inl(port, RL_DTCCR_LO) & RL_DTCCR_CMD)) 299 break; 300 micro_delay(10); 301 } 302 303 /* Update counters */ 304 miss = rep->v_dtcc_buf->MissPkt; 305 netdriver_stat_ierror(miss - last_miss); 306 last_miss = miss; 307 308 coll = rep->v_dtcc_buf->Tx1Col + rep->v_dtcc_buf->TxMCol; 309 netdriver_stat_coll(coll - last_coll); 310 last_coll = coll; 311 } 312 313 #if 0 314 /*===========================================================================* 315 * rtl8169_dump * 316 *===========================================================================*/ 317 static void rtl8169_dump(void) 318 { 319 re_dtcc *dtcc; 320 re_t *rep; 321 322 rep = &re_state; 323 324 printf("\n"); 325 326 rtl8169_update_stat(rep); 327 328 printf("Realtek RTL 8169 driver %s:\n", netdriver_name()); 329 330 printf("interrupts :%8u\n", rep->interrupts); 331 332 printf("\nRealtek RTL 8169 Tally Counters:\n"); 333 334 dtcc = rep->v_dtcc_buf; 335 336 if (dtcc->TxOk_high) 337 printf("TxOk :%8u%08u\t", 338 dtcc->TxOk_high, dtcc->TxOk_low); 339 else 340 printf("TxOk :%16u\t", dtcc->TxOk_low); 341 342 if (dtcc->RxOk_high) 343 printf("RxOk :%8u%08u\n", 344 dtcc->RxOk_high, dtcc->RxOk_low); 345 else 346 printf("RxOk :%16u\n", dtcc->RxOk_low); 347 348 if (dtcc->TxEr_high) 349 printf("TxEr :%8u%08u\t", 350 dtcc->TxEr_high, dtcc->TxEr_low); 351 else 352 printf("TxEr :%16u\t", dtcc->TxEr_low); 353 354 printf("RxEr :%16u\n", dtcc->RxEr); 355 356 printf("Tx1Col :%16u\t", dtcc->Tx1Col); 357 printf("TxMCol :%16u\n", dtcc->TxMCol); 358 359 if (dtcc->RxOkPhy_high) 360 printf("RxOkPhy :%8u%08u\t", 361 dtcc->RxOkPhy_high, dtcc->RxOkPhy_low); 362 else 363 printf("RxOkPhy :%16u\t", dtcc->RxOkPhy_low); 364 365 if (dtcc->RxOkBrd_high) 366 printf("RxOkBrd :%8u%08u\n", 367 dtcc->RxOkBrd_high, dtcc->RxOkBrd_low); 368 else 369 printf("RxOkBrd :%16u\n", dtcc->RxOkBrd_low); 370 371 printf("RxOkMul :%16u\t", dtcc->RxOkMul); 372 printf("MissPkt :%16d\n", dtcc->MissPkt); 373 374 printf("\nRealtek RTL 8169 Miscellaneous Info:\n"); 375 376 printf("tx_head :%8d busy %d\t", 377 rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy); 378 } 379 #endif 380 381 /*===========================================================================* 382 * rl_set_mode * 383 *===========================================================================*/ 384 static void rl_set_mode(unsigned int mode, 385 const netdriver_addr_t * mcast_list __unused, 386 unsigned int mcast_count __unused) 387 { 388 re_t *rep; 389 390 rep = &re_state; 391 392 rep->re_mode = mode; 393 394 rl_rec_mode(rep); 395 } 396 397 /*===========================================================================* 398 * rl_probe * 399 *===========================================================================*/ 400 static int rl_probe(re_t *rep, unsigned int skip) 401 { 402 int r, devind; 403 u16_t vid, did; 404 u32_t bar; 405 u8_t ilr; 406 #if VERBOSE 407 const char *dname; 408 #endif 409 410 pci_init(); 411 412 r = pci_first_dev(&devind, &vid, &did); 413 if (r == 0) 414 return 0; 415 416 while (skip--) { 417 r = pci_next_dev(&devind, &vid, &did); 418 if (!r) 419 return 0; 420 } 421 422 #if VERBOSE 423 dname = pci_dev_name(vid, did); 424 if (!dname) 425 dname = "unknown device"; 426 printf("%s: ", netdriver_name()); 427 printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind)); 428 #endif 429 430 pci_reserve(devind); 431 bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; 432 if (bar < 0x400) { 433 panic("base address is not properly configured"); 434 } 435 rep->re_base_port = bar; 436 437 ilr = pci_attr_r8(devind, PCI_ILR); 438 rep->re_irq = ilr; 439 #if VERBOSE 440 printf("%s: using I/O address 0x%lx, IRQ %d\n", 441 netdriver_name(), (unsigned long)bar, ilr); 442 #endif 443 444 return TRUE; 445 } 446 447 /*===========================================================================* 448 * rl_init_buf * 449 *===========================================================================*/ 450 static void rl_init_buf(re_t *rep) 451 { 452 size_t rx_bufsize, tx_bufsize, rx_descsize, tx_descsize, tot_bufsize; 453 struct re_desc *desc; 454 phys_bytes buf; 455 char *mallocbuf; 456 int d; 457 458 /* Allocate receive and transmit descriptors */ 459 rx_descsize = (N_RX_DESC * sizeof(struct re_desc)); 460 tx_descsize = (N_TX_DESC * sizeof(struct re_desc)); 461 462 /* Allocate receive and transmit buffers */ 463 tx_bufsize = NDEV_ETH_PACKET_MAX_TAGGED; 464 if (tx_bufsize % 4) 465 tx_bufsize += 4-(tx_bufsize % 4); /* Align */ 466 rx_bufsize = RX_BUFSIZE; 467 tot_bufsize = rx_descsize + tx_descsize; 468 tot_bufsize += (N_TX_DESC * tx_bufsize) + (N_RX_DESC * rx_bufsize); 469 tot_bufsize += sizeof(struct re_dtcc); 470 471 if (tot_bufsize % 4096) 472 tot_bufsize += 4096 - (tot_bufsize % 4096); 473 474 if (!(mallocbuf = alloc_contig(tot_bufsize, AC_ALIGN64K, &buf))) 475 panic("Couldn't allocate kernel buffer"); 476 477 /* Rx Descriptor */ 478 rep->re_rx_desc = (re_desc *)mallocbuf; 479 rep->p_rx_desc = buf; 480 memset(mallocbuf, 0x00, rx_descsize); 481 buf += rx_descsize; 482 mallocbuf += rx_descsize; 483 484 /* Tx Descriptor */ 485 rep->re_tx_desc = (re_desc *)mallocbuf; 486 rep->p_tx_desc = buf; 487 memset(mallocbuf, 0x00, tx_descsize); 488 buf += tx_descsize; 489 mallocbuf += tx_descsize; 490 491 desc = rep->re_rx_desc; 492 for (d = 0; d < N_RX_DESC; d++) { 493 /* Setting Rx buffer */ 494 rep->re_rx[d].ret_buf = buf; 495 rep->re_rx[d].v_ret_buf = mallocbuf; 496 buf += rx_bufsize; 497 mallocbuf += rx_bufsize; 498 499 /* Setting Rx descriptor */ 500 if (d == (N_RX_DESC - 1)) /* Last descriptor: set EOR bit */ 501 desc->status = DESC_EOR | DESC_OWN | 502 (RX_BUFSIZE & DESC_RX_LENMASK); 503 else 504 desc->status = DESC_OWN | 505 (RX_BUFSIZE & DESC_RX_LENMASK); 506 507 desc->addr_low = rep->re_rx[d].ret_buf; 508 desc++; 509 } 510 desc = rep->re_tx_desc; 511 for (d = 0; d < N_TX_DESC; d++) { 512 rep->re_tx[d].ret_busy = FALSE; 513 rep->re_tx[d].ret_buf = buf; 514 rep->re_tx[d].v_ret_buf = mallocbuf; 515 buf += tx_bufsize; 516 mallocbuf += tx_bufsize; 517 518 /* Setting Tx descriptor */ 519 desc->addr_low = rep->re_tx[d].ret_buf; 520 desc++; 521 } 522 rep->re_tx_busy = 0; 523 524 /* Dump Tally Counter buffer */ 525 rep->dtcc_buf = buf; 526 rep->v_dtcc_buf = (re_dtcc *)mallocbuf; 527 } 528 529 /*===========================================================================* 530 * rl_init_hw * 531 *===========================================================================*/ 532 static void rl_init_hw(re_t *rep, netdriver_addr_t *addr, 533 unsigned int instance) 534 { 535 int s; 536 #if VERBOSE 537 int i; 538 #endif 539 540 /* 541 * Set the interrupt handler. The policy is to only send HARD_INT 542 * notifications. Don't reenable interrupts automatically. The id 543 * that is passed back is the interrupt line number. 544 */ 545 rep->re_hook_id = rep->re_irq; 546 if ((s = sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK) 547 printf("RTL8169: error, couldn't set IRQ policy: %d\n", s); 548 549 rl_reset_hw(rep); 550 551 if ((s = sys_irqenable(&rep->re_hook_id)) != OK) 552 printf("RTL8169: error, couldn't enable interrupts: %d\n", s); 553 554 #if VERBOSE 555 printf("%s: model: %s mac: 0x%08x\n", 556 netdriver_name(), rep->re_model, rep->re_mac); 557 #endif 558 559 rl_confaddr(rep, addr, instance); 560 561 #if VERBOSE 562 printf("%s: Ethernet address ", netdriver_name()); 563 for (i = 0; i < 6; i++) { 564 printf("%x%c", addr->na_addr[i], 565 i < 5 ? ':' : '\n'); 566 } 567 #endif 568 } 569 570 static void rtl8169s_phy_config(port_t port) 571 { 572 mdio_write(port, 0x1f, 0x0001); 573 mdio_write(port, 0x06, 0x006e); 574 mdio_write(port, 0x08, 0x0708); 575 mdio_write(port, 0x15, 0x4000); 576 mdio_write(port, 0x18, 0x65c7); 577 578 mdio_write(port, 0x1f, 0x0001); 579 mdio_write(port, 0x03, 0x00a1); 580 mdio_write(port, 0x02, 0x0008); 581 mdio_write(port, 0x01, 0x0120); 582 mdio_write(port, 0x00, 0x1000); 583 mdio_write(port, 0x04, 0x0800); 584 mdio_write(port, 0x04, 0x0000); 585 586 mdio_write(port, 0x03, 0xff41); 587 mdio_write(port, 0x02, 0xdf60); 588 mdio_write(port, 0x01, 0x0140); 589 mdio_write(port, 0x00, 0x0077); 590 mdio_write(port, 0x04, 0x7800); 591 mdio_write(port, 0x04, 0x7000); 592 593 mdio_write(port, 0x03, 0x802f); 594 mdio_write(port, 0x02, 0x4f02); 595 mdio_write(port, 0x01, 0x0409); 596 mdio_write(port, 0x00, 0xf0f9); 597 mdio_write(port, 0x04, 0x9800); 598 mdio_write(port, 0x04, 0x9000); 599 600 mdio_write(port, 0x03, 0xdf01); 601 mdio_write(port, 0x02, 0xdf20); 602 mdio_write(port, 0x01, 0xff95); 603 mdio_write(port, 0x00, 0xba00); 604 mdio_write(port, 0x04, 0xa800); 605 mdio_write(port, 0x04, 0xa000); 606 607 mdio_write(port, 0x03, 0xff41); 608 mdio_write(port, 0x02, 0xdf20); 609 mdio_write(port, 0x01, 0x0140); 610 mdio_write(port, 0x00, 0x00bb); 611 mdio_write(port, 0x04, 0xb800); 612 mdio_write(port, 0x04, 0xb000); 613 614 mdio_write(port, 0x03, 0xdf41); 615 mdio_write(port, 0x02, 0xdc60); 616 mdio_write(port, 0x01, 0x6340); 617 mdio_write(port, 0x00, 0x007d); 618 mdio_write(port, 0x04, 0xd800); 619 mdio_write(port, 0x04, 0xd000); 620 621 mdio_write(port, 0x03, 0xdf01); 622 mdio_write(port, 0x02, 0xdf20); 623 mdio_write(port, 0x01, 0x100a); 624 mdio_write(port, 0x00, 0xa0ff); 625 mdio_write(port, 0x04, 0xf800); 626 mdio_write(port, 0x04, 0xf000); 627 628 mdio_write(port, 0x1f, 0x0000); 629 mdio_write(port, 0x0b, 0x0000); 630 mdio_write(port, 0x00, 0x9200); 631 } 632 633 static void rtl8169scd_phy_config(port_t port) 634 { 635 mdio_write(port, 0x1f, 0x0001); 636 mdio_write(port, 0x04, 0x0000); 637 mdio_write(port, 0x03, 0x00a1); 638 mdio_write(port, 0x02, 0x0008); 639 mdio_write(port, 0x01, 0x0120); 640 mdio_write(port, 0x00, 0x1000); 641 mdio_write(port, 0x04, 0x0800); 642 mdio_write(port, 0x04, 0x9000); 643 mdio_write(port, 0x03, 0x802f); 644 mdio_write(port, 0x02, 0x4f02); 645 mdio_write(port, 0x01, 0x0409); 646 mdio_write(port, 0x00, 0xf099); 647 mdio_write(port, 0x04, 0x9800); 648 mdio_write(port, 0x04, 0xa000); 649 mdio_write(port, 0x03, 0xdf01); 650 mdio_write(port, 0x02, 0xdf20); 651 mdio_write(port, 0x01, 0xff95); 652 mdio_write(port, 0x00, 0xba00); 653 mdio_write(port, 0x04, 0xa800); 654 mdio_write(port, 0x04, 0xf000); 655 mdio_write(port, 0x03, 0xdf01); 656 mdio_write(port, 0x02, 0xdf20); 657 mdio_write(port, 0x01, 0x101a); 658 mdio_write(port, 0x00, 0xa0ff); 659 mdio_write(port, 0x04, 0xf800); 660 mdio_write(port, 0x04, 0x0000); 661 mdio_write(port, 0x1f, 0x0000); 662 663 mdio_write(port, 0x1f, 0x0001); 664 mdio_write(port, 0x10, 0xf41b); 665 mdio_write(port, 0x14, 0xfb54); 666 mdio_write(port, 0x18, 0xf5c7); 667 mdio_write(port, 0x1f, 0x0000); 668 669 mdio_write(port, 0x1f, 0x0001); 670 mdio_write(port, 0x17, 0x0cc0); 671 mdio_write(port, 0x1f, 0x0000); 672 } 673 674 /*===========================================================================* 675 * rl_reset_hw * 676 *===========================================================================*/ 677 static void rl_reset_hw(re_t *rep) 678 { 679 port_t port; 680 u32_t t; 681 int i; 682 683 port = rep->re_base_port; 684 685 rl_outw(port, RL_IMR, 0x0000); 686 687 /* Reset the device */ 688 rl_outb(port, RL_CR, RL_CR_RST); 689 SPIN_UNTIL(!(rl_inb(port, RL_CR) & RL_CR_RST), 1000000); 690 if (rl_inb(port, RL_CR) & RL_CR_RST) 691 printf("rtl8169: reset failed to complete"); 692 rl_outw(port, RL_ISR, 0xFFFF); 693 694 /* Get Model and MAC info */ 695 t = rl_inl(port, RL_TCR); 696 rep->re_mac = (t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM)); 697 switch (rep->re_mac) { 698 case RL_TCR_HWVER_RTL8169: 699 rep->re_model = "RTL8169"; 700 701 rl_outw(port, RL_CCR_UNDOC, 0x01); 702 break; 703 case RL_TCR_HWVER_RTL8169S: 704 rep->re_model = "RTL8169S"; 705 706 rtl8169s_phy_config(port); 707 708 rl_outw(port, RL_CCR_UNDOC, 0x01); 709 mdio_write(port, 0x0b, 0x0000); /* w 0x0b 15 0 0 */ 710 break; 711 case RL_TCR_HWVER_RTL8110S: 712 rep->re_model = "RTL8110S"; 713 714 rtl8169s_phy_config(port); 715 716 rl_outw(port, RL_CCR_UNDOC, 0x01); 717 break; 718 case RL_TCR_HWVER_RTL8169SB: 719 rep->re_model = "RTL8169SB"; 720 721 mdio_write(port, 0x1f, 0x02); 722 mdio_write(port, 0x01, 0x90d0); 723 mdio_write(port, 0x1f, 0x00); 724 725 rl_outw(port, RL_CCR_UNDOC, 0x01); 726 break; 727 case RL_TCR_HWVER_RTL8110SCd: 728 rep->re_model = "RTL8110SCd"; 729 730 rtl8169scd_phy_config(port); 731 732 rl_outw(port, RL_CCR_UNDOC, 0x01); 733 break; 734 case RL_TCR_HWVER_RTL8105E: 735 rep->re_model = "RTL8105E"; 736 break; 737 default: 738 rep->re_model = "Unknown"; 739 rep->re_mac = t; 740 break; 741 } 742 743 mdio_write(port, MII_CTRL, MII_CTRL_RST); 744 for (i = 0; i < 1000; i++) { 745 t = mdio_read(port, MII_CTRL); 746 if (!(t & MII_CTRL_RST)) 747 break; 748 else 749 micro_delay(100); 750 } 751 752 t = mdio_read(port, MII_CTRL); 753 t |= MII_CTRL_ANE | MII_CTRL_DM | MII_CTRL_SP_1000; 754 mdio_write(port, MII_CTRL, t); 755 756 t = mdio_read(port, MII_ANA); 757 t |= MII_ANA_10THD | MII_ANA_10TFD | MII_ANA_100TXHD | MII_ANA_100TXFD; 758 t |= MII_ANA_PAUSE_SYM | MII_ANA_PAUSE_ASYM; 759 mdio_write(port, MII_ANA, t); 760 761 t = mdio_read(port, MII_1000_CTRL) | 0x300; 762 mdio_write(port, MII_1000_CTRL, t); 763 764 /* Restart Auto-Negotiation Process */ 765 t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_RAN; 766 mdio_write(port, MII_CTRL, t); 767 768 rl_outw(port, RL_9346CR, RL_9346CR_EEM_CONFIG); /* Unlock */ 769 770 switch (rep->re_mac) { 771 case RL_TCR_HWVER_RTL8169S: 772 case RL_TCR_HWVER_RTL8110S: 773 /* Bit-3 and bit-14 of the C+CR register MUST be 1. */ 774 t = rl_inw(port, RL_CPLUSCMD); 775 rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW | (1 << 14)); 776 break; 777 case RL_TCR_HWVER_RTL8169: 778 case RL_TCR_HWVER_RTL8169SB: 779 case RL_TCR_HWVER_RTL8110SCd: 780 t = rl_inw(port, RL_CPLUSCMD); 781 rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW); 782 break; 783 } 784 785 rl_outw(port, RL_INTRMITIGATE, 0x00); 786 787 t = rl_inb(port, RL_CR); 788 rl_outb(port, RL_CR, t | RL_CR_RE | RL_CR_TE); 789 790 /* Initialize Rx */ 791 rl_outw(port, RL_RMS, RX_BUFSIZE); /* Maximum rx packet size */ 792 t = rl_inl(port, RL_RCR) & RX_CONFIG_MASK; 793 rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | t); 794 rl_outl(port, RL_RDSAR_LO, rep->p_rx_desc); 795 rl_outl(port, RL_RDSAR_HI, 0x00); /* For 64 bit */ 796 797 /* Initialize Tx */ 798 rl_outw(port, RL_ETTHR, 0x3f); /* No early transmit */ 799 rl_outl(port, RL_TCR, RL_TCR_MXDMA_2048 | RL_TCR_IFG_STD); 800 rl_outl(port, RL_TNPDS_LO, rep->p_tx_desc); 801 rl_outl(port, RL_TNPDS_HI, 0x00); /* For 64 bit */ 802 803 rl_outw(port, RL_9346CR, RL_9346CR_EEM_NORMAL); /* Lock */ 804 805 rl_outw(port, RL_MPC, 0x00); 806 rl_outw(port, RL_MULINT, rl_inw(port, RL_MULINT) & 0xF000); 807 rl_outw(port, RL_IMR, RE_INTR_MASK); 808 } 809 810 /*===========================================================================* 811 * rl_confaddr * 812 *===========================================================================*/ 813 static void rl_confaddr(re_t *rep, netdriver_addr_t *addr, 814 unsigned int instance) 815 { 816 static char eakey[] = RL_ENVVAR "#_EA"; 817 static char eafmt[] = "x:x:x:x:x:x"; 818 int i; 819 port_t port; 820 long v; 821 822 /* User defined ethernet address? */ 823 eakey[sizeof(RL_ENVVAR)-1] = '0' + instance; 824 825 port = rep->re_base_port; 826 827 for (i = 0; i < 6; i++) { 828 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET) 829 break; 830 addr->na_addr[i] = v; 831 } 832 833 if (i != 0 && i != 6) 834 env_panic(eakey); /* It's all or nothing */ 835 836 /* Should update ethernet address in hardware */ 837 if (i == 6) 838 rl_set_hwaddr(addr); 839 840 /* Get ethernet address */ 841 for (i = 0; i < 6; i++) 842 addr->na_addr[i] = rl_inb(port, RL_IDR+i); 843 } 844 845 /*===========================================================================* 846 * rl_set_hwaddr * 847 *===========================================================================*/ 848 static void rl_set_hwaddr(const netdriver_addr_t *addr) 849 { 850 re_t *rep; 851 port_t port; 852 u32_t w; 853 int i; 854 855 rep = &re_state; 856 857 port = rep->re_base_port; 858 rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG); 859 w = 0; 860 for (i = 0; i < 4; i++) 861 w |= (addr->na_addr[i] << (i * 8)); 862 rl_outl(port, RL_IDR, w); 863 w = 0; 864 for (i = 4; i < 6; i++) 865 w |= (addr->na_addr[i] << ((i-4) * 8)); 866 rl_outl(port, RL_IDR + 4, w); 867 rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL); 868 } 869 870 /*===========================================================================* 871 * rl_rec_mode * 872 *===========================================================================*/ 873 static void rl_rec_mode(re_t *rep) 874 { 875 port_t port; 876 u32_t rcr; 877 u32_t mc_filter[2]; /* Multicast hash filter */ 878 879 port = rep->re_base_port; 880 881 mc_filter[1] = mc_filter[0] = 0xffffffff; 882 rl_outl(port, RL_MAR + 0, mc_filter[0]); 883 rl_outl(port, RL_MAR + 4, mc_filter[1]); 884 885 rcr = rl_inl(port, RL_RCR); 886 rcr &= ~(RL_RCR_AB | RL_RCR_AM | RL_RCR_APM | RL_RCR_AAP); 887 if (rep->re_mode & NDEV_MODE_PROMISC) 888 rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP; 889 if (rep->re_mode & NDEV_MODE_BCAST) 890 rcr |= RL_RCR_AB; 891 if (rep->re_mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL)) 892 rcr |= RL_RCR_AM; 893 rcr |= RL_RCR_APM; 894 rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | rcr); 895 } 896 897 /*===========================================================================* 898 * rl_recv * 899 *===========================================================================*/ 900 static ssize_t rl_recv(struct netdriver_data *data, size_t max) 901 { 902 int index; 903 port_t port; 904 unsigned totlen, packlen; 905 re_desc *desc; 906 u32_t rxstat; 907 re_t *rep; 908 909 rep = &re_state; 910 911 port = rep->re_base_port; 912 913 if (rl_inb(port, RL_CR) & RL_CR_BUFE) 914 return SUSPEND; /* Receive buffer is empty, suspend */ 915 916 index = rep->re_rx_head; 917 desc = rep->re_rx_desc; 918 desc += index; 919 920 for (;;) { 921 rxstat = desc->status; 922 923 if (rxstat & DESC_OWN) 924 return SUSPEND; 925 926 if (rxstat & DESC_RX_CRC) 927 netdriver_stat_ierror(1); 928 929 if ((rxstat & (DESC_FS | DESC_LS)) == (DESC_FS | DESC_LS)) 930 break; 931 932 #if VERBOSE 933 printf("rl_recv: packet is fragmented\n"); 934 #endif 935 /* Fix the fragmented packet */ 936 if (index == N_RX_DESC - 1) { 937 desc->status = DESC_EOR | DESC_OWN | 938 (RX_BUFSIZE & DESC_RX_LENMASK); 939 index = 0; 940 desc = rep->re_rx_desc; 941 } else { 942 desc->status = DESC_OWN | 943 (RX_BUFSIZE & DESC_RX_LENMASK); 944 index++; 945 desc++; 946 } 947 /* Loop until we get correct packet */ 948 } 949 950 totlen = rxstat & DESC_RX_LENMASK; 951 if (totlen < 8 || totlen > 2 * NDEV_ETH_PACKET_MAX) { 952 /* Someting went wrong */ 953 printf("rl_recv: bad length (%u) in status 0x%08x\n", 954 totlen, rxstat); 955 panic(NULL); 956 } 957 958 /* Should subtract the CRC */ 959 packlen = totlen - NDEV_ETH_PACKET_CRC; 960 if (packlen > max) 961 packlen = max; 962 963 netdriver_copyout(data, 0, rep->re_rx[index].v_ret_buf, packlen); 964 965 if (index == N_RX_DESC - 1) { 966 desc->status = DESC_EOR | DESC_OWN | 967 (RX_BUFSIZE & DESC_RX_LENMASK); 968 index = 0; 969 } else { 970 desc->status = DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK); 971 index++; 972 } 973 rep->re_rx_head = index; 974 assert(rep->re_rx_head < N_RX_DESC); 975 976 return packlen; 977 } 978 979 /*===========================================================================* 980 * rl_send * 981 *===========================================================================*/ 982 static int rl_send(struct netdriver_data *data, size_t size) 983 { 984 int tx_head; 985 re_t *rep; 986 re_desc *desc; 987 988 rep = &re_state; 989 990 tx_head = rep->re_tx_head; 991 992 desc = rep->re_tx_desc; 993 desc += tx_head; 994 995 assert(desc); 996 assert(rep->re_tx_desc); 997 assert(rep->re_tx_head >= 0 && rep->re_tx_head < N_TX_DESC); 998 999 if (rep->re_tx[tx_head].ret_busy) 1000 return SUSPEND; 1001 1002 netdriver_copyin(data, 0, rep->re_tx[tx_head].v_ret_buf, size); 1003 1004 rep->re_tx[tx_head].ret_busy = TRUE; 1005 rep->re_tx_busy++; 1006 1007 if (tx_head == N_TX_DESC - 1) { 1008 desc->status = DESC_EOR | DESC_OWN | DESC_FS | DESC_LS | size; 1009 tx_head = 0; 1010 } else { 1011 desc->status = DESC_OWN | DESC_FS | DESC_LS | size; 1012 tx_head++; 1013 } 1014 1015 assert(tx_head < N_TX_DESC); 1016 rep->re_tx_head = tx_head; 1017 1018 rl_outl(rep->re_base_port, RL_TPPOLL, RL_TPPOLL_NPQ); 1019 1020 return OK; 1021 } 1022 1023 /*===========================================================================* 1024 * rl_check_ints * 1025 *===========================================================================*/ 1026 static void rl_check_ints(re_t *rep) 1027 { 1028 if (!rep->re_got_int) 1029 return; 1030 rep->re_got_int = FALSE; 1031 1032 netdriver_recv(); 1033 1034 if (rep->re_need_reset) 1035 rl_do_reset(rep); 1036 1037 if (rep->re_send_int) { 1038 rep->re_send_int = FALSE; 1039 1040 netdriver_send(); 1041 } 1042 1043 if (rep->re_report_link) { 1044 rep->re_report_link = FALSE; 1045 1046 netdriver_link(); 1047 1048 #if VERBOSE 1049 rl_report_link(rep); 1050 #endif 1051 } 1052 } 1053 1054 /*===========================================================================* 1055 * rl_get_link * 1056 *===========================================================================*/ 1057 static unsigned int rl_get_link(uint32_t *media) 1058 { 1059 re_t *rep; 1060 u8_t mii_status; 1061 1062 rep = &re_state; 1063 1064 mii_status = rl_inb(rep->re_base_port, RL_PHYSTAT); 1065 1066 if (!(mii_status & RL_STAT_LINK)) 1067 return NDEV_LINK_DOWN; 1068 1069 if (mii_status & RL_STAT_1000) 1070 *media = IFM_ETHER | IFM_1000_T; 1071 else if (mii_status & RL_STAT_100) 1072 *media = IFM_ETHER | IFM_100_TX; 1073 else if (mii_status & RL_STAT_10) 1074 *media = IFM_ETHER | IFM_10_T; 1075 1076 if (mii_status & RL_STAT_FULLDUP) 1077 *media |= IFM_FDX; 1078 else 1079 *media |= IFM_HDX; 1080 1081 return NDEV_LINK_UP; 1082 } 1083 1084 /*===========================================================================* 1085 * rl_report_link * 1086 *===========================================================================*/ 1087 #if VERBOSE 1088 static void rl_report_link(re_t *rep) 1089 { 1090 port_t port; 1091 u8_t mii_status; 1092 1093 port = rep->re_base_port; 1094 1095 mii_status = rl_inb(port, RL_PHYSTAT); 1096 1097 if (mii_status & RL_STAT_LINK) { 1098 rep->re_link_up = 1; 1099 printf("%s: link up at ", netdriver_name()); 1100 } else { 1101 rep->re_link_up = 0; 1102 printf("%s: link down\n", netdriver_name()); 1103 return; 1104 } 1105 1106 if (mii_status & RL_STAT_1000) 1107 printf("1000 Mbps"); 1108 else if (mii_status & RL_STAT_100) 1109 printf("100 Mbps"); 1110 else if (mii_status & RL_STAT_10) 1111 printf("10 Mbps"); 1112 1113 if (mii_status & RL_STAT_FULLDUP) 1114 printf(", full duplex"); 1115 else 1116 printf(", half duplex"); 1117 printf("\n"); 1118 1119 dump_phy(rep); 1120 } 1121 #endif 1122 1123 /*===========================================================================* 1124 * rl_do_reset * 1125 *===========================================================================*/ 1126 static void rl_do_reset(re_t *rep) 1127 { 1128 rep->re_need_reset = FALSE; 1129 rl_reset_hw(rep); 1130 rl_rec_mode(rep); 1131 1132 rep->re_tx_head = 0; 1133 if (rep->re_tx[rep->re_tx_head].ret_busy) 1134 rep->re_tx_busy--; 1135 rep->re_tx[rep->re_tx_head].ret_busy = FALSE; 1136 rep->re_send_int = TRUE; 1137 } 1138 1139 #if VERBOSE 1140 static void dump_phy(const re_t *rep) 1141 { 1142 port_t port; 1143 u32_t t; 1144 1145 port = rep->re_base_port; 1146 1147 t = rl_inb(port, RL_CONFIG0); 1148 printf("CONFIG0\t\t:"); 1149 t = t & RL_CFG0_ROM; 1150 if (t == RL_CFG0_ROM128K) 1151 printf(" 128K Boot ROM"); 1152 else if (t == RL_CFG0_ROM64K) 1153 printf(" 64K Boot ROM"); 1154 else if (t == RL_CFG0_ROM32K) 1155 printf(" 32K Boot ROM"); 1156 else if (t == RL_CFG0_ROM16K) 1157 printf(" 16K Boot ROM"); 1158 else if (t == RL_CFG0_ROM8K) 1159 printf(" 8K Boot ROM"); 1160 else if (t == RL_CFG0_ROMNO) 1161 printf(" No Boot ROM"); 1162 printf("\n"); 1163 1164 t = rl_inb(port, RL_CONFIG1); 1165 printf("CONFIG1\t\t:"); 1166 if (t & RL_CFG1_LEDS1) 1167 printf(" LED1"); 1168 if (t & RL_CFG1_LEDS0) 1169 printf(" LED0"); 1170 if (t & RL_CFG1_DVRLOAD) 1171 printf(" Driver"); 1172 if (t & RL_CFG1_LWACT) 1173 printf(" LWAKE"); 1174 if (t & RL_CFG1_IOMAP) 1175 printf(" IOMAP"); 1176 if (t & RL_CFG1_MEMMAP) 1177 printf(" MEMMAP"); 1178 if (t & RL_CFG1_VPD) 1179 printf(" VPD"); 1180 if (t & RL_CFG1_PME) 1181 printf(" PME"); 1182 printf("\n"); 1183 1184 t = rl_inb(port, RL_CONFIG2); 1185 printf("CONFIG2\t\t:"); 1186 if (t & RL_CFG2_AUX) 1187 printf(" AUX"); 1188 if (t & RL_CFG2_PCIBW) 1189 printf(" PCI-64-Bit"); 1190 else 1191 printf(" PCI-32-Bit"); 1192 t = t & RL_CFG2_PCICLK; 1193 if (t == RL_CFG2_66MHZ) 1194 printf(" 66 MHz"); 1195 else if (t == RL_CFG2_33MHZ) 1196 printf(" 33 MHz"); 1197 printf("\n"); 1198 1199 t = mdio_read(port, MII_CTRL); 1200 printf("MII_CTRL\t:"); 1201 if (t & MII_CTRL_RST) 1202 printf(" Reset"); 1203 if (t & MII_CTRL_LB) 1204 printf(" Loopback"); 1205 if (t & MII_CTRL_ANE) 1206 printf(" ANE"); 1207 if (t & MII_CTRL_PD) 1208 printf(" Power-down"); 1209 if (t & MII_CTRL_ISO) 1210 printf(" Isolate"); 1211 if (t & MII_CTRL_RAN) 1212 printf(" RAN"); 1213 if (t & MII_CTRL_DM) 1214 printf(" Full-duplex"); 1215 if (t & MII_CTRL_CT) 1216 printf(" COL-signal"); 1217 t = t & (MII_CTRL_SP_LSB | MII_CTRL_SP_MSB); 1218 if (t == MII_CTRL_SP_10) 1219 printf(" 10 Mb/s"); 1220 else if (t == MII_CTRL_SP_100) 1221 printf(" 100 Mb/s"); 1222 else if (t == MII_CTRL_SP_1000) 1223 printf(" 1000 Mb/s"); 1224 printf("\n"); 1225 1226 t = mdio_read(port, MII_STATUS); 1227 printf("MII_STATUS\t:"); 1228 if (t & MII_STATUS_100T4) 1229 printf(" 100Base-T4"); 1230 if (t & MII_STATUS_100XFD) 1231 printf(" 100BaseX-FD"); 1232 if (t & MII_STATUS_100XHD) 1233 printf(" 100BaseX-HD"); 1234 if (t & MII_STATUS_10FD) 1235 printf(" 10Mbps-FD"); 1236 if (t & MII_STATUS_10HD) 1237 printf(" 10Mbps-HD"); 1238 if (t & MII_STATUS_100T2FD) 1239 printf(" 100Base-T2-FD"); 1240 if (t & MII_STATUS_100T2HD) 1241 printf(" 100Base-T2-HD"); 1242 if (t & MII_STATUS_EXT_STAT) 1243 printf(" Ext-stat"); 1244 if (t & MII_STATUS_RES) 1245 printf(" res-0x%x", t & MII_STATUS_RES); 1246 if (t & MII_STATUS_MFPS) 1247 printf(" MFPS"); 1248 if (t & MII_STATUS_ANC) 1249 printf(" ANC"); 1250 if (t & MII_STATUS_RF) 1251 printf(" remote-fault"); 1252 if (t & MII_STATUS_ANA) 1253 printf(" ANA"); 1254 if (t & MII_STATUS_LS) 1255 printf(" Link"); 1256 if (t & MII_STATUS_JD) 1257 printf(" Jabber"); 1258 if (t & MII_STATUS_EC) 1259 printf(" Extended-capability"); 1260 printf("\n"); 1261 1262 t = mdio_read(port, MII_ANA); 1263 printf("MII_ANA\t\t: 0x%04x\n", t); 1264 1265 t = mdio_read(port, MII_ANLPA); 1266 printf("MII_ANLPA\t: 0x%04x\n", t); 1267 1268 t = mdio_read(port, MII_ANE); 1269 printf("MII_ANE\t\t:"); 1270 if (t & MII_ANE_RES) 1271 printf(" res-0x%x", t & MII_ANE_RES); 1272 if (t & MII_ANE_PDF) 1273 printf(" Par-Detect-Fault"); 1274 if (t & MII_ANE_LPNPA) 1275 printf(" LP-Next-Page-Able"); 1276 if (t & MII_ANE_NPA) 1277 printf(" Loc-Next-Page-Able"); 1278 if (t & MII_ANE_PR) 1279 printf(" Page-Received"); 1280 if (t & MII_ANE_LPANA) 1281 printf(" LP-Auto-Neg-Able"); 1282 printf("\n"); 1283 1284 t = mdio_read(port, MII_1000_CTRL); 1285 printf("MII_1000_CTRL\t:"); 1286 if (t & MII_1000C_FULL) 1287 printf(" 1000BaseT-FD"); 1288 if (t & MII_1000C_HALF) 1289 printf(" 1000BaseT-HD"); 1290 printf("\n"); 1291 1292 t = mdio_read(port, MII_1000_STATUS); 1293 if (t) { 1294 printf("MII_1000_STATUS\t:"); 1295 if (t & MII_1000S_LRXOK) 1296 printf(" Local-Receiver"); 1297 if (t & MII_1000S_RRXOK) 1298 printf(" Remote-Receiver"); 1299 if (t & MII_1000S_HALF) 1300 printf(" 1000BaseT-HD"); 1301 if (t & MII_1000S_FULL) 1302 printf(" 1000BaseT-FD"); 1303 printf("\n"); 1304 1305 t = mdio_read(port, MII_EXT_STATUS); 1306 printf("MII_EXT_STATUS\t:"); 1307 if (t & MII_ESTAT_1000XFD) 1308 printf(" 1000BaseX-FD"); 1309 if (t & MII_ESTAT_1000XHD) 1310 printf(" 1000BaseX-HD"); 1311 if (t & MII_ESTAT_1000TFD) 1312 printf(" 1000BaseT-FD"); 1313 if (t & MII_ESTAT_1000THD) 1314 printf(" 1000BaseT-HD"); 1315 printf("\n"); 1316 } 1317 } 1318 #endif 1319 1320 /*===========================================================================* 1321 * rl_intr * 1322 *===========================================================================*/ 1323 static void rl_intr(unsigned int __unused mask) 1324 { 1325 re_t *rep; 1326 int s; 1327 1328 rep = &re_state; 1329 1330 /* Run interrupt handler at driver level. */ 1331 rl_handler(rep); 1332 1333 /* Reenable interrupts for this hook. */ 1334 if ((s = sys_irqenable(&rep->re_hook_id)) != OK) 1335 printf("RTL8169: error, couldn't enable interrupts: %d\n", s); 1336 1337 /* Perform tasks based on the flagged conditions. */ 1338 rl_check_ints(rep); 1339 } 1340 1341 /*===========================================================================* 1342 * rl_handler * 1343 *===========================================================================*/ 1344 static void rl_handler(re_t *rep) 1345 { 1346 int i, port, tx_head, tx_tail, link_up; 1347 u16_t isr; 1348 re_desc *desc; 1349 1350 port = rep->re_base_port; 1351 1352 /* Ack interrupt */ 1353 isr = rl_inw(port, RL_ISR); 1354 if(!isr) 1355 return; 1356 rl_outw(port, RL_ISR, isr); 1357 rep->interrupts++; 1358 1359 if (isr & RL_IMR_FOVW) { 1360 isr &= ~RL_IMR_FOVW; 1361 /* Should do anything? */ 1362 } 1363 if (isr & RL_IMR_PUN) { 1364 isr &= ~RL_IMR_PUN; 1365 1366 /* 1367 * Either the link status changed or there was a TX fifo 1368 * underrun. 1369 */ 1370 link_up = !(!(rl_inb(port, RL_PHYSTAT) & RL_STAT_LINK)); 1371 if (link_up != rep->re_link_up) { 1372 rep->re_report_link = TRUE; 1373 rep->re_got_int = TRUE; 1374 } 1375 } 1376 1377 if (isr & (RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK)) { 1378 if (isr & RL_ISR_RER) 1379 netdriver_stat_ierror(1); 1380 isr &= ~(RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK); 1381 1382 rep->re_got_int = TRUE; 1383 } 1384 1385 if ((isr & (RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK)) || 1) { 1386 if (isr & RL_ISR_TER) 1387 netdriver_stat_oerror(1); 1388 isr &= ~(RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK); 1389 1390 /* Transmit completed */ 1391 tx_head = rep->re_tx_head; 1392 tx_tail = tx_head+1; 1393 if (tx_tail >= N_TX_DESC) 1394 tx_tail = 0; 1395 for (i = 0; i < 2 * N_TX_DESC; i++) { 1396 if (!rep->re_tx[tx_tail].ret_busy) { 1397 /* Strange, this buffer is not in-use. 1398 * Increment tx_tail until tx_head is 1399 * reached (or until we find a buffer that 1400 * is in-use. 1401 */ 1402 if (tx_tail == tx_head) 1403 break; 1404 if (++tx_tail >= N_TX_DESC) 1405 tx_tail = 0; 1406 assert(tx_tail < N_TX_DESC); 1407 continue; 1408 } 1409 desc = rep->re_tx_desc; 1410 desc += tx_tail; 1411 if (desc->status & DESC_OWN) { 1412 /* Buffer is not yet ready */ 1413 break; 1414 } 1415 1416 rep->re_tx[tx_tail].ret_busy = FALSE; 1417 rep->re_tx_busy--; 1418 1419 if (++tx_tail >= N_TX_DESC) 1420 tx_tail = 0; 1421 assert(tx_tail < N_TX_DESC); 1422 1423 rep->re_send_int = TRUE; 1424 rep->re_got_int = TRUE; 1425 rep->re_tx_alive = TRUE; 1426 } 1427 assert(i < 2 * N_TX_DESC); 1428 } 1429 1430 /* Ignore Reserved Interrupt */ 1431 if (isr & RL_ISR_RES) 1432 isr &= ~RL_ISR_RES; 1433 1434 if (isr) 1435 printf("rl_handler: unhandled interrupt isr = 0x%04x\n", isr); 1436 } 1437 1438 /*===========================================================================* 1439 * rl_tick * 1440 *===========================================================================*/ 1441 static void rl_tick(void) 1442 { 1443 re_t *rep; 1444 1445 rep = &re_state; 1446 1447 /* Should collect statistics */ 1448 if (!(++rep->dtcc_counter % RE_DTCC_VALUE)) 1449 rtl8169_update_stat(rep); 1450 1451 assert(rep->re_tx_busy >= 0 && rep->re_tx_busy <= N_TX_DESC); 1452 if (rep->re_tx_busy == 0) { 1453 /* Assume that an idle system is alive */ 1454 rep->re_tx_alive = TRUE; 1455 return; 1456 } 1457 if (rep->re_tx_alive) { 1458 rep->re_tx_alive = FALSE; 1459 return; 1460 } 1461 printf("%s: TX timeout, resetting\n", netdriver_name()); 1462 printf("tx_head :%8d busy %d\t", 1463 rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy); 1464 rep->re_need_reset = TRUE; 1465 rep->re_got_int = TRUE; 1466 1467 rl_check_ints(rep); 1468 } 1469