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, Universitaetstrasse 6, 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