1 #include <minix/drivers.h> 2 #include <minix/netdriver.h> 3 #include <machine/pci.h> 4 #include "vt6105.h" 5 #include "io.h" 6 7 /* global value */ 8 static vt_driver g_driver; 9 static int g_instance; 10 11 /* driver interface */ 12 static int vt_init(unsigned int instance, ether_addr_t *addr); 13 static void vt_stop(void); 14 static void vt_mode(unsigned int mode); 15 static ssize_t vt_recv(struct netdriver_data *data, size_t max); 16 static int vt_send(struct netdriver_data *data, size_t size); 17 static void vt_intr(unsigned int mask); 18 static void vt_stat(eth_stat_t *stat); 19 20 /* internal function */ 21 static int vt_probe(vt_driver *pdev, int instance); 22 static int vt_init_buf(vt_driver *pdev); 23 static int vt_init_hw(vt_driver *pdev, ether_addr_t *addr); 24 static int vt_reset_hw(vt_driver *pdev); 25 static void vt_conf_addr(vt_driver *pdev, ether_addr_t *addr); 26 static void vt_handler(vt_driver *pdev); 27 static void vt_check_ints(vt_driver *pdev); 28 29 /* developer interface */ 30 static void vt_init_rx_desc(vt_desc *desc, size_t size, phys_bytes dma); 31 static void vt_init_tx_desc(vt_desc *desc, size_t size, phys_bytes dma); 32 static int vt_real_reset(u32_t base); 33 static int vt_init_power(u32_t base); 34 static int vt_init_mii(u32_t base); 35 static int vt_init_io(u32_t base); 36 static void vt_start_rx_tx(u32_t base); 37 static void vt_get_addr(u32_t base, u8_t *pa); 38 static int vt_check_link(u32_t base); 39 static void vt_stop_rx_tx(u32_t base); 40 static int vt_rx_status_ok(vt_desc *desc); 41 static int vt_get_rx_len(vt_desc *desc); 42 static void vt_tx_desc_start(vt_desc *desc, size_t size); 43 static void vt_wakeup_tx(u32_t base); 44 static int vt_tx_status_ok(vt_desc *desc); 45 46 /* ======= Developer-defined function ======= */ 47 /* Intialize Rx descriptor (### RX_DESC_INIT ###) */ 48 static void vt_init_rx_desc(vt_desc *desc, size_t size, phys_bytes dma) { 49 desc->status = DESC_OWN | ((size << 16) & DESC_RX_LENMASK); 50 desc->addr = dma; 51 desc->length = size; 52 } 53 54 /* Intialize Tx descriptor (### TX_DESC_INIT ###) */ 55 static void vt_init_tx_desc(vt_desc *desc, size_t size, phys_bytes dma) { 56 desc->addr = dma; 57 desc->length = size; 58 } 59 60 /* Real hardware reset (### RESET_HARDWARE_CAN_FAIL ###) 61 * -- Return OK means success, Others means failure */ 62 static int vt_real_reset(u32_t base) { 63 vt_out16(base, REG_CR, CMD_RESET); 64 micro_delay(10000); 65 if (vt_in16(base, REG_CR) & CMD_RESET) { 66 vt_out8(base, REG_MCR1, 0x40); 67 micro_delay(10000); 68 if (vt_in16(base, REG_CR) & CMD_RESET) 69 return -EIO; 70 } 71 return OK; 72 } 73 74 /* Intialize power (### POWER_INIT_CAN_FAIL ###) 75 * -- Return OK means success, Others means failure */ 76 static int vt_init_power(u32_t base) { 77 u8_t stick; 78 stick = vt_in8(base, REG_STICK); 79 vt_out8(base, REG_STICK, stick & 0xfc); 80 return OK; 81 } 82 83 /* Intialize MII interface (### MII_INIT_CAN_FAIL ###) 84 * -- Return OK means success, Others means failure */ 85 static int vt_init_mii(u32_t base) { 86 return OK; 87 } 88 89 /* Intialize other hardware I/O registers (### INIT_HARDWARE_IO_CAN_FAIL ###) 90 * -- Return OK means success, Others means failure */ 91 static int vt_init_io(u32_t base) { 92 vt_out16(base, REG_BCR0, 0x0006); 93 vt_out8(base, REG_TCR, 0x20); 94 vt_out8(base, REG_RCR, 0x78); 95 return OK; 96 } 97 98 /* Start Rx/Tx (### START_RX_TX ###) */ 99 static void vt_start_rx_tx(u32_t base) { 100 u16_t cmd = CMD_START | CMD_RX_ON | CMD_TX_ON | CMD_NO_POLL | CMD_FDUPLEX; 101 vt_out16(base, REG_CR, cmd); 102 micro_delay(1000); 103 } 104 105 /* Get MAC address to the array 'pa' (### GET_MAC_ADDR ###) */ 106 static void vt_get_addr(u32_t base, u8_t *pa) { 107 int i; 108 for (i = 0; i < 6; i++) 109 pa[i] = vt_in8(base, REG_ADDR + i); 110 } 111 112 /* Check link status (### CHECK_LINK ###) 113 * -- Return LINK_UP or LINK_DOWN */ 114 static int vt_check_link(u32_t base) { 115 u32_t r; 116 vt_out8(base, REG_MII_CFG, 0x01); 117 vt_out8(base, REG_MII_ADDR, 0x01); 118 vt_out8(base, REG_MII_CR, 0x40); 119 micro_delay(10000); 120 r = vt_in16(base, REG_MII_DATA); 121 if (r & 0x0004) 122 return LINK_UP; 123 return LINK_DOWN; 124 } 125 126 /* Stop Rx/Tx (### STOP_RX_TX ###) */ 127 static void vt_stop_rx_tx(u32_t base) { 128 vt_out16(base, REG_CR, CMD_STOP); 129 } 130 131 /* Check whether Rx status OK (### CHECK_RX_STATUS_OK ###) 132 * -- Return TRUE or FALSE */ 133 static int vt_rx_status_ok(vt_desc *desc) { 134 if (!(desc->status & DESC_OWN)) { 135 if ((desc->status & DESC_RX_NORMAL) == DESC_RX_NORMAL) 136 return TRUE; 137 } 138 return FALSE; 139 } 140 141 /* Get Rx data length from descriptor (### GET_RX_LEN ###) 142 * --- Return the length */ 143 static int vt_get_rx_len(vt_desc *desc) { 144 int len; 145 len = ((desc->status & DESC_RX_LENMASK) >> 16) - ETH_CRC_SIZE; 146 return len; 147 } 148 149 /* Set Tx descriptor in send (### TX_DESC_START ###) */ 150 static void vt_tx_desc_start(vt_desc *desc, size_t size) { 151 desc->status = DESC_OWN | DESC_FIRST | DESC_LAST; 152 desc->length = 0x00e08000 | (size > 60 ? size : 60); 153 } 154 155 /* Wake up Tx channel (### WAKE_UP_TX ###) */ 156 static void vt_wakeup_tx(u32_t base) { 157 u8_t cmd; 158 cmd = vt_in8(base, REG_CR); 159 cmd |= CMD_TX_DEMAND; 160 vt_out8(base, REG_CR, cmd); 161 } 162 163 /* Check whether Tx status OK (### CHECK_TX_STATUS_OK ###) 164 * -- Return TRUE or FALSE */ 165 static int vt_tx_status_ok(vt_desc *desc) { 166 if (!(desc->status & DESC_OWN)) 167 return TRUE; 168 return FALSE; 169 } 170 171 /* Driver interface table */ 172 static const struct netdriver vt_table = { 173 .ndr_init = vt_init, 174 .ndr_stop = vt_stop, 175 .ndr_mode = vt_mode, 176 .ndr_recv = vt_recv, 177 .ndr_send = vt_send, 178 .ndr_stat = vt_stat, 179 .ndr_intr = vt_intr, 180 }; 181 182 int main(int argc, char *argv[]) { 183 env_setargs(argc, argv); 184 netdriver_task(&vt_table); 185 } 186 187 /* Initialize the driver */ 188 static int vt_init(unsigned int instance, ether_addr_t *addr) { 189 int ret = 0; 190 191 /* Intialize driver data structure */ 192 memset(&g_driver, 0, sizeof(g_driver)); 193 g_driver.link = LINK_UNKNOWN; 194 strcpy(g_driver.name, "netdriver#0"); 195 g_driver.name[10] += instance; 196 g_instance = instance; 197 198 /* Probe the device */ 199 if (vt_probe(&g_driver, instance)) { 200 printf("vt6105: Device is not found\n"); 201 ret = -ENODEV; 202 goto err_probe; 203 } 204 205 /* Allocate and initialize buffer */ 206 if (vt_init_buf(&g_driver)) { 207 printf("vt6105: Fail to initialize buffer\n"); 208 ret = -ENODEV; 209 goto err_init_buf; 210 } 211 212 /* Intialize hardware */ 213 if (vt_init_hw(&g_driver, addr)) { 214 printf("vt6105: Fail to initialize hardware\n"); 215 ret = -EIO; 216 goto err_init_hw; 217 } 218 219 /* Use a synchronous alarm instead of a watchdog timer */ 220 sys_setalarm(sys_hz(), 0); 221 222 /* Clear send and recv flag */ 223 g_driver.send_flag = FALSE; 224 g_driver.recv_flag = FALSE; 225 226 return 0; 227 228 err_init_hw: 229 free_contig(g_driver.buf, g_driver.buf_size); 230 err_init_buf: 231 err_probe: 232 return ret; 233 } 234 235 /* Match the device and get base address */ 236 static int vt_probe(vt_driver *pdev, int instance) { 237 int devind, ioflag; 238 u16_t cr, vid, did; 239 u32_t bar, size; 240 u8_t irq, rev; 241 u8_t *reg; 242 243 /* Find pci device */ 244 pci_init(); 245 if (!pci_first_dev(&devind, &vid, &did)) 246 return -EIO; 247 while (instance--) { 248 if (!pci_next_dev(&devind, &vid, &did)) 249 return -EIO; 250 } 251 pci_reserve(devind); 252 253 /* Enable bus mastering */ 254 cr = pci_attr_r16(devind, PCI_CR); 255 if (!(cr & PCI_CR_MAST_EN)) 256 pci_attr_w16(devind, PCI_CR, cr | PCI_CR_MAST_EN); 257 258 /* Get base address */ 259 #ifdef DMA_REG_MODE 260 if (pci_get_bar(devind, PCI_BAR, &base, &size, &ioflag)) { 261 printf("vt6105: Fail to get PCI BAR\n"); 262 return -EIO; 263 } 264 if (ioflag) { 265 printf("vt6105: PCI BAR is not for memory\n"); 266 return -EIO; 267 } 268 if ((reg = vm_map_phys(SELF, (void *)base, size)) == MAP_FAILED) { 269 printf("vt6105: Fail to map hardware registers from PCI\n"); 270 return -EIO; 271 } 272 pdev->base_addr = (u32_t)reg; 273 #else 274 bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; 275 if (bar < 0x400) { 276 printf("vt6105: Base address is not properly configured\n"); 277 return -EIO; 278 } 279 pdev->base_addr = bar; 280 #endif 281 282 /* Get irq number */ 283 irq = pci_attr_r8(devind, PCI_ILR); 284 pdev->irq = irq; 285 286 /* Get revision ID */ 287 rev = pci_attr_r8(devind, PCI_REV); 288 pdev->revision = rev; 289 290 #ifdef MY_DEBUG 291 printf("vt6105: Base address is 0x%08x\n", pdev->base_addr); 292 printf("vt6105: IRQ number is 0x%02x\n", pdev->irq); 293 printf("vt6105: Revision ID is 0x%02x\n", pdev->revision); 294 #endif 295 296 return 0; 297 } 298 299 /* Allocate and initialize buffer */ 300 static int vt_init_buf(vt_driver *pdev) { 301 size_t rx_desc_size, tx_desc_size, rx_buf_size, tx_buf_size, tot_buf_size; 302 vt_desc *desc; 303 phys_bytes buf_dma, next; 304 char *buf; 305 int i; 306 307 /* Build Rx and Tx descriptor buffer */ 308 rx_desc_size = RX_DESC_NUM * sizeof(vt_desc); 309 tx_desc_size = TX_DESC_NUM * sizeof(vt_desc); 310 311 /* Allocate Rx and Tx buffer */ 312 tx_buf_size = TX_BUF_SIZE; 313 if (tx_buf_size % 4) 314 tx_buf_size += 4 - (tx_buf_size % 4); 315 rx_buf_size = RX_BUF_SIZE; 316 tot_buf_size = rx_desc_size + tx_desc_size; 317 tot_buf_size += TX_DESC_NUM * tx_buf_size + RX_DESC_NUM * rx_buf_size; 318 if (tot_buf_size % 4096) 319 tot_buf_size += 4096 - (tot_buf_size % 4096); 320 321 if (!(buf = alloc_contig(tot_buf_size, 0, &buf_dma))) { 322 printf("vt6105: Fail to allocate memory\n"); 323 return -ENOMEM; 324 } 325 pdev->buf_size = tot_buf_size; 326 pdev->buf = buf; 327 328 /* Rx descriptor */ 329 pdev->rx_desc = (vt_desc *)buf; 330 pdev->rx_desc_dma = buf_dma; 331 memset(buf, 0, rx_desc_size); 332 buf += rx_desc_size; 333 buf_dma += rx_desc_size; 334 335 /* Tx descriptor */ 336 pdev->tx_desc = (vt_desc *)buf; 337 pdev->tx_desc_dma = buf_dma; 338 memset(buf, 0, tx_desc_size); 339 buf += tx_desc_size; 340 buf_dma += tx_desc_size; 341 342 /* Rx buffer assignment */ 343 desc = pdev->rx_desc; 344 next = pdev->rx_desc_dma; 345 for (i = 0; i < RX_DESC_NUM; i++) { 346 /* Set Rx buffer */ 347 pdev->rx[i].buf_dma = buf_dma; 348 pdev->rx[i].buf = buf; 349 buf_dma += rx_buf_size; 350 buf += rx_buf_size; 351 352 /* Set Rx descriptor */ 353 /* ### RX_DESC_INIT ### */ 354 vt_init_rx_desc(desc, rx_buf_size, pdev->rx[i].buf_dma); 355 if (i == (RX_DESC_NUM - 1)) 356 desc->next = pdev->rx_desc_dma; 357 else { 358 next += sizeof(vt_desc); 359 desc->next = next; 360 desc++; 361 } 362 } 363 364 /* Tx buffer assignment */ 365 desc = pdev->tx_desc; 366 next = pdev->tx_desc_dma; 367 for (i = 0; i < TX_DESC_NUM; i++) { 368 /* Set Tx buffer */ 369 pdev->tx[i].busy = 0; 370 pdev->tx[i].buf_dma = buf_dma; 371 pdev->tx[i].buf = buf; 372 buf_dma += tx_buf_size; 373 buf += tx_buf_size; 374 375 /* Set Rx descriptor */ 376 /* ### TX_DESC_INIT ### */ 377 vt_init_tx_desc(desc, tx_buf_size, pdev->tx[i].buf_dma); 378 if (i == (TX_DESC_NUM - 1)) 379 desc->next = pdev->tx_desc_dma; 380 else { 381 next += sizeof(vt_desc); 382 desc->next = next; 383 desc++; 384 } 385 } 386 pdev->tx_busy_num = 0; 387 pdev->tx_head = 0; 388 pdev->tx_tail = 0; 389 pdev->rx_head = 0; 390 391 return 0; 392 } 393 394 /* Intialize hardware */ 395 static int vt_init_hw(vt_driver *pdev, ether_addr_t *addr) { 396 int r, ret; 397 398 /* Set the OS interrupt handler */ 399 pdev->hook = pdev->irq; 400 if ((r = sys_irqsetpolicy(pdev->irq, 0, &pdev->hook)) != OK) { 401 printf("vt6105: Fail to set OS IRQ policy: %d\n", r); 402 ret = -EFAULT; 403 goto err_irq_policy; 404 } 405 406 /* Reset hardware */ 407 if (vt_reset_hw(pdev)) { 408 printf("vt6105: Fail to reset the device\n"); 409 ret = -EIO; 410 goto err_reset_hw; 411 } 412 413 /* Enable OS IRQ */ 414 if ((r = sys_irqenable(&pdev->hook)) != OK) { 415 printf("vt6105: Fail to enable OS IRQ: %d\n", r); 416 ret = -EFAULT; 417 goto err_irq_enable; 418 } 419 420 /* Configure MAC address */ 421 vt_conf_addr(pdev, addr); 422 423 /* Detect link status */ 424 pdev->link = vt_check_link(pdev->base_addr); 425 #ifdef MY_DEBUG 426 if (pdev->link) 427 printf("vt6105: Link up\n"); 428 else 429 printf("vt6105: Link down\n"); 430 #endif 431 432 return 0; 433 434 err_reset_hw: 435 err_irq_enable: 436 err_irq_policy: 437 return ret; 438 } 439 440 /* Reset hardware */ 441 static int vt_reset_hw(vt_driver *pdev) { 442 u32_t base = pdev->base_addr; 443 int ret; 444 445 /* Reset the chip */ 446 /* ### RESET_HARDWARE_CAN_FAIL ### */ 447 if (vt_real_reset(base)) { 448 printf("vt6105: Fail to reset the hardware\n"); 449 ret = -EIO; 450 goto err_real_reset; 451 } 452 453 /* Initialize power */ 454 /* ### POWER_INIT_CAN_FAIL ### */ 455 if (vt_init_power(base)) { 456 printf("vt6105: Fail to initialize power\n"); 457 ret = -EIO; 458 goto err_init_power; 459 } 460 461 /* Initialize MII interface */ 462 /* ### MII_INIT_CAN_FAIL ### */ 463 if (vt_init_mii(base)) { 464 printf("vt6105: Fail to initialize MII interface\n"); 465 ret = -EIO; 466 goto err_init_mii; 467 } 468 469 /* Initialize hardware I/O registers */ 470 /* ### SET_RX_DESC_REG ### */ 471 if (vt_init_io(base)) { 472 printf("vt6105: Fail to initialize I/O registers\n"); 473 ret = -EIO; 474 goto err_init_io; 475 } 476 477 /* Set Rx/Tx descriptor into register */ 478 /* ### SET_RX_DESC_REG ### */ 479 vt_out32(base, REG_RX_DESC_BASEL, pdev->rx_desc_dma); 480 #ifdef DESC_BASE_DMA64 481 vt_out32(base, REG_RX_DESC_BASEU, 0x00000000); 482 #endif 483 /* ### SET_TX_DESC_REG ### */ 484 vt_out32(base, REG_TX_DESC_BASEL, pdev->tx_desc_dma); 485 #ifdef DESC_BASE_DMA64 486 vt_out32(base, REG_TX_DESC_BASEU, 0x00000000); 487 #endif 488 489 /* Enable interrupts */ 490 /* ### ENABLE_INTR ### */ 491 vt_out16(base, REG_IMR, INTR_IMR_ENABLE); 492 493 /* Start the device, Rx and Tx */ 494 /* ### START_RX_TX ### */ 495 vt_start_rx_tx(base); 496 497 return 0; 498 499 err_init_io: 500 err_init_mii: 501 err_init_power: 502 err_real_reset: 503 return ret; 504 } 505 506 /* Configure MAC address */ 507 static void vt_conf_addr(vt_driver *pdev, ether_addr_t *addr) { 508 u8_t pa[6]; 509 u32_t base = pdev->base_addr; 510 511 /* Get MAC address */ 512 /* ### GET_MAC_ADDR ### */ 513 vt_get_addr(base, pa); 514 addr->ea_addr[0] = pa[0]; 515 addr->ea_addr[1] = pa[1]; 516 addr->ea_addr[2] = pa[2]; 517 addr->ea_addr[3] = pa[3]; 518 addr->ea_addr[4] = pa[4]; 519 addr->ea_addr[5] = pa[5]; 520 #ifdef MY_DEBUG 521 printf("vt6105: Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n", 522 addr->ea_addr[0], addr->ea_addr[1], addr->ea_addr[2], 523 addr->ea_addr[3], addr->ea_addr[4], addr->ea_addr[5]); 524 #endif 525 } 526 527 /* Stop the driver */ 528 static void vt_stop(void) { 529 u32_t base = g_driver.base_addr; 530 531 /* Free Rx and Tx buffer*/ 532 free_contig(g_driver.buf, g_driver.buf_size); 533 534 /* Stop interrupt */ 535 /* ### DISABLE_INTR ### */ 536 vt_out16(base, REG_IMR, INTR_IMR_DISABLE); 537 538 /* Stop Rx/Tx */ 539 /* ### STOP_RX_TX ### */ 540 vt_stop_rx_tx(base); 541 } 542 543 /* Set driver mode */ 544 static void vt_mode(unsigned int mode) { 545 vt_driver *pdev = &g_driver; 546 u32_t base = pdev->base_addr; 547 u8_t rcr; 548 549 pdev->mode = mode; 550 551 /* ### READ_RCR ### */ 552 rcr = vt_in8(base, REG_RCR); 553 rcr &= ~(RCR_UNICAST | RCR_MULTICAST | RCR_BROADCAST); 554 if (pdev->mode & NDEV_PROMISC) 555 rcr |= RCR_UNICAST | RCR_MULTICAST; 556 if (pdev->mode & NDEV_BROAD) 557 rcr |= RCR_BROADCAST; 558 if (pdev->mode & NDEV_MULTI) 559 rcr |= RCR_MULTICAST; 560 rcr |= RCR_UNICAST; 561 /* ### WRITE_RCR ### */ 562 vt_out8(base, REG_RCR, rcr); 563 } 564 565 /* Receive data */ 566 static ssize_t vt_recv(struct netdriver_data *data, size_t max) { 567 vt_driver *pdev = &g_driver; 568 u32_t totlen, packlen; 569 vt_desc *desc; 570 int index, i; 571 572 index = pdev->rx_head; 573 desc = pdev->rx_desc; 574 desc += index; 575 576 /* Check whether the receiving is OK */ 577 /* ### CHECK_RX_STATUS_OK ### */ 578 if (vt_rx_status_ok(desc) != TRUE) 579 return SUSPEND; 580 581 /* Check Rx status error */ 582 /* ### CHECK_RX_STATUS_ERROR ### */ 583 if (desc->status & DESC_STATUS_RX_RECV_ERR) 584 printf("vt6105: Rx error\n"); 585 586 /* Get data length */ 587 /* ### Get Rx data length ### */ 588 totlen = vt_get_rx_len(desc); 589 if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) { 590 printf("vt6105: Bad data length: %d\n", totlen); 591 panic(NULL); 592 } 593 594 packlen = totlen; 595 if (packlen > max) 596 packlen = max; 597 598 /* Copy data to user */ 599 netdriver_copyout(data, 0, pdev->rx[index].buf, packlen); 600 pdev->stat.ets_packetR++; 601 602 /* Set Rx descriptor status */ 603 /* ### SET_RX_STATUS_INTR ### */ 604 desc->status = DESC_STATUS_RX_RECV_CLEAR; 605 if (index == RX_DESC_NUM - 1) 606 index = 0; 607 else 608 index++; 609 pdev->rx_head = index; 610 611 #ifdef MY_DEBUG 612 printf("vt6105: Successfully receive a packet, length = %d\n", packlen); 613 #endif 614 615 return packlen; 616 } 617 618 /* Transmit data */ 619 static int vt_send(struct netdriver_data *data, size_t size) { 620 vt_driver *pdev = &g_driver; 621 vt_desc *desc; 622 int tx_head, i; 623 u32_t base = pdev->base_addr; 624 625 tx_head = pdev->tx_head; 626 desc = pdev->tx_desc; 627 desc += tx_head; 628 629 if (pdev->tx[tx_head].busy) 630 return SUSPEND; 631 632 /* Copy data from user */ 633 netdriver_copyin(data, 0, pdev->tx[tx_head].buf, size); 634 635 /* Set busy */ 636 pdev->tx[tx_head].busy = TRUE; 637 pdev->tx_busy_num++; 638 639 /* Set Tx descriptor status */ 640 /* ### TX_DESC_START ### */ 641 vt_tx_desc_start(desc, size); 642 if (tx_head == TX_DESC_NUM - 1) 643 tx_head = 0; 644 else 645 tx_head++; 646 pdev->tx_head = tx_head; 647 648 /* Wake up transmit channel */ 649 /* ### WAKE_UP_TX ### */ 650 vt_wakeup_tx(base); 651 652 return 0; 653 } 654 655 /* Handle Interrupt */ 656 static void vt_intr(unsigned int mask) { 657 int s; 658 659 /* Run interrupt handler at driver level */ 660 vt_handler(&g_driver); 661 662 /* Reenable interrupts for this hook */ 663 if ((s = sys_irqenable(&g_driver.hook)) != OK) 664 printf("vt6105: Cannot enable OS interrupts: %d\n", s); 665 666 /* Perform tasks based on the flagged conditions */ 667 vt_check_ints(&g_driver); 668 } 669 670 /* Real handler interrupt */ 671 static void vt_handler(vt_driver *pdev) { 672 u32_t base = pdev->base_addr; 673 u16_t intr_status; 674 int flag = 0, tx_head, tx_tail; 675 vt_desc *desc; 676 677 /* Get interrupt status */ 678 /* ### GET_INTR_STATUS ### */ 679 intr_status = vt_in16(base, REG_ISR); 680 681 /* Clear interrupt */ 682 /* ### CLEAR_INTR ### */ 683 vt_out16(base, REG_ISR, intr_status & INTR_ISR_CLEAR); 684 685 /* Enable interrupt */ 686 /* ### ENABLE_INTR ### */ 687 vt_out16(base, REG_IMR, INTR_IMR_ENABLE); 688 689 /* Check interrupt error */ 690 /* ### CHECK_INTR_ERROR ### */ 691 if (intr_status & INTR_ISR_ERR) { 692 printf("vt6105: interrupt error\n"); 693 return; 694 } 695 696 /* Check link status */ 697 /* ### CHECK_LINK_INTR ### */ 698 if (intr_status & INTR_ISR_LINK_EVENT) { 699 pdev->link = vt_check_link(base); 700 #ifdef MY_DEBUG 701 printf("vt6105: Link state change\n"); 702 #endif 703 flag++; 704 } 705 706 /* Check Rx request status */ 707 /* ### CHECK_RX_INTR ### */ 708 if (intr_status & INTR_ISR_RX_DONE) { 709 pdev->recv_flag = TRUE; 710 flag++; 711 } 712 713 /* Check Tx request status */ 714 /* ### CHECK_TX_INTR ### */ 715 if (intr_status & INTR_ISR_TX_DONE) { 716 pdev->send_flag = TRUE; 717 flag++; 718 719 /* Manage Tx Buffer */ 720 tx_head = pdev->tx_head; 721 tx_tail = pdev->tx_tail; 722 while (tx_tail != tx_head) { 723 desc = pdev->tx_desc; 724 desc += tx_tail; 725 if (!pdev->tx[tx_tail].busy) 726 printf("vt6105: Strange, buffer not busy?\n"); 727 728 /* Check whether the transmiting is OK */ 729 /* ### CHECK_TX_STATUS_OK ### */ 730 if (vt_tx_status_ok(desc) != TRUE) 731 break; 732 733 /* Check Tx status error */ 734 /* ### CHECK_TX_STATUS_ERROR ### */ 735 if (desc->status & DESC_STATUS_TX_SEND_ERR) 736 printf("vt6105: Tx error\n"); 737 738 pdev->stat.ets_packetT++; 739 pdev->tx[tx_tail].busy = FALSE; 740 pdev->tx_busy_num--; 741 742 if (++tx_tail >= TX_DESC_NUM) 743 tx_tail = 0; 744 745 pdev->send_flag = TRUE; 746 pdev->recv_flag = TRUE; 747 748 /* Set Tx descriptor status in interrupt */ 749 /* ### SET_TX_STATUS_INTR ### */ 750 desc->status = DESC_STATUS_TX_SEND_CLEAR; 751 752 #ifdef MY_DEBUG 753 printf("vt6105: Successfully send a packet\n"); 754 #endif 755 } 756 pdev->tx_tail = tx_tail; 757 } 758 #ifdef MY_DEBUG 759 if (!flag) { 760 printf("vt6105: Unknown error in interrupt\n"); 761 return; 762 } 763 #endif 764 } 765 766 /* Check interrupt and perform */ 767 static void vt_check_ints(vt_driver *pdev) { 768 if (!pdev->recv_flag) 769 return; 770 pdev->recv_flag = FALSE; 771 772 /* Handle data receive */ 773 netdriver_recv(); 774 775 /* Handle data transmit */ 776 if (pdev->send_flag) { 777 pdev->send_flag = FALSE; 778 netdriver_send(); 779 } 780 } 781 782 static void vt_stat(eth_stat_t *stat) { 783 memcpy(stat, &g_driver.stat, sizeof(*stat)); 784 } 785