Changes in / [8136102:6643a19] in mainline
- Location:
- uspace
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/net/netif/netif_skel.c
r8136102 r6643a19 130 130 if (result > NETIF_NULL) { 131 131 int phone = device->nil_phone; 132 fibril_rwlock_write_unlock(&netif_globals.lock); 132 133 nil_device_state_msg(phone, device_id, result); 133 fibril_rwlock_write_unlock(&netif_globals.lock);134 134 return EOK; 135 135 } … … 166 166 if (result > NETIF_NULL) { 167 167 int phone = device->nil_phone; 168 fibril_rwlock_write_unlock(&netif_globals.lock); 168 169 nil_device_state_msg(phone, device_id, result); 169 fibril_rwlock_write_unlock(&netif_globals.lock);170 170 return EOK; 171 171 } -
uspace/srv/hw/netif/dp8390/dp8390.c
r8136102 r6643a19 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 -
uspace/srv/hw/netif/dp8390/dp8390.h
r8136102 r6643a19 50 50 51 51 #include <fibril_synch.h> 52 #include <adt/list.h>53 52 #include <net/packet.h> 54 #include <netif_skel.h>55 53 56 54 /** Module name */ … … 232 230 } ne2k_t; 233 231 234 typedef struct {235 link_t link;236 packet_t *packet;237 } frame_t;238 239 232 extern int ne2k_probe(ne2k_t *, void *, int); 240 233 extern int ne2k_up(ne2k_t *); 241 234 extern void ne2k_down(ne2k_t *); 242 235 extern void ne2k_send(ne2k_t *, packet_t *); 243 extern link_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);236 extern void ne2k_interrupt(ne2k_t *, uint8_t isr, int, device_id_t); 244 237 245 238 #endif -
uspace/srv/hw/netif/dp8390/ne2000.c
r8136102 r6643a19 68 68 #define IRQ_GET_ISR(call) ((int) IPC_GET_ARG2(call)) 69 69 70 /** Return the TSR from the interrupt call.71 *72 * @param[in] call The interrupt call.73 *74 */75 #define IRQ_GET_TSR(call) ((int) IPC_GET_ARG3(call))76 77 70 static int irc_service = 0; 78 71 static int irc_phone = -1; … … 83 76 static irq_cmd_t ne2k_cmds[] = { 84 77 { 85 /* Read Interrupt Status Register */86 78 .cmd = CMD_PIO_READ_8, 87 79 .addr = NULL, … … 89 81 }, 90 82 { 91 /* Mask supported interrupt causes */92 83 .cmd = CMD_BTEST, 93 .value = (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW | 94 ISR_CNT | ISR_RDC), 84 .value = 0x7f, 95 85 .srcarg = 2, 96 86 .dstarg = 3, 97 87 }, 98 88 { 99 /* Predicate for accepting the interrupt */100 89 .cmd = CMD_PREDICATE, 101 .value = 4,90 .value = 2, 102 91 .srcarg = 3 103 92 }, 104 93 { 105 /*106 * Mask future interrupts via107 * Interrupt Mask Register108 */109 .cmd = CMD_PIO_WRITE_8,110 .addr = NULL,111 .value = 0112 },113 {114 /* Acknowledge the current interrupt */115 94 .cmd = CMD_PIO_WRITE_A_8, 116 95 .addr = NULL, … … 118 97 }, 119 98 { 120 /* Read Transmit Status Register */121 .cmd = CMD_PIO_READ_8,122 .addr = NULL,123 .dstarg = 3124 },125 {126 99 .cmd = CMD_ACCEPT 127 100 } … … 138 111 /** Handle the interrupt notification. 139 112 * 140 * This is the interrupt notification function. It is quarantied 141 * that there is only a single instance of this notification 142 * function running at one time until the return from the 143 * ne2k_interrupt() function (where the interrupts are unmasked 144 * again). 113 * This is the interrupt notification function. 145 114 * 146 115 * @param[in] iid Interrupt notification identifier. … … 165 134 fibril_rwlock_read_unlock(&netif_globals.lock); 166 135 167 if (ne2k != NULL) { 168 link_t *frames = 169 ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call)); 170 171 if (frames != NULL) { 172 while (!list_empty(frames)) { 173 frame_t *frame = 174 list_get_instance(frames->next, frame_t, link); 175 176 list_remove(&frame->link); 177 nil_received_msg(nil_phone, device_id, frame->packet, 178 SERVICE_NONE); 179 free(frame); 180 } 181 182 free(frames); 183 } 184 } 136 if (ne2k != NULL) 137 ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), nil_phone, device_id); 185 138 } 186 139 … … 312 265 313 266 ne2k_cmds[0].addr = ne2k->port + DP_ISR; 314 ne2k_cmds[3].addr = ne2k->port + DP_IMR; 315 ne2k_cmds[4].addr = ne2k_cmds[0].addr; 267 ne2k_cmds[3].addr = ne2k_cmds[0].addr; 316 268 317 269 int rc = ipc_register_irq(ne2k->irq, device->device_id, … … 326 278 } 327 279 328 change_state(device, NETIF_ACTIVE);329 330 280 if (irc_service) 331 281 async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq); 282 283 change_state(device, NETIF_ACTIVE); 332 284 } 333 285
Note:
See TracChangeset
for help on using the changeset viewer.