Changeset 60b2b69 in mainline for uspace/srv/hw/netif/ne2000/dp8390.c
- Timestamp:
- 2011-01-14T13:04:10Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5f635ca
- Parents:
- 5ccb15c (diff), 00c2d035 (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/srv/hw/netif/ne2000/dp8390.c
r5ccb15c r60b2b69 54 54 #include <errno.h> 55 55 #include <libarch/ddi.h> 56 #include <netif_skel.h>57 56 #include <net/packet.h> 58 #include <nil_interface.h>59 57 #include <packet_client.h> 60 58 #include "dp8390.h" … … 81 79 82 80 /** NE2000 retry count */ 83 #define NE2K_RETRY 10081 #define NE2K_RETRY 0x1000 84 82 85 83 /** NE2000 error messages rate limiting */ … … 186 184 memcpy(&word, buf, 1); 187 185 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; 188 204 } 189 205 } … … 210 226 ne2k->up = false; 211 227 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 } 228 ne2k_init(ne2k); 224 229 225 230 /* Check if the DP8390 is really there */ 226 val = pio_read_8(ne2k->port + DP_CR);231 uint8_t val = pio_read_8(ne2k->port + DP_CR); 227 232 if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT)) 228 233 return EXDEV; … … 242 247 for (i = 0; i < ETH_ADDR; i++) 243 248 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); 244 268 245 269 /* … … 318 342 319 343 /* Step 10: */ 320 pio_write_8(ne2k->port + DP_CR, CR_ DM_ABORT | CR_STA);344 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA); 321 345 322 346 /* Step 11: */ … … 329 353 330 354 /* 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 351 355 ne2k->up = true; 352 356 return EOK; … … 362 366 if ((ne2k->probed) && (ne2k->up)) { 363 367 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT); 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 368 ne2k_init(ne2k); 370 369 ne2k->up = false; 371 370 } … … 420 419 pio_write_8(ne2k->port + DP_RBCR1, 0); 421 420 422 for (i = 0; i < 0x1000; i++) {421 for (i = 0; i < NE2K_RETRY; i++) { 423 422 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0) 424 423 break; … … 430 429 431 430 /* Acknowledge the ISR_RDC (remote DMA) interrupt */ 432 for (i = 0; i < 0x1000; i++) {431 for (i = 0; i < NE2K_RETRY; i++) { 433 432 if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0) 434 433 break; … … 448 447 } 449 448 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); 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); 467 464 bzero(buf, length); 468 465 uint8_t last = page + length / DP_PAGE; … … 481 478 482 479 ne2k->stats.receive_packets++; 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 { 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 488 494 while (true) { 489 495 uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1; … … 534 540 ne2k->overruns++; 535 541 next = current; 536 } else if ((header.status & RSR_PRX) && (ne2k->up)) 537 ne2k_receive_frame(ne2k, boundary, length, nil_phone, device_id); 542 } else if ((header.status & RSR_PRX) && (ne2k->up)) { 543 if (frames != NULL) { 544 frame_t *frame = ne2k_receive_frame(ne2k, boundary, length); 545 if (frame != NULL) 546 list_append(&frame->link, frames); 547 } 548 } 538 549 539 550 /* … … 550 561 pio_write_8(ne2k->port + DP_BNRY, next); 551 562 } 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++; 563 564 return frames; 565 } 566 567 link_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr) 568 { 569 /* List of received frames */ 570 link_t *frames = NULL; 571 572 if (isr & (ISR_PTX | ISR_TXE)) { 573 if (isr & ISR_TXE) 574 ne2k->stats.send_errors++; 575 else { 576 if (tsr & TSR_PTX) 577 ne2k->stats.send_packets++; 578 579 if (tsr & TSR_COL) 580 ne2k->stats.collisions++; 581 582 if (tsr & TSR_ABT) 583 ne2k->stats.send_aborted_errors++; 584 585 if (tsr & TSR_CRS) 586 ne2k->stats.send_carrier_errors++; 587 588 if (tsr & TSR_FU) { 589 ne2k->underruns++; 590 if (ne2k->underruns < NE2K_ERL) 591 fprintf(stderr, "%s: FIFO underrun\n", NAME); 592 592 } 593 593 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); 594 if (tsr & TSR_CDH) { 595 ne2k->stats.send_heartbeat_errors++; 596 if (ne2k->stats.send_heartbeat_errors < NE2K_ERL) 597 fprintf(stderr, "%s: CD heartbeat failure\n", NAME); 605 598 } 606 599 607 fibril_mutex_unlock(&ne2k->sq_mutex); 600 if (tsr & TSR_OWC) 601 ne2k->stats.send_window_errors++; 608 602 } 609 603 610 if (isr & ISR_PRX)611 ne2k_receive(ne2k, nil_phone, device_id);612 613 if (isr & ISR_RXE)614 ne2k->s tats.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);604 fibril_mutex_lock(&ne2k->sq_mutex); 605 606 if (ne2k->sq.dirty) { 607 /* Prepare the buffer for next packet */ 608 ne2k->sq.dirty = false; 609 ne2k->sq.size = 0; 610 611 /* Signal a next frame to be sent */ 612 fibril_condvar_broadcast(&ne2k->sq_cv); 613 } else { 614 ne2k->misses++; 615 if (ne2k->misses < NE2K_ERL) 616 fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME); 623 617 } 624 618 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) { 619 fibril_mutex_unlock(&ne2k->sq_mutex); 620 } 621 622 if (isr & ISR_RXE) 623 ne2k->stats.receive_errors++; 624 625 if (isr & ISR_CNT) { 626 ne2k->stats.receive_crc_errors += 627 pio_read_8(ne2k->port + DP_CNTR0); 628 ne2k->stats.receive_frame_errors += 629 pio_read_8(ne2k->port + DP_CNTR1); 630 ne2k->stats.receive_missed_errors += 631 pio_read_8(ne2k->port + DP_CNTR2); 632 } 633 634 if (isr & ISR_PRX) 635 frames = ne2k_receive(ne2k); 636 637 if (isr & ISR_RST) { 637 638 /* 638 639 * The chip is stopped, and all arrived … … 642 643 } 643 644 644 /* Signal a next frame to be sent */ 645 if (signal) 646 fibril_condvar_broadcast(&ne2k->sq_cv); 645 /* Unmask interrupts to be processed in the next round */ 646 pio_write_8(ne2k->port + DP_IMR, 647 IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE); 648 649 return frames; 647 650 } 648 651
Note:
See TracChangeset
for help on using the changeset viewer.