Changeset 90782c36 in mainline
- Timestamp:
- 2014-05-21T19:36:59Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1ac202
- Parents:
- fef725d
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
rfef725d r90782c36 138 138 nic/e1k \ 139 139 nic/rtl8139 \ 140 nic/rtl8169 \ 140 141 block/ahci 141 142 -
uspace/drv/nic/rtl8169/Makefile
rfef725d r90782c36 34 34 35 35 SOURCES = \ 36 driver.c \ 37 general.c \ 38 defs.c 36 driver.c 39 37 40 38 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/nic/rtl8169/defs.h
rfef725d r90782c36 87 87 WAKEUP3LD = 0xa4, /**< Power Management Wakeup frame3 low dword, 8b */ 88 88 WAKEUP3HD = 0xac, /**< Power Management Wakeup frame3 high dword, 8b */ 89 WAKEUP 2LD = 0xb4, /**< Power Management Wakeup frame4 low dword, 8b */90 WAKEUP 2HD = 0xbc, /**< Power Management Wakeup frame4 high dword, 8b */89 WAKEUP4LD = 0xb4, /**< Power Management Wakeup frame4 low dword, 8b */ 90 WAKEUP4HD = 0xbc, /**< Power Management Wakeup frame4 high dword, 8b */ 91 91 CRC0 = 0xc4, /**< 16-bit CRC of wakeup frame 0, 2b */ 92 92 CRC1 = 0xc6, /**< 16-bit CRC of wakeup frame 1, 2b */ … … 132 132 CONFIG2_PCICLKF_SHIFT = 0, 133 133 CONFIG2_PCICLKF_SIZE = 2 134 } '134 }; 135 135 136 136 enum rtl8169_config3 { … … 240 240 ANAR_10_FD = (1 << 6), /**< 10BASE_T full duplex */ 241 241 ANAR_10_HD = (1 << 5), /**< 10BASE_T half duplex */ 242 ANAR_SELECTOR = 0x1. /**< Selector */ 242 ANAR_SELECTOR = 0x1, /**< Selector */ 243 }; 244 245 enum rtl8169_phystatus { 246 PHYSTATUS_TBIEN = (1 << 7), /**< TBI enabled */ 247 PHYSTATUS_TXFLOW = (1 << 6), /**< TX flow control enabled */ 248 PHYSTATUS_RXFLOW = (1 << 5), /**< RX flow control enabled */ 249 PHYSTATUS_1000M = (1 << 4), /**< Link speed is 1000Mbit/s */ 250 PHYSTATUS_100M = (1 << 3), /**< Link speed is 100Mbit/s */ 251 PHYSTATUS_10M = (1 << 2), /**< Link speed is 10Mbit/s */ 252 PHYSTATUS_LINK = (1 << 1), /**< Link up */ 253 PHYSTATUS_FDX = (1 << 0), /**< Link is full duplex */ 243 254 }; 244 255 -
uspace/drv/nic/rtl8169/driver.c
rfef725d r90782c36 55 55 FIBRIL_MUTEX_INITIALIZE(irq_reg_lock); 56 56 57 static int rtl8169_set_addr(ddf_fun_t *fun, const nic_address_t *addr); 58 static int rtl8169_get_device_info(ddf_fun_t *fun, nic_device_info_t *info); 59 static int rtl8169_get_cable_state(ddf_fun_t *fun, nic_cable_state_t *state); 60 static int rtl8169_get_operation_mode(ddf_fun_t *fun, int *speed, 61 nic_channel_mode_t *duplex, nic_role_t *role); 62 static int rtl8169_set_operation_mode(ddf_fun_t *fun, int speed, 63 nic_channel_mode_t duplex, nic_role_t role); 64 static int rtl8169_pause_get(ddf_fun_t *fun, nic_result_t *we_send, 65 nic_result_t *we_receive, uint16_t *time); 66 static int rtl8169_pause_set(ddf_fun_t *fun, int allow_send, int allow_receive, 67 uint16_t time); 68 static int rtl8169_autoneg_enable(ddf_fun_t *fun, uint32_t advertisement); 69 static int rtl8169_autoneg_disable(ddf_fun_t *fun); 70 static int rtl8169_autoneg_probe(ddf_fun_t *fun, uint32_t *advertisement, 71 uint32_t *their_adv, nic_result_t *result, nic_result_t *their_result); 72 static int rtl8169_autoneg_restart(ddf_fun_t *fun); 73 static int rtl8169_defective_get_mode(ddf_fun_t *fun, uint32_t *mode); 74 static int rtl8169_defective_set_mode(ddf_fun_t *fun, uint32_t mode); 75 static int rtl8169_on_activated(nic_t *nic_data); 76 static int rtl8169_on_stopped(nic_t *nic_data); 77 static void rtl8169_send_frame(nic_t *nic_data, void *data, size_t size); 78 static void rtl8169_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, 79 ipc_call_t *icall); 80 static inline int rtl8169_register_int_handler(nic_t *nic_data); 81 static inline void rtl8169_get_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr); 82 static inline void rtl8169_set_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr); 83 84 static void rtl8169_reset(rtl8169_t *rtl8169); 85 static int rtl8169_get_resource_info(ddf_dev_t *dev); 86 static int rtl8169_fill_resource_info(ddf_dev_t *dev, const hw_res_list_parsed_t *hw_resources); 87 static rtl8169_t *rtl8169_create_dev_data(ddf_dev_t *dev); 88 57 89 /** Network interface options for RTL8169 card driver */ 58 90 static nic_iface_t rtl8169_nic_iface = { … … 75 107 }; 76 108 109 irq_pio_range_t rtl8169_irq_pio_ranges[] = { 110 { 111 .base = 0, 112 .size = RTL8169_IO_SIZE 113 } 114 }; 115 116 irq_cmd_t rtl8169_irq_commands[] = { 117 { 118 /* Get the interrupt status */ 119 .cmd = CMD_PIO_READ_16, 120 .addr = NULL, 121 .dstarg = 2 122 }, 123 { 124 .cmd = CMD_PREDICATE, 125 .value = 3, 126 .srcarg = 2 127 }, 128 { 129 /* Mark interrupts as solved */ 130 .cmd = CMD_PIO_WRITE_16, 131 .addr = NULL, 132 .value = 0xFFFF 133 }, 134 { 135 /* Disable interrupts until interrupt routine is finished */ 136 .cmd = CMD_PIO_WRITE_16, 137 .addr = NULL, 138 .value = 0x0000 139 }, 140 { 141 .cmd = CMD_ACCEPT 142 } 143 }; 144 145 /** Interrupt code definition */ 146 irq_code_t rtl8169_irq_code = { 147 .rangecount = sizeof(rtl8169_irq_pio_ranges) / sizeof(irq_pio_range_t), 148 .ranges = rtl8169_irq_pio_ranges, 149 .cmdcount = sizeof(rtl8169_irq_commands) / sizeof(irq_cmd_t), 150 .cmds = rtl8169_irq_commands 151 }; 152 77 153 /** Basic device operations for RTL8169 driver */ 78 154 static ddf_dev_ops_t rtl8169_dev_ops; … … 91 167 }; 92 168 169 static int rtl8169_get_resource_info(ddf_dev_t *dev) 170 { 171 assert(dev); 172 173 nic_t *nic_data = nic_get_from_ddf_dev(dev); 174 assert(nic_data); 175 176 hw_res_list_parsed_t hw_res_parsed; 177 hw_res_list_parsed_init(&hw_res_parsed); 178 179 /* Get hw resources form parent driver */ 180 int rc = nic_get_resources(nic_data, &hw_res_parsed); 181 if (rc != EOK) 182 return rc; 183 184 /* Fill resources information to the device */ 185 int ret = rtl8169_fill_resource_info(dev, &hw_res_parsed); 186 hw_res_list_parsed_clean(&hw_res_parsed); 187 188 return ret; 189 } 190 191 static int rtl8169_fill_resource_info(ddf_dev_t *dev, const hw_res_list_parsed_t 192 *hw_resources) 193 { 194 assert(dev); 195 assert(hw_resources); 196 197 rtl8169_t *rtl8169 = nic_get_specific(nic_get_from_ddf_dev(dev)); 198 assert(rtl8169); 199 200 if (hw_resources->irqs.count != 1) { 201 ddf_msg(LVL_ERROR, "%s device: unexpected irq count", ddf_dev_get_name(dev)); 202 return EINVAL; 203 }; 204 if (hw_resources->io_ranges.count != 1) { 205 ddf_msg(LVL_ERROR, "%s device: unexpected io ranges count", ddf_dev_get_name(dev)); 206 return EINVAL; 207 } 208 209 rtl8169->irq = hw_resources->irqs.irqs[0]; 210 ddf_msg(LVL_DEBUG, "%s device: irq 0x%x assigned", ddf_dev_get_name(dev), rtl8169->irq); 211 212 rtl8169->regs_phys = (void *)((size_t)RNGABS(hw_resources->io_ranges.ranges[0])); 213 if (hw_resources->io_ranges.ranges[0].size < RTL8169_IO_SIZE) { 214 ddf_msg(LVL_ERROR, "I/O range assigned to the device " 215 "%s is too small.", ddf_dev_get_name(dev)); 216 return EINVAL; 217 } 218 ddf_msg(LVL_DEBUG, "%s device: i/o addr %p assigned.", ddf_dev_get_name(dev), rtl8169->regs_phys); 219 220 return EOK; 221 } 222 223 static rtl8169_t *rtl8169_create_dev_data(ddf_dev_t *dev) 224 { 225 assert(dev); 226 assert(!nic_get_from_ddf_dev(dev)); 227 228 nic_t *nic_data = nic_create_and_bind(dev); 229 if (!nic_data) 230 return NULL; 231 232 rtl8169_t *rtl8169 = malloc(sizeof(rtl8169_t)); 233 if (!rtl8169) { 234 nic_unbind_and_destroy(dev); 235 return NULL; 236 } 237 238 memset(rtl8169, 0, sizeof(rtl8169_t)); 239 240 rtl8169->nic_data = nic_data; 241 nic_set_specific(nic_data, rtl8169); 242 nic_set_send_frame_handler(nic_data, rtl8169_send_frame); 243 nic_set_state_change_handlers(nic_data, 244 rtl8169_on_activated, NULL, rtl8169_on_stopped); 245 nic_set_filtering_change_handlers(nic_data, 246 NULL, NULL, NULL, NULL, NULL); 247 248 fibril_mutex_initialize(&rtl8169->rx_lock); 249 fibril_mutex_initialize(&rtl8169->tx_lock); 250 251 nic_set_wol_max_caps(nic_data, NIC_WV_BROADCAST, 1); 252 nic_set_wol_max_caps(nic_data, NIC_WV_LINK_CHANGE, 1); 253 nic_set_wol_max_caps(nic_data, NIC_WV_MAGIC_PACKET, 1); 254 255 return rtl8169; 256 } 257 258 259 static int rtl8169_dev_initialize(ddf_dev_t *dev) 260 { 261 int ret; 262 263 rtl8169_t *rtl8169 = rtl8169_create_dev_data(dev); 264 if (rtl8169 == NULL) { 265 ddf_msg(LVL_ERROR, "Not enough memory for initializing %s.", ddf_dev_get_name(dev)); 266 return ENOMEM; 267 } 268 269 ret = rtl8169_get_resource_info(dev); 270 if (ret != EOK) { 271 ddf_msg(LVL_ERROR, "Can't obtain H/W resources information"); 272 goto failed; 273 } 274 275 ddf_msg(LVL_DEBUG, "The device is initialized"); 276 return ret; 277 278 failed: 279 ddf_msg(LVL_ERROR, "The device initialization failed"); 280 // rtl8139_dev_cleanup(dev); 281 return ret; 282 283 } 284 285 inline static int rtl8169_register_int_handler(nic_t *nic_data) 286 { 287 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 288 289 rtl8169_irq_code.ranges[0].base = (uintptr_t) rtl8169->regs; 290 rtl8169_irq_code.cmds[0].addr = rtl8169->regs + ISR; 291 rtl8169_irq_code.cmds[2].addr = rtl8169->regs + ISR; 292 rtl8169_irq_code.cmds[3].addr = rtl8169->regs + IMR; 293 int rc = register_interrupt_handler(nic_get_ddf_dev(nic_data), 294 rtl8169->irq, rtl8169_irq_handler, &rtl8169_irq_code); 295 296 return rc; 297 } 298 93 299 static int rtl8169_dev_add(ddf_dev_t *dev) 94 300 { 95 301 ddf_fun_t *fun; 302 nic_address_t nic_addr; 96 303 int rc; 97 304 … … 99 306 ddf_msg(LVL_NOTE, "RTL8169_dev_add %s (handle = %zu)", 100 307 ddf_dev_get_name(dev), ddf_dev_get_handle(dev)); 308 101 309 102 310 /* Init structures */ … … 105 313 return rc; 106 314 315 nic_t *nic_data = nic_get_from_ddf_dev(dev); 316 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 317 318 /* Map register space */ 319 rc = pio_enable(rtl8169->regs_phys, RTL8169_IO_SIZE, &rtl8169->regs); 320 if (rc != EOK) { 321 ddf_msg(LVL_ERROR, "Cannot map register space for device %s.", 322 ddf_dev_get_name(dev)); 323 goto err_destroy; 324 } 325 326 /* Read MAC address and print it */ 327 rtl8169_get_hwaddr(rtl8169, &nic_addr); 328 ddf_msg(LVL_NOTE, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x", 329 nic_addr.address[0], nic_addr.address[1], 330 nic_addr.address[2], nic_addr.address[3], 331 nic_addr.address[4], nic_addr.address[5]); 332 333 rc = nic_report_address(nic_data, &nic_addr); 334 if (rc != EOK) 335 goto err_pio; 336 337 rc = rtl8169_register_int_handler(nic_data); 338 if (rc != EOK) { 339 ddf_msg(LVL_ERROR, "Failed to register IRQ handler (%d)", rc); 340 goto err_irq; 341 342 } 343 344 ddf_msg(LVL_DEBUG, "Interrupt handler installed"); 345 346 rtl8169_reset(rtl8169); 347 pio_write_16(rtl8169->regs + IMR, 0xffff); 348 349 uint8_t cr_value = pio_read_8(rtl8169->regs + CR); 350 pio_write_8(rtl8169->regs + CR, cr_value | CR_TE | CR_RE); 351 352 rc = nic_connect_to_services(nic_data); 353 if (rc != EOK) { 354 ddf_msg(LVL_ERROR, "Failed to connect to services (%d)", rc); 355 goto err_irq; 356 } 357 358 fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0"); 359 if (fun == NULL) { 360 ddf_msg(LVL_ERROR, "Failed creating device function"); 361 goto err_srv; 362 } 363 364 nic_set_ddf_fun(nic_data, fun); 365 ddf_fun_set_ops(fun, &rtl8169_dev_ops); 366 ddf_fun_data_implant(fun, nic_data); 367 368 rc = ddf_fun_bind(fun); 369 if (rc != EOK) { 370 ddf_msg(LVL_ERROR, "Failed binding device function"); 371 goto err_fun_create; 372 } 373 374 rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); 375 if (rc != EOK) { 376 ddf_msg(LVL_ERROR, "Failed adding function to category"); 377 goto err_fun_bind; 378 } 379 380 ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.", 381 ddf_dev_get_name(dev)); 382 return EOK; 383 384 err_fun_bind: 385 ddf_fun_unbind(fun); 386 err_fun_create: 387 ddf_fun_destroy(fun); 388 err_srv: 389 /* XXX Disconnect from services */ 390 err_irq: 391 //unregister_interrupt_handler(dev, rtl8169->irq); 392 err_pio: 393 err_destroy: 394 //rtl8169_dev_cleanup(dev); 395 return rc; 396 107 397 return EOK; 108 398 } … … 139 429 { 140 430 return EOK; 141 { 431 } 142 432 143 433 static int rtl8169_pause_set(ddf_fun_t *fun, int allow_send, int allow_receive, … … 178 468 } 179 469 470 static int rtl8169_on_activated(nic_t *nic_data) 471 { 472 ddf_msg(LVL_NOTE, "Activating device"); 473 474 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 475 476 pio_write_16(rtl8169->regs + IMR, 0xffff); 477 478 return EOK; 479 } 480 481 static int rtl8169_on_stopped(nic_t *nic_data) 482 { 483 return EOK; 484 } 485 486 inline static void rtl8169_reset(rtl8169_t *rtl8169) 487 { 488 pio_write_8(rtl8169->regs + CR, CR_RST); 489 memory_barrier(); 490 while (pio_read_8(rtl8169->regs + CR) & CR_RST) { 491 usleep(1); 492 read_barrier(); 493 } 494 } 495 496 static void rtl8169_link_change(ddf_dev_t *dev) 497 { 498 nic_t *nic_data = nic_get_from_ddf_dev(dev); 499 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 500 501 uint8_t phystatus = pio_read_8(rtl8169->regs + PHYSTATUS); 502 503 if (phystatus & PHYSTATUS_LINK) { 504 ddf_msg(LVL_NOTE, "%s: Link up", ddf_dev_get_name(dev)); 505 506 int speed; 507 const char *fdx = phystatus & PHYSTATUS_FDX ? "full duplex" : "half duplex"; 508 509 if (phystatus & PHYSTATUS_10M) 510 speed = 10; 511 512 if (phystatus & PHYSTATUS_100M) 513 speed = 100; 514 515 if (phystatus & PHYSTATUS_1000M) 516 speed = 1000; 517 518 ddf_msg(LVL_NOTE, "%s: Speed %dMbit/s, %s", ddf_dev_get_name(dev), speed, fdx); 519 } else { 520 ddf_msg(LVL_NOTE, "%s: Link down", ddf_dev_get_name(dev)); 521 } 522 523 } 524 525 static void rtl8169_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, 526 ipc_call_t *icall) 527 { 528 assert(dev); 529 assert(icall); 530 531 ddf_msg(LVL_NOTE, "rtl8169_irq_handler()"); 532 533 uint16_t isr = (uint16_t) IPC_GET_ARG2(*icall); 534 nic_t *nic_data = nic_get_from_ddf_dev(dev); 535 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 536 537 /* Packet underrun or link change */ 538 if (isr & INT_PUN) 539 rtl8169_link_change(dev); 540 541 pio_write_16(rtl8169->regs + IMR, 0xffff); 542 } 543 180 544 static void rtl8169_send_frame(nic_t *nic_data, void *data, size_t size) 181 545 { 182 546 547 } 548 549 static inline void rtl8169_get_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr) 550 { 551 int i; 552 553 assert(rtl8169); 554 assert(addr); 555 556 for (i = 0; i < 6; i++) 557 addr->address[i] = pio_read_8(rtl8169->regs + MAC0 + i); 558 } 559 560 static inline void rtl8169_set_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr) 561 { 562 int i; 563 564 assert(rtl8169); 565 assert(addr); 566 567 for (i = 0; i < 6; i++) 568 addr->address[i] = pio_read_8(rtl8169->regs + MAC0 + i); 183 569 } 184 570 -
uspace/drv/nic/rtl8169/driver.h
rfef725d r90782c36 38 38 #define NAME "rtl8169" 39 39 40 #define TX_BUFF_COUNT 16 41 42 /** RTL8139 device data */ 43 typedef struct rtl8169_data { 44 /** I/O address of the device */ 45 void *regs_phys; 46 /** Mapped I/O port */ 47 void *regs; 48 /** The irq assigned */ 49 int irq; 50 51 /** Mask of the turned interupts (IMR value) */ 52 uint16_t int_mask; 53 54 /** The memory allocated for the transmittion buffers 55 * Each buffer takes 2kB 56 */ 57 uintptr_t tx_buff_phys; 58 void *tx_buff_virt; 59 60 /** Virtual adresses of the Tx buffers */ 61 void *tx_buff[TX_BUFF_COUNT]; 62 63 /** The nubmer of the next buffer to use, index = tx_next % TX_BUFF_COUNT */ 64 size_t tx_next; 65 /** The number of the first used buffer in the row 66 * 67 * tx_used is in the interval tx_next - TX_BUFF_COUNT and tx_next: 68 * tx_next - TX_BUFF_COUNT: there is no useable Tx descriptor 69 * tx_next: all Tx descriptors are can be used 70 */ 71 size_t tx_used; 72 73 /** Buffer for receiving frames */ 74 uintptr_t rx_buff_phys; 75 void *rx_buff_virt; 76 77 /** Lock for receiver */ 78 fibril_mutex_t rx_lock; 79 /** Lock for transmitter */ 80 fibril_mutex_t tx_lock; 81 82 /** Backward pointer to nic_data */ 83 nic_t *nic_data; 84 85 } rtl8169_t; 86 40 87 #endif
Note:
See TracChangeset
for help on using the changeset viewer.