Changeset a35b458 in mainline for uspace/drv/nic/ne2k
- Timestamp:
- 2018-03-02T20:10:49Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- Location:
- uspace/drv/nic/ne2k
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/nic/ne2k/dp8390.c
r3061bc1 ra35b458 74 74 /** Copy of RSR */ 75 75 uint8_t status; 76 76 77 77 /** Pointer to next frame */ 78 78 uint8_t next; 79 79 80 80 /** Receive Byte Count Low */ 81 81 uint8_t rbcl; 82 82 83 83 /** Receive Byte Count High */ 84 84 uint8_t rbch; … … 95 95 { 96 96 size_t i; 97 97 98 98 for (i = 0; (i << 1) < size; i++) 99 99 *((uint16_t *) buf + i) = pio_read_16((ioport16_t *) (port)); … … 110 110 { 111 111 size_t i; 112 112 113 113 for (i = 0; (i << 1) < size; i++) 114 114 pio_write_16((ioport16_t *) port, *((uint16_t *) buf + i)); … … 118 118 { 119 119 size_t esize = size & ~1; 120 120 121 121 pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff); 122 122 pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff); … … 124 124 pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff); 125 125 pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 126 126 127 127 if (esize != 0) { 128 128 pio_read_buf_16(ne2k->data_port, buf, esize); … … 130 130 buf += esize; 131 131 } 132 132 133 133 if (size) { 134 134 assert(size == 1); 135 135 136 136 uint16_t word = pio_read_16(ne2k->data_port); 137 137 memcpy(buf, &word, 1); … … 143 143 size_t esize_ru = (size + 1) & ~1; 144 144 size_t esize = size & ~1; 145 145 146 146 pio_write_8(ne2k->port + DP_RBCR0, esize_ru & 0xff); 147 147 pio_write_8(ne2k->port + DP_RBCR1, (esize_ru >> 8) & 0xff); … … 149 149 pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff); 150 150 pio_write_8(ne2k->port + DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 151 151 152 152 if (esize != 0) { 153 153 pio_write_buf_16(ne2k->data_port, buf, esize); … … 155 155 buf += esize; 156 156 } 157 157 158 158 if (size) { 159 159 assert(size == 1); 160 160 161 161 uint16_t word = 0; 162 162 163 163 memcpy(&word, buf, 1); 164 164 pio_write_16(ne2k->data_port, word); … … 169 169 { 170 170 unsigned int i; 171 171 172 172 /* Reset the ethernet card */ 173 173 uint8_t val = pio_read_8(ne2k->port + NE2K_RESET); … … 175 175 pio_write_8(ne2k->port + NE2K_RESET, val); 176 176 async_usleep(2000); 177 177 178 178 /* Reset the DP8390 */ 179 179 pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT); … … 197 197 { 198 198 unsigned int i; 199 199 200 200 ne2k_init(ne2k); 201 201 202 202 /* Check if the DP8390 is really there */ 203 203 uint8_t val = pio_read_8(ne2k->port + DP_CR); 204 204 if ((val & (CR_STP | CR_TXP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT)) 205 205 return EXDEV; 206 206 207 207 /* Disable the receiver and init TCR and DCR */ 208 208 pio_write_8(ne2k->port + DP_RCR, RCR_MON); 209 209 pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL); 210 210 pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS); 211 211 212 212 /* Setup a transfer to get the MAC address */ 213 213 pio_write_8(ne2k->port + DP_RBCR0, ETH_ADDR << 1); … … 216 216 pio_write_8(ne2k->port + DP_RSAR1, 0); 217 217 pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 218 218 219 219 for (i = 0; i < ETH_ADDR; i++) 220 220 ne2k->mac.address[i] = pio_read_16(ne2k->data_port); 221 221 222 222 return EOK; 223 223 } … … 226 226 { 227 227 memcpy(&ne2k->mac, address, sizeof(nic_address_t)); 228 228 229 229 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STP); 230 230 231 231 pio_write_8(ne2k->port + DP_RBCR0, ETH_ADDR << 1); 232 232 pio_write_8(ne2k->port + DP_RBCR1, 0); … … 254 254 if (!ne2k->probed) 255 255 return EXDEV; 256 256 257 257 ne2k_init(ne2k); 258 258 259 259 /* 260 260 * Setup send queue. Use the first … … 266 266 fibril_mutex_initialize(&ne2k->sq_mutex); 267 267 fibril_condvar_initialize(&ne2k->sq_cv); 268 268 269 269 /* 270 270 * Setup receive ring buffer. Use all the rest … … 275 275 ne2k->start_page = ne2k->sq.page + SQ_PAGES; 276 276 ne2k->stop_page = ne2k->sq.page + NE2K_SIZE / DP_PAGE; 277 277 278 278 /* 279 279 * Initialization of the DP8390 following the mandatory procedure … … 281 281 * Controller", National Semiconductor, July 1995, Page 29). 282 282 */ 283 283 284 284 /* Step 1: */ 285 285 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT); 286 286 287 287 /* Step 2: */ 288 288 pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS); 289 289 290 290 /* Step 3: */ 291 291 pio_write_8(ne2k->port + DP_RBCR0, 0); 292 292 pio_write_8(ne2k->port + DP_RBCR1, 0); 293 293 294 294 /* Step 4: */ 295 295 pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration); 296 296 297 297 /* Step 5: */ 298 298 pio_write_8(ne2k->port + DP_TCR, TCR_INTERNAL); 299 299 300 300 /* Step 6: */ 301 301 pio_write_8(ne2k->port + DP_BNRY, ne2k->start_page); 302 302 pio_write_8(ne2k->port + DP_PSTART, ne2k->start_page); 303 303 pio_write_8(ne2k->port + DP_PSTOP, ne2k->stop_page); 304 304 305 305 /* Step 7: */ 306 306 pio_write_8(ne2k->port + DP_ISR, 0xff); 307 307 308 308 /* Step 8: */ 309 309 pio_write_8(ne2k->port + DP_IMR, 310 310 IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE); 311 311 312 312 /* Step 9: */ 313 313 pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP); 314 314 315 315 pio_write_8(ne2k->port + DP_PAR0, ne2k->mac.address[0]); 316 316 pio_write_8(ne2k->port + DP_PAR1, ne2k->mac.address[1]); … … 319 319 pio_write_8(ne2k->port + DP_PAR4, ne2k->mac.address[4]); 320 320 pio_write_8(ne2k->port + DP_PAR5, ne2k->mac.address[5]); 321 321 322 322 pio_write_8(ne2k->port + DP_MAR0, 0); 323 323 pio_write_8(ne2k->port + DP_MAR1, 0); … … 328 328 pio_write_8(ne2k->port + DP_MAR6, 0); 329 329 pio_write_8(ne2k->port + DP_MAR7, 0); 330 330 331 331 pio_write_8(ne2k->port + DP_CURR, ne2k->start_page + 1); 332 332 333 333 /* Step 10: */ 334 334 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA); 335 335 336 336 /* Step 11: */ 337 337 pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL); 338 338 339 339 /* Reset counters by reading */ 340 340 pio_read_8(ne2k->port + DP_CNTR0); 341 341 pio_read_8(ne2k->port + DP_CNTR1); 342 342 pio_read_8(ne2k->port + DP_CNTR2); 343 343 344 344 /* Finish the initialization */ 345 345 ne2k->up = true; … … 415 415 416 416 fibril_mutex_lock(&ne2k->sq_mutex); 417 417 418 418 while (ne2k->sq.dirty) { 419 419 fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex); 420 420 } 421 421 422 422 if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) { 423 423 fibril_mutex_unlock(&ne2k->sq_mutex); … … 446 446 if (frame == NULL) 447 447 return NULL; 448 448 449 449 memset(frame->data, 0, length); 450 450 uint8_t last = page + length / DP_PAGE; 451 451 452 452 if (last >= ne2k->stop_page) { 453 453 size_t left = (ne2k->stop_page - page) * DP_PAGE … … 481 481 //TODO: isn't some locking necessary here? 482 482 uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1; 483 483 484 484 if (boundary == ne2k->stop_page) 485 485 boundary = ne2k->start_page; 486 486 487 487 pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_STA); 488 488 uint8_t current = pio_read_8(ne2k->port + DP_CURR); … … 491 491 /* No more frames to process */ 492 492 break; 493 493 494 494 recv_header_t header; 495 495 size_t size = sizeof(header); 496 496 size_t offset = boundary * DP_PAGE; 497 497 498 498 /* Get the frame header */ 499 499 pio_write_8(ne2k->port + DP_RBCR0, size & 0xff); … … 502 502 pio_write_8(ne2k->port + DP_RSAR1, (offset >> 8) & 0xff); 503 503 pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 504 504 505 505 pio_read_buf_16(ne2k->data_port, (void *) &header, size); 506 506 … … 508 508 (((size_t) header.rbcl) | (((size_t) header.rbch) << 8)) - size; 509 509 uint8_t next = header.next; 510 510 511 511 if ((length < ETH_MIN_PACK_SIZE) 512 512 || (length > ETH_MAX_PACK_SIZE_TAGGED)) { … … 535 535 break; 536 536 } 537 537 538 538 /* 539 539 * Update the boundary pointer … … 585 585 ne2k->sq.dirty = false; 586 586 ne2k->sq.size = 0; 587 587 588 588 /* Signal a next frame to be sent */ 589 589 fibril_condvar_broadcast(&ne2k->sq_cv); … … 615 615 ne2k_reset(ne2k); 616 616 } 617 617 618 618 /* Unmask interrupts to be processed in the next round */ 619 619 pio_write_8(ne2k->port + DP_IMR, … … 627 627 else 628 628 ne2k->receive_configuration &= ~RCR_AB; 629 629 630 630 pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration); 631 631 } … … 637 637 else 638 638 ne2k->receive_configuration &= ~RCR_AM; 639 639 640 640 pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration); 641 641 } … … 647 647 else 648 648 ne2k->receive_configuration &= ~RCR_PRO; 649 649 650 650 pio_write_8(ne2k->port + DP_RCR, ne2k->receive_configuration); 651 651 } … … 655 655 /* Select Page 1 and stop all transfers */ 656 656 pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP); 657 657 658 658 pio_write_8(ne2k->port + DP_MAR0, (uint8_t) hash); 659 659 pio_write_8(ne2k->port + DP_MAR1, (uint8_t) (hash >> 8)); … … 664 664 pio_write_8(ne2k->port + DP_MAR6, (uint8_t) (hash >> 48)); 665 665 pio_write_8(ne2k->port + DP_MAR7, (uint8_t) (hash >> 56)); 666 666 667 667 /* Select Page 0 and resume transfers */ 668 668 pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA); -
uspace/drv/nic/ne2k/dp8390.h
r3061bc1 ra35b458 235 235 int irq; 236 236 nic_address_t mac; 237 237 238 238 uint8_t start_page; /**< Ring buffer start page */ 239 239 uint8_t stop_page; /**< Ring buffer stop page */ 240 240 241 241 /* Send queue */ 242 242 struct { … … 247 247 fibril_mutex_t sq_mutex; 248 248 fibril_condvar_t sq_cv; 249 249 250 250 /* Driver run-time variables */ 251 251 bool probed; -
uspace/drv/nic/ne2k/ne2k.c
r3061bc1 ra35b458 183 183 hw_res_list_parsed_t hw_res_parsed; 184 184 hw_res_list_parsed_init(&hw_res_parsed); 185 185 186 186 errno_t rc = nic_get_resources(nic_data, &hw_res_parsed); 187 187 188 188 if (rc != EOK) 189 189 goto failed; 190 190 191 191 if (hw_res_parsed.irqs.count == 0) { 192 192 rc = EINVAL; 193 193 goto failed; 194 194 } 195 195 196 196 if (hw_res_parsed.io_ranges.count == 0) { 197 197 rc = EINVAL; 198 198 goto failed; 199 199 } 200 200 201 201 if (hw_res_parsed.io_ranges.ranges[0].size < NE2K_IO_SIZE) { 202 202 rc = EINVAL; 203 203 goto failed; 204 204 } 205 205 206 206 ne2k_t *ne2k = (ne2k_t *) nic_get_specific(nic_data); 207 207 ne2k->irq = hw_res_parsed.irqs.irqs[0]; 208 208 209 209 addr_range_t regs = hw_res_parsed.io_ranges.ranges[0]; 210 210 ne2k->base_port = RNGABSPTR(regs); 211 211 212 212 hw_res_list_parsed_clean(&hw_res_parsed); 213 213 214 214 /* Enable programmed I/O */ 215 215 if (pio_enable_range(®s, &ne2k->port) != EOK) 216 216 return EADDRNOTAVAIL; 217 217 218 218 ne2k->data_port = ne2k->port + NE2K_DATA; 219 219 ne2k->receive_configuration = RCR_AB | RCR_AM; 220 220 ne2k->probed = false; 221 221 ne2k->up = false; 222 222 223 223 /* Find out whether the device is present. */ 224 224 if (ne2k_probe(ne2k) != EOK) 225 225 return ENOENT; 226 226 227 227 ne2k->probed = true; 228 228 229 229 if (ne2k_register_interrupt(nic_data, NULL) != EOK) 230 230 return EINVAL; 231 231 232 232 return EOK; 233 233 234 234 failed: 235 235 hw_res_list_parsed_clean(&hw_res_parsed); … … 358 358 { 359 359 ddf_fun_t *fun; 360 360 361 361 /* Allocate driver data for the device. */ 362 362 nic_t *nic_data = nic_create_and_bind(dev); 363 363 if (nic_data == NULL) 364 364 return ENOMEM; 365 365 366 366 nic_set_send_frame_handler(nic_data, ne2k_send); 367 367 nic_set_state_change_handlers(nic_data, … … 370 370 ne2k_on_unicast_mode_change, ne2k_on_multicast_mode_change, 371 371 ne2k_on_broadcast_mode_change, NULL, NULL); 372 372 373 373 ne2k_t *ne2k = malloc(sizeof(ne2k_t)); 374 374 if (NULL != ne2k) { … … 379 379 return ENOMEM; 380 380 } 381 381 382 382 ne2k->dev = dev; 383 383 ne2k->parent_sess = ddf_dev_parent_sess_get(dev); … … 386 386 return ENOMEM; 387 387 } 388 388 389 389 errno_t rc = ne2k_dev_init(nic_data); 390 390 if (rc != EOK) { … … 392 392 return rc; 393 393 } 394 394 395 395 rc = nic_report_address(nic_data, &ne2k->mac); 396 396 if (rc != EOK) { … … 398 398 return rc; 399 399 } 400 400 401 401 fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0"); 402 402 if (fun == NULL) { … … 404 404 return ENOMEM; 405 405 } 406 406 407 407 nic_set_ddf_fun(nic_data, fun); 408 408 ddf_fun_set_ops(fun, &ne2k_dev_ops); 409 409 410 410 rc = ddf_fun_bind(fun); 411 411 if (rc != EOK) { … … 414 414 return rc; 415 415 } 416 416 417 417 rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); 418 418 if (rc != EOK) { … … 421 421 return rc; 422 422 } 423 423 424 424 return EOK; 425 425 } … … 441 441 { 442 442 printf("%s: HelenOS NE 2000 network adapter driver\n", NAME); 443 443 444 444 nic_driver_init(NAME); 445 445 nic_driver_implement(&ne2k_driver_ops, &ne2k_dev_ops, &ne2k_nic_iface); 446 446 447 447 return ddf_driver_main(&ne2k_driver); 448 448 }
Note:
See TracChangeset
for help on using the changeset viewer.