Changes in uspace/srv/hw/netif/dp8390/dp8390.c [7300c37:3c106e88] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hw/netif/dp8390/dp8390.c
r7300c37 r3c106e88 54 54 #include <errno.h> 55 55 #include <libarch/ddi.h> 56 #include <netif_skel.h> 56 57 #include <net/packet.h> 58 #include <nil_interface.h> 57 59 #include <packet_client.h> 58 60 #include "dp8390.h" … … 79 81 80 82 /** NE2000 retry count */ 81 #define NE2K_RETRY 0x100083 #define NE2K_RETRY 100 82 84 83 85 /** NE2000 error messages rate limiting */ … … 184 186 memcpy(&word, buf, 1); 185 187 pio_write_16(ne2k->data_port, word); 186 }187 }188 189 static void ne2k_init(ne2k_t *ne2k)190 {191 unsigned int i;192 193 /* Reset the ethernet card */194 uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);195 usleep(2000);196 pio_write_8(ne2k->port + NE2K_RESET, val);197 usleep(2000);198 199 /* Reset the DP8390 */200 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);201 for (i = 0; i < NE2K_RETRY; i++) {202 if (pio_read_8(ne2k->port + DP_ISR) != 0)203 break;204 188 } 205 189 } … … 226 210 ne2k->up = false; 227 211 228 ne2k_init(ne2k); 212 /* Reset the ethernet card */ 213 uint8_t val = pio_read_8(ne2k->port + NE2K_RESET); 214 usleep(2000); 215 pio_write_8(ne2k->port + NE2K_RESET, val); 216 usleep(2000); 217 218 /* Reset the DP8390 */ 219 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT); 220 for (i = 0; i < 0x1000; i++) { 221 if (pio_read_8(ne2k->port + DP_ISR) != 0) 222 break; 223 } 229 224 230 225 /* Check if the DP8390 is really there */ 231 uint8_tval = pio_read_8(ne2k->port + DP_CR);226 val = pio_read_8(ne2k->port + DP_CR); 232 227 if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT)) 233 228 return EXDEV; … … 247 242 for (i = 0; i < ETH_ADDR; i++) 248 243 ne2k->mac[i] = pio_read_16(ne2k->data_port); 249 250 ne2k->probed = true;251 return EOK;252 }253 254 /** Start the network interface.255 *256 * @param[in,out] ne2k Network interface structure.257 *258 * @return EOK on success.259 * @return EXDEV if the network interface is disabled.260 *261 */262 int ne2k_up(ne2k_t *ne2k)263 {264 if (!ne2k->probed)265 return EXDEV;266 267 ne2k_init(ne2k);268 244 269 245 /* … … 342 318 343 319 /* Step 10: */ 344 pio_write_8(ne2k->port + DP_CR, CR_ PS_P0 | CR_DM_ABORT | CR_STA);320 pio_write_8(ne2k->port + DP_CR, CR_DM_ABORT | CR_STA); 345 321 346 322 /* Step 11: */ … … 353 329 354 330 /* Finish the initialization */ 331 ne2k->probed = true; 332 return EOK; 333 } 334 335 /** Start the network interface. 336 * 337 * @param[in,out] ne2k Network interface structure. 338 * 339 * @return EOK on success. 340 * @return EXDEV if the network interface is disabled. 341 * 342 */ 343 int ne2k_up(ne2k_t *ne2k) 344 { 345 if (!ne2k->probed) 346 return EXDEV; 347 348 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA); 349 pio_write_8(ne2k->port + DP_RCR, RCR_AB); 350 355 351 ne2k->up = true; 356 352 return EOK; … … 366 362 if ((ne2k->probed) && (ne2k->up)) { 367 363 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT); 368 ne2k_init(ne2k); 364 365 /* Reset the ethernet card */ 366 uint8_t val = pio_read_8(ne2k->port + NE2K_RESET); 367 usleep(2000); 368 pio_write_8(ne2k->port + NE2K_RESET, val); 369 369 370 ne2k->up = false; 370 371 } … … 419 420 pio_write_8(ne2k->port + DP_RBCR1, 0); 420 421 421 for (i = 0; i < NE2K_RETRY; i++) {422 for (i = 0; i < 0x1000; i++) { 422 423 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0) 423 424 break; … … 429 430 430 431 /* Acknowledge the ISR_RDC (remote DMA) interrupt */ 431 for (i = 0; i < NE2K_RETRY; i++) {432 for (i = 0; i < 0x1000; i++) { 432 433 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0) 433 434 break; … … 447 448 } 448 449 449 static frame_t *ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length) 450 { 451 frame_t *frame = (frame_t *) malloc(sizeof(frame_t)); 452 if (frame == NULL) 453 return NULL; 454 455 link_initialize(&frame->link); 456 457 frame->packet = netif_packet_get_1(length); 458 if (frame->packet == NULL) { 459 free(frame); 460 return NULL; 461 } 462 463 void *buf = packet_suffix(frame->packet, length); 450 static uint8_t ne2k_isr_ack(ne2k_t *ne2k) 451 { 452 uint8_t isr = pio_read_8(ne2k->port + DP_ISR); 453 if (isr != 0) 454 pio_write_8(ne2k->port + DP_ISR, isr); 455 456 return isr; 457 } 458 459 static void ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length, 460 int nil_phone, device_id_t device_id) 461 { 462 packet_t *packet = netif_packet_get_1(length); 463 if (!packet) 464 return; 465 466 void *buf = packet_suffix(packet, length); 464 467 bzero(buf, length); 465 468 uint8_t last = page + length / DP_PAGE; … … 478 481 479 482 ne2k->stats.receive_packets++; 480 return frame; 481 } 482 483 static link_t *ne2k_receive(ne2k_t *ne2k) 484 { 485 /* 486 * Allocate memory for the list of received frames. 487 * If the allocation fails here we still receive the 488 * frames from the network, but they will be lost. 489 */ 490 link_t *frames = (link_t *) malloc(sizeof(link_t)); 491 if (frames != NULL) 492 list_initialize(frames); 493 483 nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE); 484 } 485 486 static void ne2k_receive(ne2k_t *ne2k, int nil_phone, device_id_t device_id) 487 { 494 488 while (true) { 495 489 uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1; … … 540 534 ne2k->overruns++; 541 535 next = current; 542 } else if ((header.status & RSR_PRX) && (ne2k->up)) { 543 frame_t *frame = ne2k_receive_frame(ne2k, boundary, length); 544 if ((frame != NULL) && (frames != NULL)) 545 list_append(&frame->link, frames); 546 } 536 } else if ((header.status & RSR_PRX) && (ne2k->up)) 537 ne2k_receive_frame(ne2k, boundary, length, nil_phone, device_id); 547 538 548 539 /* … … 559 550 pio_write_8(ne2k->port + DP_BNRY, next); 560 551 } 561 562 return frames; 563 } 564 565 link_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr) 566 { 567 /* List of received frames */ 568 link_t *frames = NULL; 569 570 if (isr & (ISR_PTX | ISR_TXE)) { 571 if (isr & ISR_TXE) 572 ne2k->stats.send_errors++; 573 else { 574 if (tsr & TSR_PTX) 575 ne2k->stats.send_packets++; 576 577 if (tsr & TSR_COL) 578 ne2k->stats.collisions++; 579 580 if (tsr & TSR_ABT) 581 ne2k->stats.send_aborted_errors++; 582 583 if (tsr & TSR_CRS) 584 ne2k->stats.send_carrier_errors++; 585 586 if (tsr & TSR_FU) { 587 ne2k->underruns++; 588 if (ne2k->underruns < NE2K_ERL) 589 fprintf(stderr, "%s: FIFO underrun\n", NAME); 552 } 553 554 void ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, int nil_phone, device_id_t device_id) 555 { 556 bool signal = false; 557 bool stopped = false; 558 559 for (; (isr & 0x7f) != 0; isr = ne2k_isr_ack(ne2k)) { 560 if (isr & (ISR_PTX | ISR_TXE)) { 561 if (isr & ISR_TXE) 562 ne2k->stats.send_errors++; 563 else { 564 uint8_t tsr = pio_read_8(ne2k->port + DP_TSR); 565 566 if (tsr & TSR_PTX) 567 ne2k->stats.send_packets++; 568 569 if (tsr & TSR_COL) 570 ne2k->stats.collisions++; 571 572 if (tsr & TSR_ABT) 573 ne2k->stats.send_aborted_errors++; 574 575 if (tsr & TSR_CRS) 576 ne2k->stats.send_carrier_errors++; 577 578 if (tsr & TSR_FU) { 579 ne2k->underruns++; 580 if (ne2k->underruns < NE2K_ERL) 581 fprintf(stderr, "%s: FIFO underrun\n", NAME); 582 } 583 584 if (tsr & TSR_CDH) { 585 ne2k->stats.send_heartbeat_errors++; 586 if (ne2k->stats.send_heartbeat_errors < NE2K_ERL) 587 fprintf(stderr, "%s: CD heartbeat failure\n", NAME); 588 } 589 590 if (tsr & TSR_OWC) 591 ne2k->stats.send_window_errors++; 590 592 } 591 593 592 if (tsr & TSR_CDH) { 593 ne2k->stats.send_heartbeat_errors++; 594 if (ne2k->stats.send_heartbeat_errors < NE2K_ERL) 595 fprintf(stderr, "%s: CD heartbeat failure\n", NAME); 594 fibril_mutex_lock(&ne2k->sq_mutex); 595 596 if (ne2k->sq.dirty) { 597 /* Prepare the buffer for next packet */ 598 ne2k->sq.dirty = false; 599 ne2k->sq.size = 0; 600 signal = true; 601 } else { 602 ne2k->misses++; 603 if (ne2k->misses < NE2K_ERL) 604 fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME); 596 605 } 597 606 598 if (tsr & TSR_OWC) 599 ne2k->stats.send_window_errors++; 607 fibril_mutex_unlock(&ne2k->sq_mutex); 600 608 } 601 609 602 fibril_mutex_lock(&ne2k->sq_mutex);603 604 if (ne2k->sq.dirty) {605 /* Prepare the buffer for next packet */606 ne2k->s q.dirty = false;607 ne2k->sq.size = 0;608 609 /* Signal a next frame to be sent */610 fibril_condvar_broadcast(&ne2k->sq_cv);611 } else {612 ne2k->misses++;613 if (ne2k->misses < NE2K_ERL)614 fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);610 if (isr & ISR_PRX) 611 ne2k_receive(ne2k, nil_phone, device_id); 612 613 if (isr & ISR_RXE) 614 ne2k->stats.receive_errors++; 615 616 if (isr & ISR_CNT) { 617 ne2k->stats.receive_crc_errors += 618 pio_read_8(ne2k->port + DP_CNTR0); 619 ne2k->stats.receive_frame_errors += 620 pio_read_8(ne2k->port + DP_CNTR1); 621 ne2k->stats.receive_missed_errors += 622 pio_read_8(ne2k->port + DP_CNTR2); 615 623 } 616 624 617 fibril_mutex_unlock(&ne2k->sq_mutex); 618 } 619 620 if (isr & ISR_RXE) 621 ne2k->stats.receive_errors++; 622 623 if (isr & ISR_CNT) { 624 ne2k->stats.receive_crc_errors += 625 pio_read_8(ne2k->port + DP_CNTR0); 626 ne2k->stats.receive_frame_errors += 627 pio_read_8(ne2k->port + DP_CNTR1); 628 ne2k->stats.receive_missed_errors += 629 pio_read_8(ne2k->port + DP_CNTR2); 630 } 631 632 if (isr & ISR_PRX) 633 frames = ne2k_receive(ne2k); 634 635 if (isr & ISR_RST) { 625 if (isr & ISR_RST) { 626 /* 627 * This means we got an interrupt but the ethernet 628 * chip is shutdown. We set the flag 'stopped' 629 * and continue processing arrived packets. When the 630 * receive buffer is empty, we reset the DP8390. 631 */ 632 stopped = true; 633 } 634 } 635 636 if (stopped) { 636 637 /* 637 638 * The chip is stopped, and all arrived … … 641 642 } 642 643 643 /* Unmask interrupts to be processed in the next round */ 644 pio_write_8(ne2k->port + DP_IMR, 645 IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE); 646 647 return frames; 644 /* Signal a next frame to be sent */ 645 if (signal) 646 fibril_condvar_broadcast(&ne2k->sq_cv); 648 647 } 649 648
Note:
See TracChangeset
for help on using the changeset viewer.