Changeset d7ff048 in mainline for uspace/drv/nic/ne2k/dp8390.c
- Timestamp:
- 2011-10-08T13:08:53Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bf08ff0
- Parents:
- 8367d1d (diff), 80099c19 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/nic/ne2k/dp8390.c
r8367d1d rd7ff048 2 2 * Copyright (c) 2009 Lukas Mejdrech 3 3 * Copyright (c) 2011 Martin Decky 4 * Copyright (c) 2011 Radim Vansa 4 5 * All rights reserved. 5 6 * … … 38 39 */ 39 40 40 /** @addtogroup ne2000 41 * @{ 42 */ 43 44 /** @file 41 /** 42 * @addtogroup drv_ne2k 43 * @{ 44 */ 45 46 /** 47 * @file 48 * @brief NE2000 driver core 45 49 * 46 50 * NE2000 (based on DP8390) network interface core implementation. … … 65 69 #define SQ_PAGES 6 66 70 67 /* NE2000 implementation. */68 69 /** NE2000 Data Register */70 #define NE2K_DATA 0x001071 72 /** NE2000 Reset register */73 #define NE2K_RESET 0x001f74 75 /** NE2000 data start */76 #define NE2K_START 0x400077 78 /** NE2000 data size */79 #define NE2K_SIZE 0x400080 81 /** NE2000 retry count */82 #define NE2K_RETRY 0x100083 84 /** NE2000 error messages rate limiting */85 #define NE2K_ERL 1086 87 /** Minimum Ethernet packet size in bytes */88 #define ETH_MIN_PACK_SIZE 6089 90 /** Maximum Ethernet packet size in bytes */91 #define ETH_MAX_PACK_SIZE_TAGGED 151892 93 71 /** Type definition of the receive header 94 72 * … … 216 194 * 217 195 */ 218 int ne2k_probe(ne2k_t *ne2k , void *port, int irq)196 int ne2k_probe(ne2k_t *ne2k) 219 197 { 220 198 unsigned int i; 221 222 /* General initialization */223 ne2k->port = port;224 ne2k->data_port = ne2k->port + NE2K_DATA;225 ne2k->irq = irq;226 ne2k->probed = false;227 ne2k->up = false;228 199 229 200 ne2k_init(ne2k); … … 247 218 248 219 for (i = 0; i < ETH_ADDR; i++) 249 ne2k->mac[i] = pio_read_16(ne2k->data_port); 250 251 ne2k->probed = true; 220 ne2k->mac.address[i] = pio_read_16(ne2k->data_port); 221 252 222 return EOK; 223 } 224 225 void ne2k_set_physical_address(ne2k_t *ne2k, const nic_address_t *address) 226 { 227 memcpy(&ne2k->mac, address, sizeof(nic_address_t)); 228 229 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STP); 230 231 pio_write_8(ne2k->port + DP_RBCR0, ETH_ADDR << 1); 232 pio_write_8(ne2k->port + DP_RBCR1, 0); 233 pio_write_8(ne2k->port + DP_RSAR0, 0); 234 pio_write_8(ne2k->port + DP_RSAR1, 0); 235 pio_write_8(ne2k->port + DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 236 237 size_t i; 238 for (i = 0; i < ETH_ADDR; i++) 239 pio_write_16(ne2k->data_port, ne2k->mac.address[i]); 240 241 //pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA); 253 242 } 254 243 … … 304 293 305 294 /* Step 4: */ 306 pio_write_8(ne2k->port + DP_RCR, RCR_AB);295 pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration); 307 296 308 297 /* Step 5: */ … … 324 313 pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP); 325 314 326 pio_write_8(ne2k->port + DP_PAR0, ne2k->mac [0]);327 pio_write_8(ne2k->port + DP_PAR1, ne2k->mac [1]);328 pio_write_8(ne2k->port + DP_PAR2, ne2k->mac [2]);329 pio_write_8(ne2k->port + DP_PAR3, ne2k->mac [3]);330 pio_write_8(ne2k->port + DP_PAR4, ne2k->mac [4]);331 pio_write_8(ne2k->port + DP_PAR5, ne2k->mac [5]);332 333 pio_write_8(ne2k->port + DP_MAR0, 0 xff);334 pio_write_8(ne2k->port + DP_MAR1, 0 xff);335 pio_write_8(ne2k->port + DP_MAR2, 0 xff);336 pio_write_8(ne2k->port + DP_MAR3, 0 xff);337 pio_write_8(ne2k->port + DP_MAR4, 0 xff);338 pio_write_8(ne2k->port + DP_MAR5, 0 xff);339 pio_write_8(ne2k->port + DP_MAR6, 0 xff);340 pio_write_8(ne2k->port + DP_MAR7, 0 xff);315 pio_write_8(ne2k->port + DP_PAR0, ne2k->mac.address[0]); 316 pio_write_8(ne2k->port + DP_PAR1, ne2k->mac.address[1]); 317 pio_write_8(ne2k->port + DP_PAR2, ne2k->mac.address[2]); 318 pio_write_8(ne2k->port + DP_PAR3, ne2k->mac.address[3]); 319 pio_write_8(ne2k->port + DP_PAR4, ne2k->mac.address[4]); 320 pio_write_8(ne2k->port + DP_PAR5, ne2k->mac.address[5]); 321 322 pio_write_8(ne2k->port + DP_MAR0, 0); 323 pio_write_8(ne2k->port + DP_MAR1, 0); 324 pio_write_8(ne2k->port + DP_MAR2, 0); 325 pio_write_8(ne2k->port + DP_MAR3, 0); 326 pio_write_8(ne2k->port + DP_MAR4, 0); 327 pio_write_8(ne2k->port + DP_MAR5, 0); 328 pio_write_8(ne2k->port + DP_MAR6, 0); 329 pio_write_8(ne2k->port + DP_MAR7, 0); 341 330 342 331 pio_write_8(ne2k->port + DP_CURR, ne2k->start_page + 1); … … 372 361 } 373 362 363 static void ne2k_reset(ne2k_t *ne2k) 364 { 365 unsigned int i; 366 367 fibril_mutex_lock(&ne2k->sq_mutex); 368 369 /* Stop the chip */ 370 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT); 371 pio_write_8(ne2k->port + DP_RBCR0, 0); 372 pio_write_8(ne2k->port + DP_RBCR1, 0); 373 374 for (i = 0; i < NE2K_RETRY; i++) { 375 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0) 376 break; 377 } 378 379 pio_write_8(ne2k->port + DP_TCR, TCR_1EXTERNAL | TCR_OFST); 380 pio_write_8(ne2k->port + DP_CR, CR_STA | CR_DM_ABORT); 381 pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL); 382 383 /* Acknowledge the ISR_RDC (remote DMA) interrupt */ 384 for (i = 0; i < NE2K_RETRY; i++) { 385 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0) 386 break; 387 } 388 389 uint8_t val = pio_read_8(ne2k->port + DP_ISR); 390 pio_write_8(ne2k->port + DP_ISR, val & ~ISR_RDC); 391 392 /* 393 * Reset the transmit ring. If we were transmitting a frame, 394 * we pretend that the packet is processed. Higher layers will 395 * retransmit if the packet wasn't actually sent. 396 */ 397 ne2k->sq.dirty = false; 398 399 fibril_mutex_unlock(&ne2k->sq_mutex); 400 } 401 374 402 /** Send a frame. 375 403 * … … 378 406 * 379 407 */ 380 void ne2k_send(ne2k_t *ne2k, packet_t *packet) 381 { 408 void ne2k_send(nic_t *nic_data, packet_t *packet) 409 { 410 ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data); 411 382 412 assert(ne2k->probed); 383 413 assert(ne2k->up); 384 414 385 415 fibril_mutex_lock(&ne2k->sq_mutex); 386 416 387 while (ne2k->sq.dirty) 417 while (ne2k->sq.dirty) { 388 418 fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex); 389 419 } 390 420 void *buf = packet_get_data(packet); 391 421 size_t size = packet_get_data_length(packet); … … 393 423 if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) { 394 424 fibril_mutex_unlock(&ne2k->sq_mutex); 395 fprintf(stderr, "%s: Frame dropped (invalid size %zu bytes)\n",396 NAME, size);397 425 return; 398 426 } 399 427 400 428 /* Upload the frame to the ethernet card */ 401 429 ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size); 402 430 ne2k->sq.dirty = true; 403 431 ne2k->sq.size = size; 404 432 405 433 /* Initialize the transfer */ 406 434 pio_write_8(ne2k->port + DP_TPSR, ne2k->sq.page); … … 408 436 pio_write_8(ne2k->port + DP_TBCR1, (size >> 8) & 0xff); 409 437 pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA); 410 411 438 fibril_mutex_unlock(&ne2k->sq_mutex); 412 } 413 414 static void ne2k_reset(ne2k_t *ne2k) 415 { 416 unsigned int i; 417 418 /* Stop the chip */ 419 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT); 420 pio_write_8(ne2k->port + DP_RBCR0, 0); 421 pio_write_8(ne2k->port + DP_RBCR1, 0); 422 423 for (i = 0; i < NE2K_RETRY; i++) { 424 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0) 425 break; 426 } 427 428 pio_write_8(ne2k->port + DP_TCR, TCR_1EXTERNAL | TCR_OFST); 429 pio_write_8(ne2k->port + DP_CR, CR_STA | CR_DM_ABORT); 430 pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL); 431 432 /* Acknowledge the ISR_RDC (remote DMA) interrupt */ 433 for (i = 0; i < NE2K_RETRY; i++) { 434 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0) 435 break; 436 } 437 438 uint8_t val = pio_read_8(ne2k->port + DP_ISR); 439 pio_write_8(ne2k->port + DP_ISR, val & ~ISR_RDC); 440 441 /* 442 * Reset the transmit ring. If we were transmitting a frame, 443 * we pretend that the packet is processed. Higher layers will 444 * retransmit if the packet wasn't actually sent. 445 */ 446 fibril_mutex_lock(&ne2k->sq_mutex); 447 ne2k->sq.dirty = false; 448 fibril_mutex_unlock(&ne2k->sq_mutex); 449 } 450 451 static frame_t *ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length) 452 { 453 frame_t *frame = (frame_t *) malloc(sizeof(frame_t)); 439 440 /* Relase packet */ 441 nic_release_packet(nic_data, packet); 442 } 443 444 static nic_frame_t *ne2k_receive_frame(nic_t *nic_data, uint8_t page, 445 size_t length) 446 { 447 ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data); 448 449 nic_frame_t *frame = nic_alloc_frame(nic_data, length); 454 450 if (frame == NULL) 455 451 return NULL; 456 457 link_initialize(&frame->link);458 459 frame->packet = netif_packet_get_1(length);460 if (frame->packet == NULL) {461 free(frame);462 return NULL;463 }464 452 465 453 void *buf = packet_suffix(frame->packet, length); … … 470 458 size_t left = (ne2k->stop_page - page) * DP_PAGE 471 459 - sizeof(recv_header_t); 472 473 460 ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t), 474 461 left); 475 462 ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE, 476 463 length - left); 477 } else 464 } else { 478 465 ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t), 479 466 length); 480 481 ne2k->stats.receive_packets++; 467 } 482 468 return frame; 483 469 } 484 470 485 static list_t *ne2k_receive(ne2k_t *ne2k) 486 { 471 static void ne2k_receive(nic_t *nic_data) 472 { 473 ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data); 487 474 /* 488 475 * Allocate memory for the list of received frames. … … 490 477 * frames from the network, but they will be lost. 491 478 */ 492 list_t *frames = (list_t *) malloc(sizeof(list_t)); 493 if (frames != NULL) 494 list_initialize(frames); 495 496 while (true) { 479 nic_frame_list_t *frames = nic_alloc_frame_list(); 480 size_t frames_count = 0; 481 482 /* We may block sending in this loop - after so many received frames there 483 * must be some interrupt pending (for the frames not yet downloaded) and 484 * we will continue in its handler. */ 485 while (frames_count < 16) { 486 //TODO: isn't some locking necessary here? 497 487 uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1; 498 488 … … 503 493 uint8_t current = pio_read_8(ne2k->port + DP_CURR); 504 494 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA); 505 506 495 if (current == boundary) 507 496 /* No more frames to process */ … … 520 509 521 510 pio_read_buf_16(ne2k->data_port, (void *) &header, size); 522 511 523 512 size_t length = 524 513 (((size_t) header.rbcl) | (((size_t) header.rbch) << 8)) - size; … … 527 516 if ((length < ETH_MIN_PACK_SIZE) 528 517 || (length > ETH_MAX_PACK_SIZE_TAGGED)) { 529 fprintf(stderr, "%s: Rant frame (%zu bytes)\n", NAME, length);530 518 next = current; 531 519 } else if ((header.next < ne2k->start_page) 532 520 || (header.next > ne2k->stop_page)) { 533 fprintf(stderr, "%s: Malformed next frame %u\n", NAME,534 header.next);535 521 next = current; 536 522 } else if (header.status & RSR_FO) { … … 539 525 * reset the buffers. 540 526 */ 541 fprintf(stderr, "%s: FIFO overrun\n", NAME);542 527 ne2k->overruns++; 543 528 next = current; 544 529 } else if ((header.status & RSR_PRX) && (ne2k->up)) { 545 530 if (frames != NULL) { 546 frame_t *frame = ne2k_receive_frame(ne2k, boundary, length); 547 if (frame != NULL) 548 list_append(&frame->link, frames); 549 } 531 nic_frame_t *frame = 532 ne2k_receive_frame(nic_data, boundary, length); 533 if (frame != NULL) { 534 nic_frame_list_append(frames, frame); 535 frames_count++; 536 } else { 537 break; 538 } 539 } else 540 break; 550 541 } 551 542 … … 560 551 else 561 552 next--; 562 563 553 pio_write_8(ne2k->port + DP_BNRY, next); 564 554 } 565 566 return frames; 567 } 568 569 list_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr) 570 { 571 /* List of received frames */ 572 list_t *frames = NULL; 573 555 nic_received_frame_list(nic_data, frames); 556 } 557 558 void ne2k_interrupt(nic_t *nic_data, uint8_t isr, uint8_t tsr) 559 { 560 ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data); 561 574 562 if (isr & (ISR_PTX | ISR_TXE)) { 575 if (isr & ISR_TXE) 576 ne2k->stats.send_errors++; 577 else { 578 if (tsr & TSR_PTX) 579 ne2k->stats.send_packets++; 580 581 if (tsr & TSR_COL) 582 ne2k->stats.collisions++; 583 584 if (tsr & TSR_ABT) 585 ne2k->stats.send_aborted_errors++; 586 587 if (tsr & TSR_CRS) 588 ne2k->stats.send_carrier_errors++; 589 590 if (tsr & TSR_FU) { 591 ne2k->underruns++; 592 if (ne2k->underruns < NE2K_ERL) 593 fprintf(stderr, "%s: FIFO underrun\n", NAME); 594 } 595 596 if (tsr & TSR_CDH) { 597 ne2k->stats.send_heartbeat_errors++; 598 if (ne2k->stats.send_heartbeat_errors < NE2K_ERL) 599 fprintf(stderr, "%s: CD heartbeat failure\n", NAME); 600 } 601 602 if (tsr & TSR_OWC) 603 ne2k->stats.send_window_errors++; 563 if (tsr & TSR_COL) { 564 nic_report_collisions(nic_data, 565 pio_read_8(ne2k->port + DP_NCR) & 15); 604 566 } 605 567 568 if (tsr & TSR_PTX) { 569 // TODO: fix number of sent bytes (but how?) 570 nic_report_send_ok(nic_data, 1, 0); 571 } else if (tsr & TSR_ABT) { 572 nic_report_send_error(nic_data, NIC_SEC_ABORTED, 1); 573 } else if (tsr & TSR_CRS) { 574 nic_report_send_error(nic_data, NIC_SEC_CARRIER_LOST, 1); 575 } else if (tsr & TSR_FU) { 576 ne2k->underruns++; 577 // if (ne2k->underruns < NE2K_ERL) { 578 // } 579 } else if (tsr & TSR_CDH) { 580 nic_report_send_error(nic_data, NIC_SEC_HEARTBEAT, 1); 581 // if (nic_data->stats.send_heartbeat_errors < NE2K_ERL) { 582 // } 583 } else if (tsr & TSR_OWC) { 584 nic_report_send_error(nic_data, NIC_SEC_WINDOW_ERROR, 1); 585 } 586 606 587 fibril_mutex_lock(&ne2k->sq_mutex); 607 608 588 if (ne2k->sq.dirty) { 609 589 /* Prepare the buffer for next packet */ … … 615 595 } else { 616 596 ne2k->misses++; 617 if (ne2k->misses < NE2K_ERL)618 fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);597 // if (ne2k->misses < NE2K_ERL) { 598 // } 619 599 } 620 621 600 fibril_mutex_unlock(&ne2k->sq_mutex); 622 601 } 623 624 if (isr & ISR_RXE) 625 ne2k->stats.receive_errors++; 626 602 627 603 if (isr & ISR_CNT) { 628 ne2k->stats.receive_crc_errors +=629 pio_read_8(ne2k->port + DP_CNTR0);630 ne2k->stats.receive_frame_errors +=631 pio_read_8(ne2k->port + DP_CNTR1);632 ne2k->stats.receive_missed_errors +=633 pio_read_8(ne2k->port + DP_CNTR2);634 }635 636 if (isr & ISR_PRX) 637 frames = ne2k_receive(ne2k);638 604 unsigned int errors; 605 for (errors = pio_read_8(ne2k->port + DP_CNTR0); errors > 0; --errors) 606 nic_report_receive_error(nic_data, NIC_REC_CRC, 1); 607 for (errors = pio_read_8(ne2k->port + DP_CNTR1); errors > 0; --errors) 608 nic_report_receive_error(nic_data, NIC_REC_FRAME_ALIGNMENT, 1); 609 for (errors = pio_read_8(ne2k->port + DP_CNTR2); errors > 0; --errors) 610 nic_report_receive_error(nic_data, NIC_REC_MISSED, 1); 611 } 612 if (isr & ISR_PRX) { 613 ne2k_receive(nic_data); 614 } 639 615 if (isr & ISR_RST) { 640 616 /* … … 648 624 pio_write_8(ne2k->port + DP_IMR, 649 625 IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE); 650 651 return frames; 626 } 627 628 void ne2k_set_accept_bcast(ne2k_t *ne2k, int accept) 629 { 630 if (accept) 631 ne2k->receive_configuration |= RCR_AB; 632 else 633 ne2k->receive_configuration &= ~RCR_AB; 634 635 pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration); 636 } 637 638 void ne2k_set_accept_mcast(ne2k_t *ne2k, int accept) 639 { 640 if (accept) 641 ne2k->receive_configuration |= RCR_AM; 642 else 643 ne2k->receive_configuration &= ~RCR_AM; 644 645 pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration); 646 } 647 648 void ne2k_set_promisc_phys(ne2k_t *ne2k, int promisc) 649 { 650 if (promisc) 651 ne2k->receive_configuration |= RCR_PRO; 652 else 653 ne2k->receive_configuration &= ~RCR_PRO; 654 655 pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration); 656 } 657 658 void ne2k_set_mcast_hash(ne2k_t *ne2k, uint64_t hash) 659 { 660 /* Select Page 1 and stop all transfers */ 661 pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP); 662 663 pio_write_8(ne2k->port + DP_MAR0, (uint8_t) hash); 664 pio_write_8(ne2k->port + DP_MAR1, (uint8_t) (hash >> 8)); 665 pio_write_8(ne2k->port + DP_MAR2, (uint8_t) (hash >> 16)); 666 pio_write_8(ne2k->port + DP_MAR3, (uint8_t) (hash >> 24)); 667 pio_write_8(ne2k->port + DP_MAR4, (uint8_t) (hash >> 32)); 668 pio_write_8(ne2k->port + DP_MAR5, (uint8_t) (hash >> 40)); 669 pio_write_8(ne2k->port + DP_MAR6, (uint8_t) (hash >> 48)); 670 pio_write_8(ne2k->port + DP_MAR7, (uint8_t) (hash >> 56)); 671 672 /* Select Page 0 and resume transfers */ 673 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA); 652 674 } 653 675
Note:
See TracChangeset
for help on using the changeset viewer.