1/** 2 * \file 3 * \brief Realtek RTL8029(AS) driver. 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2011 ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15/* 16 * Accessing register pages 17 */ 18#include <stdio.h> 19#include <string.h> 20#include <inttypes.h> 21 22/* 23 * Code to provide page address space access for Mackerel definitions 24 */ 25static void page_select(uint8_t page); 26 27#define PAGE_READ(_d,_a,_s,_p) (page_select(_p), mackerel_read_io_##_s(_d->base,_a)) 28#define PAGE_WRITE(_d,_a,_s,_p,_v) (page_select(_p), mackerel_write_io_##_s(_d->base,_a,_v)) 29 30#define rtl8029as_page0_read_8(d,a) PAGE_READ(d,a,8,rtl8029as_ne2000p0) 31#define rtl8029as_page0_write_8(d,a,v) PAGE_WRITE(d,a,8,rtl8029as_ne2000p0,v) 32#define rtl8029as_page0_read_16(d,a) PAGE_READ(d,a,16,rtl8029as_ne2000p0) 33#define rtl8029as_page0_write_16(d,a,v) PAGE_WRITE(d,a,16,rtl8029as_ne2000p0,v) 34 35#define rtl8029as_page1_read_8(d,a) PAGE_READ(d,a,8,rtl8029as_ne2000p1) 36#define rtl8029as_page1_write_8(d,a,v) PAGE_WRITE(d,a,8,rtl8029as_ne2000p1,v) 37 38#define rtl8029as_p2p0_read_8(d,a) PAGE_READ(d,a,8,rtl8029as_ne2000p2) 39#define rtl8029as_p2p0_write_8(d,a,v) PAGE_WRITE(d,a,8,rtl8029as_ne2000p0,v) 40 41#define rtl8029as_rtlp_read_8(d,a) PAGE_READ(d,a,8,rtl8029as_rtl8029as) 42#define rtl8029as_rtlp_write_8(d,a,v) PAGE_WRITE(d,a,8,rtl8029as_rtl8029as,v) 43#define rtl8029as_rtlp_read_16(d,a) PAGE_READ(d,a,16,rtl8029as_rtl8029as) 44#define rtl8029as_rtlp_write_16(d,a,v) PAGE_WRITE(d,a,16,rtl8029as_rtl8029as,v) 45#define rtl8029as_rtlp_read_32(d,a) PAGE_READ(d,a,32,rtl8029as_rtl8029as) 46#define rtl8029as_rtlp_write_32(d,a,v) PAGE_WRITE(d,a,32,rtl8029as_rtl8029as,v) 47 48#include <net_queue_manager/net_queue_manager.h> 49#include "rtl8029.h" 50#include <dev/rtl8029as_dev.h> 51 52 53/// The only instance of the RTL8029AS we're handling 54static rtl8029as_t rtl; 55 56/// This buffers the card's MAC address upon card reset 57static uint8_t rtl8029_mac[6]; 58 59// Buffer registered by net_queue_mgr library 60static uint8_t *packetbuf = NULL; 61static void *packetbuf_opaque = NULL; 62 63// the length of packet copied into packetbuf 64static uint16_t packet_length; 65 66static uint64_t assumed_queue_id = 0; // queue_id that will be initialized 67 68/** 69 * \brief Select an RTL8029(AS) register page. 70 * 71 * This selects one of the 4 RTL8029(AS) register pages. 72 * 73 * \param page Page to select. 74 */ 75static void page_select(uint8_t page) 76{ 77 /// The currently selected register page 78 static uint8_t current_page = -1; 79 if (current_page != page) { 80 rtl8029as_cr_t cr = rtl8029as_cr_default; 81 cr = rtl8029as_cr_sta_insert(cr, 1); 82 cr = rtl8029as_cr_rd_insert(cr, rtl8029as_acrdma); 83 cr = rtl8029as_cr_ps_insert(cr, page); 84 rtl8029as_cr_wr(&rtl, cr); 85 current_page = page; 86 } 87} 88 89/* 90 * The RTL8029(AS) has 32K of memory, starting at address 0x4000. 91 * That is page 0x40, as each page is 256 bytes in size. Memory is 92 * going up to address 0xc000. 93 */ 94 95 96static uint8_t curr_page = READ_START_PAGE; 97 98 99/** 100 * \brief Yield ASIC memory address from page number. 101 * 102 * \param page Page number. 103 * 104 * \return Corresponding memory address. 105 */ 106static inline uint16_t page_to_mem(uint8_t page) 107{ 108 return page << 8; 109} 110 111/** 112 * \brief Read from ASIC memory. 113 * 114 * \param dst Pointer to buffer to copy data to. If NULL, the data is 115 * thrown away. 116 * \param src Source address in ASIC memory to read from. 117 * \param amount Number of bytes to transfer. 118 */ 119static void read_mem(uint8_t *dst, int src, int amount) 120{ 121 int remain = amount % 4; 122 uint32_t *d = (uint32_t *)dst; 123 uint32_t val; 124 int i; 125 126 rtl8029as_rbcr_wr(&rtl, amount); // Amount of bytes to transfer 127 rtl8029as_rsar_wr(&rtl, src); // Source in NIC mem 128 129 // Start read 130 rtl8029as_cr_t cr = rtl8029as_cr_default; 131 cr = rtl8029as_cr_sta_insert(cr, 1); 132 cr = rtl8029as_cr_rd_insert(cr, rtl8029as_rrd); 133 rtl8029as_cr_wr(&rtl, cr); 134 135 // Read PIO 32-bit 136 for(i = 0; i < amount - remain; i += 4, d++) { 137 *d = rtl8029as_rdma32_rd(&rtl); 138 } 139 140 // Read remaining bytes 141 for(; i < amount; i++) { 142 val = rtl8029as_rdma8_rd(&rtl); 143 if (dst != NULL) { 144 dst[i] = val; 145 } 146 } 147 148 // Stop read 149 cr = rtl8029as_cr_rd_insert(cr, rtl8029as_acrdma); 150 rtl8029as_cr_wr(&rtl, cr); 151} 152 153/** 154 * \brief Write packet to memory at a particular page. 155 * 156 * \param page Destination start page in ASIC memory. 157 * \param buffers Descriptors for buffer chain 158 * \param count Number of buffers in chain 159 * \param pkt_len Length of packet to be sent next. 160 */ 161static inline void write_page(uint8_t page, struct driver_buffer *buffers, 162 size_t count, uint64_t pkt_len) 163{ 164 uint64_t pbuf_len = 0; 165 uint16_t dst = page_to_mem(page); 166 167 RTL8029_DEBUG("write page\n"); 168 rtl8029as_rbcr_wr(&rtl, pkt_len);// Number of bytes to transfer 169 rtl8029as_rsar_wr(&rtl, dst); // Destination in NIC mem 170 171 // Start write 172 rtl8029as_cr_t cr = rtl8029as_cr_default; 173 cr = rtl8029as_cr_sta_insert(cr, 1); 174 cr = rtl8029as_cr_rd_insert(cr, rtl8029as_rwr); 175 rtl8029as_cr_wr(&rtl, cr); 176 177 for (int idx = 0; idx < count; idx++) { 178 uint8_t *src = buffers[idx].va; 179 pbuf_len = buffers[idx].len; 180 181 uint32_t i = 0; 182 183 // write bytes until we reach word alignment in the card's memory 184 for (i = 0; dst % sizeof(uint32_t) != 0; i++, dst++) { 185 // RTL8029_DEBUG("sending byte %d\n", i); 186 rtl8029as_rdma8_wr(&rtl, src[i]); 187 } 188 // RTL8029_DEBUG("sending %d %u for len %lu\n", i, dst, pbuf_len); 189 // write 32-bit words until we don't have any whole words left 190 for (; pbuf_len - i > sizeof(uint32_t); 191 i += sizeof(uint32_t), dst += sizeof(uint32_t)) { 192 // RTL8029_DEBUG("sending word %d %u loc %p, data%u\n", 193 // i, dst, &src[i], src[i]); 194 // RTL8029_DEBUG("base is 0x%x\n", rtl.base); 195 rtl8029as_rdma32_wr(&rtl, *(uint32_t*)&src[i]); 196 } 197 // RTL8029_DEBUG("done with loop 1\n"); 198 // Write remaining bytes 199 for(; i < pbuf_len; i++, dst++) { 200 rtl8029as_rdma8_wr(&rtl, src[i]); 201 } 202 } // end for : for each pbuf in the list (for single packet) 203 204 // RTL8029_DEBUG("stopping the write\n"); 205 206 // Stop write 207 cr = rtl8029as_cr_rd_insert(cr, rtl8029as_acrdma); 208 rtl8029as_cr_wr(&rtl, cr); 209 //RTL8029_DEBUG("finished writing page!\n"); 210} 211 212/** 213 * \brief Same as read_mem(), but with page granularity. 214 * 215 * \param dst Pointer to buffer to copy data to. 216 * \param src Source start page in ASIC memory. 217 * \param amount Number of bytes to transfer. 218 */ 219static inline void read_page(uint8_t *dst, uint8_t page, int amount) 220{ 221 read_mem(dst, page_to_mem(page), amount); 222} 223 224/** 225 * \brief Reset RTL8029(AS). 226 */ 227static inline void rtl8029_reset(void) 228{ 229 rtl8029as_reset_rd(&rtl); 230} 231 232 233// FIXME: This is just a placeholder function. Should be removed 234static uint64_t rtl_tx_slots_count_fn(void) 235{ 236 return 1000; // RTL_TX_RING_SIZE; 237} 238 239/** 240 * \brief Send Ethernet packet. 241 * 242 * The packet should be a complete Ethernet frame. Nothing is added 243 * by the card or the driver. 244 * 245 */ 246static errval_t rtl8029_send_ethernet_packet_fn(struct driver_buffer *buffers, 247 size_t count) 248{ 249 // Find the length of entire packet 250 uint64_t pkt_len = 0; 251 for (int idx = 0; idx < count; idx++) { 252 pkt_len += buffers[idx].len; 253 } 254 255 // RTL8029_DEBUG("sending ethernet packet\n"); 256 assert(pkt_len <= WRITE_BUF_SIZE); 257 258 // Write packet to ASIC memory 259 write_page(WRITE_PAGE, buffers, count, pkt_len); 260 // RTL8029_DEBUG("page written\n"); 261 262 // Set address & size 263 rtl8029as_tpsr_wr(&rtl, WRITE_PAGE); 264 rtl8029as_tbcr_wr(&rtl, pkt_len); 265 // RTL8029_DEBUG("address set\n"); 266 267 268 // Initiate send 269 rtl8029as_cr_t cr = rtl8029as_cr_default; 270 cr = rtl8029as_cr_sta_insert(cr, 1); 271 cr = rtl8029as_cr_txp_insert(cr, 1); 272 cr = rtl8029as_cr_rd_insert(cr, rtl8029as_sp); 273 rtl8029as_cr_wr(&rtl, cr); 274 275 // Wait until done... 276 while(rtl8029as_tsr_ptx_rdf(&rtl) == 0); 277 278 // Tell the client we sent them!!! 279 for (int idx = 0; idx < count; idx++) { 280 handle_tx_done(buffers[idx].opaque); 281 } 282 283 return SYS_ERR_OK; 284} 285 286 287static void read_ring_buffer(uint8_t *dst, int src, int amount) 288{ 289 int stopaddr = READ_STOP_PAGE << 8; 290 291 if(src + amount < stopaddr) { 292 // No ring-buffer wrap-around 293 read_mem(dst, src, amount); 294 } else { 295 int size = stopaddr - src; 296 297 // Read everything up to end of buffer 298 read_mem(dst, src, size); 299 // Read rest from (wrapped-around) start of buffer 300 if (dst != NULL) { 301 dst += size; 302 } 303 read_mem(dst, page_to_mem(READ_START_PAGE), amount - size); 304 } 305} 306 307/** 308 * \brief Receive Ethernet packet. 309 * 310 * Reads latest new packet from ASIC packet ring-buffer and calls 311 * higher-level receive function to process packet now in main 312 * memory. 313 * 314 * Assumes card is at register page 0. 315 */ 316static void rtl8029_receive_packet(void) 317{ 318 struct { 319 rtl8029as_rsr_t rsr; 320 uint8_t next_page; 321 uint16_t length; 322 } __attribute__ ((packed)) status; 323 324 // Read packet status (first 4 bytes before Ethernet header) 325 read_page((uint8_t *)&status, curr_page, sizeof(status)); 326 327 assert(rtl8029as_rsr_prx_extract(status.rsr) == 1); 328 assert(status.length <= PACKET_SIZE); 329 int pos = curr_page + ((status.length + 4 + 255) >> 8); 330 assert(status.next_page == (pos >= READ_STOP_PAGE ? pos - 331 (READ_BUF_SIZE >> 8) : pos)); 332 333 // Read packet 334 packet_length = status.length - sizeof(status); 335 // FIXME: Can we skip reading from the ring buffer if packetbuf == NULL? Or 336 // does the card require us to read the data to continue working properly? 337 // At the moment I chose the safe path and read the data. 338 read_ring_buffer(packetbuf, page_to_mem(curr_page) + sizeof(status), 339 packet_length); 340 341 RTL8029_DEBUG("................... Packet received (length = %d)\n", 342 status.length); 343 344 // Update boundary 345 curr_page = status.next_page; 346 rtl8029as_bnry_wr(&rtl, curr_page); 347} 348 349/** 350 * \brief rtl8029as IRQ handler 351 * 352 * This handler assumes the card is at page 0. 353 * 354 * The order of actions in this function is important. An interrupt 355 * needs to be acknowledged to the card first, before reading packets 356 * from the card. Otherwise a race between reading packets and newly 357 * received packets arises and packet reception can be delayed 358 * arbitrarily. 359 */ 360static void rtl8029_handle_interrupt(void *arg) 361{ 362// thread_mutex_lock(&driver_lock); 363 364 rtl8029as_irq_t isr = rtl8029as_isr_rd(&rtl); 365 RTL8029_DEBUG("interrupt came in.\n"); 366 // 1. Acknowledge all interrupt causes 367 /* rtl8029as_irq_t nisr = { 368 .prx = 1, 369 .ptx = 1, 370 .rxe = 1, 371 .txe = 1, 372 .ovw = 1, 373 .cnt = 1, 374 .rdc = 1, 375 .rst = 1 376 }; */ 377 rtl8029as_isr_wr(&rtl, 0xff); 378 379 // 2. Get card's current packet pointer 380 uint8_t curr = rtl8029as_curr_rd(&rtl); 381 382 // 3. Process current interrupt causes 383 if(rtl8029as_irq_prx_extract(isr)) { 384 // Read as many packets as possible 385 while(curr_page != curr) { 386 rtl8029_receive_packet(); 387 388 assert(packet_length <= 1522); 389 assert(packet_length > 0); 390 391 if (packetbuf != NULL) { 392 struct driver_rx_buffer buf = { .opaque = packetbuf_opaque, 393 .len = packet_length }; 394 packetbuf = NULL; 395 process_received_packet(&buf, 1, 0); 396 } 397 } 398 } 399 400// thread_mutex_unlock(&driver_lock); 401} 402 403 404/** 405 * \brief Initialize RTL8029(AS). 406 * 407 * \param net_card_address Pointer to card's PCI configuration. 408 * 409 * \return 0 on success. Failure code otherwise. 410 */ 411static int rtl8029_initialize_card(void) 412{ 413// thread_mutex_lock(&driver_lock); 414 printf("Initializing RTL8029(AS)...\n"); 415 416 uint32_t cbio = RTL8029_IOBASE; 417 uint16_t portbase = cbio & ~0x1; 418 rtl8029as_initialize(&rtl, portbase); 419 420 // Reset card 421 rtl8029as_reset_rd(&rtl); 422 423 // Identify rtl8029as 424 if( rtl8029as_chipid_rd(&rtl,0) == 'P' 425 && rtl8029as_chipid_rd(&rtl,1) == 'C') { 426 printf("rtl8029as identified\n"); 427 } else { 428 printf("This is not a recognized rtl8029as: ID is %02x:%02x!\n", 429 rtl8029as_chipid_rd(&rtl,0), 430 rtl8029as_chipid_rd(&rtl,1) ); 431 return -1; 432 } 433 printf("RTL base is %d\n",rtl.base); 434 435 // Read my MAC address 436 for(int i=0; i < 6; i++) { 437 rtl8029_mac[i] = rtl8029as_par_rd(&rtl,i); 438 } 439 printf("My MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", 440 rtl8029_mac[0], rtl8029_mac[1], rtl8029_mac[2], rtl8029_mac[3], 441 rtl8029_mac[4], rtl8029_mac[5]); 442 443 // Start the card 444 page_select(rtl8029as_ne2000p0); 445 rtl8029as_cr_t cr = rtl8029as_cr_rd(&rtl); 446 cr = rtl8029as_cr_stp_insert(cr, 0); 447 rtl8029as_cr_wr(&rtl, cr); 448 449 // Clear interrupt status register 450 rtl8029as_irq_t isr = 0xff; 451 /* Which implies: 452 .prx = 1, 453 .ptx = 1, 454 .rxe = 1, 455 .txe = 1, 456 .ovw = 1, 457 .cnt = 1, 458 .rdc = 1, 459 .rst = 1 460 */ 461 rtl8029as_isr_wr(&rtl, isr); 462 463 /* 464 // Register interrupt handler 465 uint64_t badge = idc_handler_register(rtl8029_handle_interrupt); 466 467 struct capref ep; 468 if (endpoint_create(badge, &ep) != SYS_ERR_OK) { 469 assert(!"endpoint_create failed"); 470 return -1; 471 } 472 if (irq_handle(cfit & 0xf, ep) != SYS_ERR_OK) { 473 assert(!"Registering IRQ failed"); 474 return -1; 475 } 476*/ 477 // Set byte-wide PIO transfer 478 rtl8029as_dcr_t dcr = rtl8029as_dcr_default; 479 dcr = rtl8029as_dcr_wts_insert(dcr,0); 480 rtl8029as_dcr_wr(&rtl, dcr); 481 482 // Setup on-card receive ring-buffer 483 rtl8029as_curr_wr( &rtl, READ_START_PAGE); 484 rtl8029as_pstart_wr(&rtl, READ_START_PAGE); 485 rtl8029as_pstop_wr( &rtl, READ_STOP_PAGE); 486 rtl8029as_bnry_wr( &rtl, READ_START_PAGE); 487 488 // Enable interrupts (IRQ handler assumes we're at page 0!) 489 rtl8029as_irq_t imr = rtl8029as_irq_default; 490 imr = rtl8029as_irq_prx_insert(imr,1); 491 /* .ptx = 1, */ 492 /* .rdc = 1 */ 493 rtl8029as_imr_wr(&rtl, imr); 494 495// thread_mutex_unlock(&driver_lock); 496 return 0; 497} 498 499static void get_mac_address_fn(uint8_t *mac) 500{ 501 memcpy(mac, rtl8029_mac, 6); 502} 503 504static bool handle_free_TX_slot_fn(void) 505{ 506 return false; 507} 508 509/** 510 * Callback for net_queue_mgr library. Since we do PIO anyways, we only ever use 511 * one buffer. 512 */ 513static uint64_t find_rx_free_slot_count_fn(void) 514{ 515 return (packetbuf == NULL); 516} 517 518/** Callback for net_queue_mgr library. */ 519static errval_t register_rx_buffer_fn(uint64_t paddr, void *vaddr, void *opaque) 520{ 521 if (packetbuf != NULL) { 522 return ETHERSRV_ERR_TOO_MANY_BUFFERS; 523 } 524 525 packetbuf = vaddr; 526 packetbuf_opaque = opaque; 527 return SYS_ERR_OK; 528} 529 530static void rtl8029_init(void) 531{ 532 /* FIXME: use correct name, and make apps and netd 533 * work with multiple service names for driver. */ 534 char *service_name = "rtl8029"; 535 RTL8029_DEBUG("starting hardware init\n"); 536 rtl8029_initialize_card(); 537 /* FIXME: do hardware init*/ 538 RTL8029_DEBUG("Done with hardware init\n"); 539 540 ethersrv_init(service_name, assumed_queue_id, get_mac_address_fn, NULL, 541 rtl8029_send_ethernet_packet_fn, 542 rtl_tx_slots_count_fn, handle_free_TX_slot_fn, 543 PACKET_SIZE, register_rx_buffer_fn, find_rx_free_slot_count_fn); 544} 545 546/** 547 * \brief Initialize rtl8029 driver as legacy driver. 548 * 549 * 550 */ 551static errval_t legacy_rtl8029_driver_init(void) 552{ 553 /* FIXME: pci_client_connect returns int and not errval_t. 554 * So, change the pci_client_connect() */ 555 errval_t err = pci_client_connect(); 556 if (err_is_fail(err)) { 557 return err; 558 } 559 RTL8029_DEBUG("connected to pci\n"); 560 561 return pci_register_legacy_driver_irq(rtl8029_init, RTL8029_IOBASE, 562 RTL8029_IOEND, RTL8029_IRQ, 563 rtl8029_handle_interrupt, NULL); 564} 565 566 567//this functions polls all the client's channels as well as the transmit and 568//receive descriptor rings 569static void polling_loop(void) 570{ 571 errval_t err; 572 struct waitset *ws = get_default_waitset(); 573 while (1) { 574 err = event_dispatch(ws); 575 if (err_is_fail(err)) { 576 DEBUG_ERR(err, "in event_dispatch"); 577 break; 578 } 579// RTL8029_DEBUG("inside event dispatch\n"); 580/* notify_client_next_free_tx(); 581*/ 582 } 583} 584 585 586int main(int argc, char *argv[]) 587{ 588 errval_t err; 589 int i; 590 RTL8029_DEBUG("Starting rtl8029 standalone driver.....\n"); 591 592 // Process commandline arguments 593 for (i = 1; i < argc; i++) { 594 ethersrv_argument(argv[i]); 595 } 596#ifdef CONFIG_QEMU_NETWORK 597 printf("Starting RTL8029 for QEMU\n"); 598#else // CONFIG_QEMU_NETWORK 599 printf("Starting RTL8029 for hardware\n"); 600#endif // CONFIG_QEMU_NETWORK 601 // Initialize driver 602 err = legacy_rtl8029_driver_init(); 603 if (err_is_fail(err)) { 604 USER_PANIC_ERR(err, "legacy_rtl8029_driver_init\n"); 605 } 606 RTL8029_DEBUG("registered driver\n"); 607 608 polling_loop(); //loop myself 609} 610 611