1 #include <minix/drivers.h> 2 #include <minix/netdriver.h> 3 #include <machine/pci.h> 4 #include <sys/mman.h> 5 #include "vt6105.h" 6 #include "io.h" 7 8 /* global value */ 9 static NDR_driver g_driver; 10 static int g_instance; 11 12 /* driver interface */ 13 static int NDR_init(unsigned int instance, netdriver_addr_t * addr, 14 uint32_t * caps, unsigned int * ticks); 15 static void NDR_stop(void); 16 static void NDR_set_mode(unsigned int mode, 17 const netdriver_addr_t * mcast_list, unsigned int mcast_count); 18 static ssize_t NDR_recv(struct netdriver_data *data, size_t max); 19 static int NDR_send(struct netdriver_data *data, size_t size); 20 static void NDR_intr(unsigned int mask); 21 22 /* internal function */ 23 static int dev_probe(NDR_driver *pdev, int instance); 24 static int dev_init_buf(NDR_driver *pdev); 25 static int dev_init_hw(NDR_driver *pdev, netdriver_addr_t *addr); 26 static int dev_reset_hw(NDR_driver *pdev); 27 static void dev_conf_addr(NDR_driver *pdev, netdriver_addr_t *addr); 28 static void dev_handler(NDR_driver *pdev); 29 static void dev_check_ints(NDR_driver *pdev); 30 31 /* developer interface */ 32 static int dev_real_reset(u32_t *base); 33 static int dev_init_io(u32_t *base); 34 static int dev_init_mii(u32_t *base); 35 static void dev_intr_control(u32_t *base, int flag); 36 static void dev_rx_tx_control(u32_t *base, int flag); 37 static void dev_get_addr(u32_t *base, u8_t *pa); 38 static int dev_check_link(u32_t *base); 39 static void dev_set_rec_mode(u32_t *base, int mode); 40 static void dev_start_tx(u32_t *base); 41 static u32_t dev_read_clear_intr_status(u32_t *base); 42 static void dev_init_rx_desc(NDR_desc *desc_start, int index, size_t buf_size, 43 phys_bytes buf_dma, int max_desc_num, phys_bytes desc_dma_start); 44 static void dev_init_tx_desc(NDR_desc *desc_start, int index, size_t buf_size, 45 phys_bytes buf_dma, int max_desc_num, phys_bytes desc_dma_start); 46 static void dev_set_desc_reg(u32_t *base, phys_bytes rx_addr, 47 phys_bytes tx_addr); 48 static int dev_rx_ok_desc(u32_t *base, NDR_desc *desc, int index); 49 static int dev_rx_len_desc(u32_t *base, NDR_desc *desc, int index); 50 static void dev_set_rx_desc_done(u32_t *base, NDR_desc *desc, int index); 51 static void dev_set_tx_desc_prepare(u32_t *base, NDR_desc *desc, int index, 52 size_t data_size); 53 static int dev_tx_ok_desc(u32_t *base, NDR_desc *desc, int index); 54 static void dev_set_tx_desc_done(u32_t *base, NDR_desc *desc, int index); 55 56 /* ======= Developer implemented function ======= */ 57 /* ====== Self-defined function ======*/ 58 59 /* ====== Developer interface ======*/ 60 /* Real hardware reset (### RESET_HARDWARE_CAN_FAIL ###) 61 * -- Return OK means success, Others means failure */ 62 static int dev_real_reset(u32_t *base) { 63 u32_t base0 = base[0]; 64 ndr_out16(base0, REG_CR, CMD_RESET); 65 micro_delay(5000); 66 if (ndr_in16(base0, REG_CR) & CMD_RESET) { 67 ndr_out8(base0, REG_MCR, 0x40); 68 micro_delay(5000); 69 if (ndr_in16(base0, REG_CR) & CMD_RESET) 70 return -EIO; 71 } 72 return OK; 73 } 74 75 /* Intialize other hardware I/O registers (### INIT_HARDWARE_IO_CAN_FAIL ###) 76 * -- Return OK means success, Others means failure */ 77 static int dev_init_io(u32_t *base) { 78 u32_t base0 = base[0]; 79 u8_t stick; 80 stick = ndr_in8(base0, REG_STICK); 81 ndr_out8(base0, REG_STICK, stick & 0xfc); 82 ndr_out16(base0, REG_BCR, 0x0006); 83 ndr_out8(base0, REG_TCR, 0x20); 84 ndr_out8(base0, REG_RCR, 0x78); 85 return OK; 86 } 87 88 /* Intialize MII interface (### MII_INIT_CAN_FAIL ###) 89 -- Return OK means success, Others means failure */ 90 static int dev_init_mii(u32_t *base) { 91 u32_t base0 = base[0]; 92 ndr_out8(base0, REG_MII_CR, 0); 93 ndr_out8(base0, REG_MII_REG, 0x01); 94 ndr_out8(base0, REG_MII_CR, 0x80); 95 micro_delay(5000); 96 if (!(ndr_in8(base0, REG_MII_REG) & 0x20)) { 97 printf("NDR: Fail to monitor linkage\n"); 98 return -EIO; 99 } 100 ndr_out8(base0, REG_MII_REG, 0x41); 101 return OK; 102 } 103 104 /* Enable or disable interrupt (### INTR_ENABLE_DISABLE ###) */ 105 static void dev_intr_control(u32_t *base, int flag) { 106 u32_t data, base0 = base[0]; 107 data = ndr_in16(base0, REG_IMR); 108 if (flag == INTR_ENABLE) 109 ndr_out16(base0, REG_IMR, data | CMD_INTR_ENABLE); 110 else if (flag == INTR_DISABLE) 111 ndr_out16(base0, REG_IMR, data & ~CMD_INTR_ENABLE); 112 } 113 114 /* Enable or disable Rx/Tx (### RX_TX_ENABLE_DISABLE ###) */ 115 static void dev_rx_tx_control(u32_t *base, int flag) { 116 u32_t data, base0 = base[0]; 117 if (flag == RX_TX_ENABLE) { 118 data = CMD_START | CMD_RX_ON | CMD_TX_ON | CMD_NO_POLL | CMD_FDUPLEX; 119 ndr_out16(base0, REG_CR, data); 120 } 121 else if (flag == RX_TX_DISABLE) { 122 ndr_out16(base0, REG_CR, CMD_STOP); 123 } 124 } 125 126 /* Get MAC address to the array 'pa' (### GET_MAC_ADDR ###) */ 127 static void dev_get_addr(u32_t *base, u8_t *pa) { 128 u32_t i, base0 = base[0]; 129 for (i = 0; i < 6; i++) 130 pa[i] = ndr_in8(base0, REG_ADDR + i); 131 } 132 133 /* Check link status (### CHECK_LINK ###) 134 * -- Return LINK_UP or LINK_DOWN */ 135 static int dev_check_link(u32_t *base) { 136 u32_t data, base0 = base[0]; 137 ndr_out8(base0, REG_MII_PHY, 0x01); 138 ndr_out8(base0, REG_MII_REG, 0x01); 139 ndr_out8(base0, REG_MII_CR, 0x40); 140 micro_delay(5000); 141 if (ndr_in8(base0, REG_MII_CR) & 0x40) 142 printf("NDR: Fail to get linkage\n"); 143 data = ndr_in16(base0, REG_MII_DATA); 144 if (data & LINK_STATUS) 145 return LINK_UP; 146 return LINK_DOWN; 147 } 148 149 /* Set driver receive mode (### SET_REC_MODE ###) */ 150 static void dev_set_rec_mode(u32_t *base, int mode) { 151 u32_t data, base0 = base[0]; 152 data = ndr_in8(base0, REG_RCR); 153 data &= ~(CMD_RCR_UNICAST | CMD_RCR_MULTICAST | CMD_RCR_BROADCAST); 154 if (mode & NDEV_MODE_PROMISC) 155 data |= CMD_RCR_UNICAST | CMD_RCR_BROADCAST | CMD_RCR_MULTICAST; 156 if (mode & NDEV_MODE_BCAST) 157 data |= CMD_RCR_BROADCAST; 158 if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL)) 159 data |= CMD_RCR_MULTICAST; 160 data |= CMD_RCR_UNICAST; 161 ndr_out8(base0, REG_RCR, data); 162 } 163 164 /* Start Tx channel (### START_TX_CHANNEL ###) */ 165 static void dev_start_tx(u32_t *base) { 166 u32_t data, base0 = base[0]; 167 data = ndr_in8(base0, REG_CR); 168 ndr_out8(base0, REG_CR, data | CMD_TX_DEMAND); 169 } 170 171 /* Read and clear interrupt (### READ_CLEAR_INTR_STS ###) */ 172 static u32_t dev_read_clear_intr_status(u32_t *base) { 173 u32_t data, base0 = base[0]; 174 data = ndr_in16(base0, REG_ISR); 175 ndr_out16(base0, REG_ISR, data & INTR_STS_CLEAR); 176 return data; 177 } 178 179 /* ---------- WITH DESCRIPTOR ---------- */ 180 /* Intialize Rx descriptor (### INIT_RX_DESC ###) */ 181 static void dev_init_rx_desc(NDR_desc *desc_start, int index, size_t buf_size, 182 phys_bytes buf_dma, int max_desc_num, phys_bytes desc_dma_start) { 183 NDR_desc *desc = desc_start + index; 184 desc->status = DESC_OWN | ((buf_size << 16) & DESC_RX_LENMASK); 185 desc->addr = buf_dma; 186 desc->length = buf_size; 187 if (index == max_desc_num - 1) 188 desc->next = desc_dma_start; 189 else 190 desc->next = desc_dma_start + (index + 1) * sizeof(NDR_desc); 191 } 192 193 /* Intialize Tx descriptor (### INIT_TX_DESC ###) */ 194 static void dev_init_tx_desc(NDR_desc *desc_start, int index, size_t buf_size, 195 phys_bytes buf_dma, int max_desc_num, phys_bytes desc_dma_start) { 196 NDR_desc *desc = desc_start + index; 197 desc->addr = buf_dma; 198 desc->length = buf_size; 199 if (index == max_desc_num - 1) 200 desc->next = desc_dma_start; 201 else 202 desc->next = desc_dma_start + (index + 1) * sizeof(NDR_desc); 203 } 204 205 /* Set Rx/Tx descriptor address into device register (### SET_DESC_REG ###) */ 206 static void dev_set_desc_reg(u32_t *base, phys_bytes rx_addr, 207 phys_bytes tx_addr) { 208 u32_t base0 = base[0]; 209 ndr_out32(base0, REG_RX_DESC_BASE, rx_addr); 210 ndr_out32(base0, REG_TX_DESC_BASE, tx_addr); 211 } 212 213 /* Check whether Rx is OK from Rx descriptor (### CHECK_RX_OK_FROM_DESC ###) 214 * -- Current buffer number is index 215 * -- Return RX_OK or RX_SUSPEND or RX_ERROR */ 216 static int dev_rx_ok_desc(u32_t *base, NDR_desc *desc, int index) { 217 if (!(desc->status & DESC_OWN)) { 218 if (desc->status & DESC_RX_ERROR) 219 return RX_ERROR; 220 if ((desc->status & DESC_RX_NORMAL) == DESC_RX_NORMAL) 221 return RX_OK; 222 } 223 return RX_SUSPEND; 224 } 225 226 /* Get length from Rx descriptor (### GET_RX_LENGTH_FROM_DESC ###) 227 * -- Current buffer number is index 228 * -- Return the length */ 229 static int dev_rx_len_desc(u32_t *base, NDR_desc *desc, int index) { 230 return ((desc->status & DESC_RX_LENMASK) >> 16) - NDEV_ETH_PACKET_CRC; 231 } 232 233 /* Set Rx descriptor after Rx done (### SET_RX_DESC_DONE ###) 234 * -- Current buffer number is index */ 235 static void dev_set_rx_desc_done(u32_t *base, NDR_desc *desc, int index) { 236 desc->status = DESC_OWN; 237 } 238 239 /* Set Tx descriptor to prepare transmitting (### SET_TX_DESC_PREPARE) 240 * -- Current buffer number is index */ 241 static void dev_set_tx_desc_prepare(u32_t *base, NDR_desc *desc, int index, 242 size_t data_size) { 243 desc->status = DESC_OWN | DESC_FIRST | DESC_LAST; 244 desc->length = 0x00e08000 | (data_size > 60 ? data_size : 60); 245 } 246 247 /* Check whether Tx is OK from Tx descriptor (### CHECK_TX_OK_FROM_DESC ###) 248 * -- Current buffer number is index 249 * -- Return TX_OK or TX_SUSPEND or TX_ERROR */ 250 static int dev_tx_ok_desc(u32_t *base, NDR_desc *desc, int index) { 251 if (!(desc->status & DESC_OWN)) { 252 if (desc->status & DESC_TX_ERROR) 253 return TX_ERROR; 254 return TX_OK; 255 } 256 return TX_SUSPEND; 257 } 258 259 /* Set Tx descriptor after Tx done (### SET_TX_DESC_DONE ###) 260 * -- Current buffer number is index */ 261 static void dev_set_tx_desc_done(u32_t *base, NDR_desc *desc, int index) { 262 desc->status = 0; 263 } 264 265 /* Driver interface table */ 266 static const struct netdriver NDR_table = { 267 .ndr_name = "vr", 268 .ndr_init = NDR_init, 269 .ndr_stop = NDR_stop, 270 .ndr_set_mode = NDR_set_mode, 271 .ndr_recv = NDR_recv, 272 .ndr_send = NDR_send, 273 .ndr_intr = NDR_intr, 274 }; 275 276 int main(int argc, char *argv[]) { 277 env_setargs(argc, argv); 278 netdriver_task(&NDR_table); 279 } 280 281 /* Initialize the driver */ 282 static int 283 NDR_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps, 284 unsigned int * ticks __unused) 285 { 286 int i, ret = 0; 287 288 /* Intialize driver data structure */ 289 memset(&g_driver, 0, sizeof(g_driver)); 290 g_driver.link = LINK_UNKNOWN; 291 g_instance = instance; 292 293 /* Probe the device */ 294 if (dev_probe(&g_driver, instance)) { 295 printf("NDR: Device is not found\n"); 296 ret = -ENODEV; 297 goto err_probe; 298 } 299 300 /* Intialize hardware */ 301 if (dev_init_hw(&g_driver, addr)) { 302 printf("NDR: Fail to initialize hardware\n"); 303 ret = -EIO; 304 goto err_init_hw; 305 } 306 307 /* Allocate and initialize buffer */ 308 if (dev_init_buf(&g_driver)) { 309 printf("NDR: Fail to initialize buffer\n"); 310 ret = -ENODEV; 311 goto err_init_buf; 312 } 313 314 /* Enable interrupts */ 315 /* ### INTR_ENABLE_DISABLE ### */ 316 dev_intr_control(g_driver.base, INTR_ENABLE); 317 318 /* Start Rx and Tx */ 319 /* ### RX_TX_ENABLE_DISABLE ### */ 320 dev_rx_tx_control(g_driver.base, RX_TX_ENABLE); 321 322 /* Clear send and recv flag */ 323 g_driver.send_flag = FALSE; 324 g_driver.recv_flag = FALSE; 325 326 *caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST; 327 return OK; 328 329 err_init_buf: 330 err_init_hw: 331 err_probe: 332 return ret; 333 } 334 335 /* Stop the driver */ 336 static void NDR_stop(void) { 337 /* Free Rx and Tx buffer*/ 338 free_contig(g_driver.buf, g_driver.buf_size); 339 340 /* Stop interrupt */ 341 /* ### INTR_ENABLE_DISABLE ### */ 342 dev_intr_control(g_driver.base, INTR_DISABLE); 343 344 /* Stop Rx and Tx */ 345 /* ### RX_TX_ENABLE_DISABLE ### */ 346 dev_rx_tx_control(g_driver.base, RX_TX_DISABLE); 347 } 348 349 /* Set driver mode */ 350 static void 351 NDR_set_mode(unsigned int mode, const netdriver_addr_t * mcast_list __unused, 352 unsigned int mcast_count __unused) 353 { 354 g_driver.mode = mode; 355 /* Set driver receive mode */ 356 /* ### SET_REC_MODE ### */ 357 dev_set_rec_mode(g_driver.base, mode); 358 } 359 360 /* Receive data */ 361 static ssize_t NDR_recv(struct netdriver_data *data, size_t max) { 362 NDR_driver *pdev = &g_driver; 363 u32_t totlen, packlen; 364 int index, ret, offset = 0; 365 NDR_desc *desc; 366 367 index = pdev->rx_head; 368 desc = pdev->rx_desc; 369 desc += index; 370 /* Check whether Rx is OK from Rx descriptor */ 371 /* ### CHECK_RX_OK_FROM_DESC ### */ 372 ret = dev_rx_ok_desc(pdev->base, desc, index); 373 if (ret == RX_SUSPEND) 374 return SUSPEND; 375 else if (ret == RX_ERROR) 376 printf("NDR: Rx error now\n"); 377 /* Get length from Rx descriptor */ 378 /* ### GET_RX_LENGTH_FROM_DESC ### */ 379 totlen = dev_rx_len_desc(pdev->base, desc, index); 380 381 /* Get data length */ 382 /* ### Get , int inde, int indexxRx data length ### */ 383 if (totlen < 8 || totlen > 2 * NDEV_ETH_PACKET_MAX) { 384 printf("NDR: Bad data length: %d\n", totlen); 385 panic(NULL); 386 } 387 388 packlen = totlen; 389 if (packlen > max) 390 packlen = max; 391 392 /* Copy data to user */ 393 netdriver_copyout(data, 0, pdev->rx[index].buf + offset, packlen); 394 395 /* Set Rx descriptor after Rx done */ 396 /* ### SET_RX_DESC_DONE ### */ 397 dev_set_rx_desc_done(pdev->base, desc, index); 398 if (index == RX_BUFFER_NUM - 1) 399 index = 0; 400 else 401 index++; 402 pdev->rx_head = index; 403 404 #ifdef MY_DEBUG 405 printf("NDR: Successfully receive a packet, length = %d\n", packlen); 406 #endif 407 408 return packlen; 409 } 410 411 /* Transmit data */ 412 static int NDR_send(struct netdriver_data *data, size_t size) { 413 NDR_driver *pdev = &g_driver; 414 int tx_head, i; 415 NDR_desc *desc; 416 417 tx_head = pdev->tx_head; 418 if (pdev->tx[tx_head].busy) 419 return SUSPEND; 420 421 /* Copy data from user */ 422 netdriver_copyin(data, 0, pdev->tx[tx_head].buf, size); 423 424 /* Set busy */ 425 pdev->tx[tx_head].busy = TRUE; 426 pdev->tx_busy_num++; 427 428 desc = pdev->tx_desc; 429 desc += tx_head; 430 /* Set Tx descriptor to prepare transmitting */ 431 /* ### SET_TX_DESC_PREPARE ### */ 432 dev_set_tx_desc_prepare(pdev->base, desc, tx_head, size); 433 if (tx_head == TX_BUFFER_NUM - 1) 434 tx_head = 0; 435 else 436 tx_head++; 437 pdev->tx_head = tx_head; 438 439 /* Start Tx channel */ 440 /* ### START_TX ### */ 441 dev_start_tx(pdev->base); 442 443 return 0; 444 } 445 446 /* Handle interrupt */ 447 static void NDR_intr(unsigned int mask) { 448 int s; 449 450 /* Run interrupt handler at driver level */ 451 dev_handler(&g_driver); 452 453 /* Reenable interrupts for this hook */ 454 if ((s = sys_irqenable(&g_driver.hook)) != OK) 455 printf("NDR: Cannot enable OS interrupts: %d\n", s); 456 457 /* Perform tasks based on the flagged conditions */ 458 dev_check_ints(&g_driver); 459 } 460 461 /* Match the device and get base address */ 462 static int dev_probe(NDR_driver *pdev, int instance) { 463 int devind, ioflag, i; 464 u16_t cr, vid, did; 465 u32_t bar, size, base; 466 u8_t irq, rev; 467 u8_t *reg; 468 469 /* Find pci device */ 470 pci_init(); 471 if (!pci_first_dev(&devind, &vid, &did)) 472 return -EIO; 473 while (instance--) { 474 if (!pci_next_dev(&devind, &vid, &did)) 475 return -EIO; 476 } 477 pci_reserve(devind); 478 479 /* Enable bus mastering and I/O space */ 480 cr = pci_attr_r16(devind, PCI_CR); 481 pci_attr_w16(devind, PCI_CR, cr | 0x105); 482 483 /* Get base address */ 484 for (i = 0; i < 6; i++) 485 pdev->base[i] = 0; 486 #ifdef DMA_BASE_IOMAP 487 for (i = 0; i < 6; i++) { 488 if (pci_get_bar(devind, PCI_BAR + i * 4, &base, &size, &ioflag)) { 489 /* printf("NDR: Fail to get PCI BAR\n"); */ 490 continue; 491 } 492 if (ioflag) { 493 /* printf("NDR: PCI BAR is not for memory\n"); */ 494 continue; 495 } 496 if ((reg = vm_map_phys(SELF, (void *)base, size)) == MAP_FAILED) { 497 printf("NDR: Fail to map hardware registers from PCI\n"); 498 return -EIO; 499 } 500 pdev->base[i] = (u32_t)reg; 501 } 502 #else 503 for (i = 0; i < 6; i++) 504 pdev->base[i] = pci_attr_r32(devind, PCI_BAR + i * 4) & 0xffffffe0; 505 #endif 506 pdev->dev_name = pci_dev_name(vid, did); 507 pdev->irq = pci_attr_r8(devind, PCI_ILR); 508 pdev->revision = pci_attr_r8(devind, PCI_REV); 509 pdev->did = did; 510 pdev->vid = vid; 511 pdev->devind = devind; 512 513 #ifdef MY_DEBUG 514 printf("NDR: Hardware name is %s\n", pdev->dev_name); 515 for (i = 0; i < 6; i++) 516 printf("NDR: PCI BAR%d is 0x%08x\n", i, pdev->base[i]); 517 printf("NDR: IRQ number is 0x%02x\n", pdev->irq); 518 #endif 519 520 return 0; 521 } 522 523 /* Intialize hardware */ 524 static int dev_init_hw(NDR_driver *pdev, netdriver_addr_t *addr) { 525 int r, ret; 526 527 /* Set the OS interrupt handler */ 528 pdev->hook = pdev->irq; 529 if ((r = sys_irqsetpolicy(pdev->irq, 0, &pdev->hook)) != OK) { 530 printf("NDR: Fail to set OS IRQ policy: %d\n", r); 531 ret = -EFAULT; 532 goto err_irq_policy; 533 } 534 535 /* Reset hardware */ 536 if (dev_reset_hw(pdev)) { 537 printf("NDR: Fail to reset the device\n"); 538 ret = -EIO; 539 goto err_reset_hw; 540 } 541 542 /* Enable OS IRQ */ 543 if ((r = sys_irqenable(&pdev->hook)) != OK) { 544 printf("NDR: Fail to enable OS IRQ: %d\n", r); 545 ret = -EFAULT; 546 goto err_irq_enable; 547 } 548 549 /* Configure MAC address */ 550 dev_conf_addr(pdev, addr); 551 552 /* Detect link status */ 553 /* ### CHECK_LINK ### */ 554 pdev->link = dev_check_link(pdev->base); 555 #ifdef MY_DEBUG 556 if (pdev->link) 557 printf("NDR: Link up\n"); 558 else 559 printf("NDR: Link down\n"); 560 #endif 561 562 return 0; 563 564 err_reset_hw: 565 err_irq_enable: 566 err_irq_policy: 567 return ret; 568 } 569 570 /* Reset hardware */ 571 static int dev_reset_hw(NDR_driver *pdev) { 572 int ret; 573 574 /* Reset the chip */ 575 /* ### RESET_HARDWARE_CAN_FAIL ### */ 576 if (dev_real_reset(pdev->base)) { 577 printf("NDR: Fail to reset the hardware\n"); 578 ret = -EIO; 579 goto err_real_reset; 580 } 581 582 /* Initialize other hardware I/O registers */ 583 /* ### SET_RX_DESC_REG ### */ 584 if (dev_init_io(pdev->base)) { 585 printf("NDR: Fail to initialize I/O registers\n"); 586 ret = -EIO; 587 goto err_init_io; 588 } 589 590 /* Initialize MII interface */ 591 /* ### MII_INIT_CAN_FAIL ### */ 592 if (dev_init_mii(pdev->base)) { 593 printf("NDR: Fail to initialize MII interface\n"); 594 ret = -EIO; 595 goto err_init_mii; 596 } 597 598 return 0; 599 600 err_init_mii: 601 err_init_io: 602 err_real_reset: 603 return ret; 604 } 605 606 /* Configure MAC address */ 607 static void dev_conf_addr(NDR_driver *pdev, netdriver_addr_t *addr) { 608 u8_t pa[6]; 609 610 /* Get MAC address */ 611 /* ### GET_MAC_ADDR ### */ 612 dev_get_addr(pdev->base, pa); 613 addr->na_addr[0] = pa[0]; 614 addr->na_addr[1] = pa[1]; 615 addr->na_addr[2] = pa[2]; 616 addr->na_addr[3] = pa[3]; 617 addr->na_addr[4] = pa[4]; 618 addr->na_addr[5] = pa[5]; 619 #ifdef MY_DEBUG 620 printf("NDR: Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n", 621 addr->na_addr[0], addr->na_addr[1], addr->na_addr[2], 622 addr->na_addr[3], addr->na_addr[4], addr->na_addr[5]); 623 #endif 624 } 625 626 /* Allocate and initialize buffer */ 627 static int dev_init_buf(NDR_driver *pdev) { 628 size_t rx_desc_size, tx_desc_size, rx_buf_size, tx_buf_size, tot_buf_size; 629 phys_bytes buf_dma; 630 char *buf; 631 int i; 632 633 /* Build Rx and Tx buffer */ 634 tx_buf_size = TX_BUF_SIZE; 635 if (tx_buf_size % 4) 636 tx_buf_size += 4 - (tx_buf_size % 4); 637 rx_buf_size = RX_BUF_SIZE; 638 if (rx_buf_size % 4) 639 rx_buf_size += 4 - (rx_buf_size % 4); 640 tot_buf_size = TX_BUFFER_NUM * tx_buf_size + RX_BUFFER_NUM * rx_buf_size; 641 rx_desc_size = RX_BUFFER_NUM * sizeof(NDR_desc); 642 tx_desc_size = TX_BUFFER_NUM * sizeof(NDR_desc); 643 tot_buf_size += rx_desc_size + tx_desc_size; 644 if (tot_buf_size % 4096) 645 tot_buf_size += 4096 - (tot_buf_size % 4096); 646 647 if (!(buf = alloc_contig(tot_buf_size, 0, &buf_dma))) { 648 printf("NDR: Fail to allocate memory\n"); 649 return -ENOMEM; 650 } 651 pdev->buf_size = tot_buf_size; 652 pdev->buf = buf; 653 654 /* Rx descriptor buffer location */ 655 pdev->rx_desc = (NDR_desc *)buf; 656 pdev->rx_desc_dma = buf_dma; 657 memset(buf, 0, rx_desc_size); 658 buf += rx_desc_size; 659 buf_dma += rx_desc_size; 660 661 /* Tx descriptor buffer location */ 662 pdev->tx_desc = (NDR_desc *)buf; 663 pdev->tx_desc_dma = buf_dma; 664 memset(buf, 0, tx_desc_size); 665 buf += tx_desc_size; 666 buf_dma += tx_desc_size; 667 668 /* Rx buffer assignment */ 669 for (i = 0; i < RX_BUFFER_NUM; i++) { 670 /* Initialize Rx buffer */ 671 pdev->rx[i].buf_dma = buf_dma; 672 pdev->rx[i].buf = buf; 673 buf_dma += rx_buf_size; 674 buf += rx_buf_size; 675 /* Set Rx descriptor */ 676 /* ### INIT_RX_DESC ### */ 677 dev_init_rx_desc(pdev->rx_desc, i, rx_buf_size, pdev->rx[i].buf_dma, 678 RX_BUFFER_NUM, pdev->rx_desc_dma); 679 } 680 681 /* Tx buffer assignment */ 682 for (i = 0; i < TX_BUFFER_NUM; i++) { 683 /* Set Tx buffer */ 684 pdev->tx[i].busy = 0; 685 pdev->tx[i].buf_dma = buf_dma; 686 pdev->tx[i].buf = buf; 687 buf_dma += tx_buf_size; 688 buf += tx_buf_size; 689 /* Initialize Tx descriptor */ 690 /* ### INIT_TX_DESC ### */ 691 dev_init_tx_desc(pdev->tx_desc, i, tx_buf_size, pdev->tx[i].buf_dma, 692 TX_BUFFER_NUM, pdev->tx_desc_dma); 693 } 694 695 /* Set Rx/Tx descriptor address into device register */ 696 /* ### SET_DESC_REG ### */ 697 dev_set_desc_reg(pdev->base, g_driver.rx_desc_dma, 698 g_driver.tx_desc_dma); 699 700 pdev->tx_busy_num = 0; 701 pdev->tx_head = 0; 702 pdev->tx_tail = 0; 703 pdev->rx_head = 0; 704 705 return 0; 706 } 707 708 /* Real handler interrupt */ 709 static void dev_handler(NDR_driver *pdev) { 710 u32_t intr_status; 711 int tx_head, tx_tail, index, flag = 0, ret; 712 NDR_desc *desc; 713 714 /* Read and clear interrupt status */ 715 /* ### READ_CLEAR_INTR_STS ### */ 716 intr_status = dev_read_clear_intr_status(pdev->base); 717 718 /* Enable interrupt */ 719 /* ### INTR_ENABLE_DISABLE ### */ 720 dev_intr_control(pdev->base, INTR_ENABLE); 721 722 /* Check link status */ 723 if (intr_status & INTR_STS_LINK) { 724 pdev->link = dev_check_link(pdev->base); 725 #ifdef MY_DEBUG 726 printf("NDR: Link state change\n"); 727 #endif 728 flag++; 729 } 730 /* Check Rx request status */ 731 if (intr_status & INTR_STS_RX) { 732 pdev->recv_flag = TRUE; 733 flag++; 734 } 735 /* Check Tx request status */ 736 if (intr_status & INTR_STS_TX) { 737 pdev->send_flag = TRUE; 738 flag++; 739 740 /* Manage Tx Buffer */ 741 tx_head = pdev->tx_head; 742 tx_tail = pdev->tx_tail; 743 while (tx_tail != tx_head) { 744 if (!pdev->tx[tx_tail].busy) 745 printf("NDR: Strange, buffer not busy?\n"); 746 index = tx_tail; 747 desc = pdev->tx_desc; 748 desc += tx_tail; 749 /* Check whether Tx is OK from Tx descriptor */ 750 /* ### CHECK_TX_OK_FROM_DESC ### */ 751 ret = dev_tx_ok_desc(pdev->base, desc, index); 752 if (ret == TX_SUSPEND) 753 break; 754 else if (ret == TX_ERROR) 755 printf("NDR: Tx error now\n"); 756 757 pdev->tx[tx_tail].busy = FALSE; 758 pdev->tx_busy_num--; 759 760 if (++tx_tail >= TX_BUFFER_NUM) 761 tx_tail = 0; 762 763 pdev->send_flag = TRUE; 764 pdev->recv_flag = TRUE; 765 766 /* Set Tx descriptor after Tx done */ 767 /* ### SET_TX_DESC_DONE ### */ 768 dev_set_tx_desc_done(pdev->base, desc, index); 769 #ifdef MY_DEBUG 770 printf("NDR: Successfully send a packet\n"); 771 #endif 772 } 773 pdev->tx_tail = tx_tail; 774 } 775 #ifdef MY_DEBUG 776 if (!flag) { 777 printf("NDR: Unknown error in interrupt 0x%08x\n", intr_status); 778 return; 779 } 780 #endif 781 } 782 783 /* Check interrupt and perform */ 784 static void dev_check_ints(NDR_driver *pdev) { 785 if (!pdev->recv_flag) 786 return; 787 pdev->recv_flag = FALSE; 788 789 /* Handle data receive */ 790 netdriver_recv(); 791 792 /* Handle data transmit */ 793 if (pdev->send_flag) { 794 pdev->send_flag = FALSE; 795 netdriver_send(); 796 } 797 } 798