1 /*
2  * Copyright (c) 2013 Corey Tabaka
3  * Copyright (c) 2015 Travis Geiselbrecht
4  *
5  * Use of this source code is governed by a MIT-style
6  * license that can be found in the LICENSE file or at
7  * https://opensource.org/licenses/MIT
8  */
9 
10 #include <lk/reg.h>
11 #include <lk/err.h>
12 #include <pcnet.h>
13 #include <lk/debug.h>
14 #include <lk/trace.h>
15 #include <assert.h>
16 #include <arch/x86.h>
17 #include <platform/pc.h>
18 #include <platform/pcnet.h>
19 #include <platform/interrupts.h>
20 #include <kernel/thread.h>
21 #include <kernel/mutex.h>
22 #include <kernel/event.h>
23 #include <dev/class/netif.h>
24 #include <dev/bus/pci.h>
25 #include <stdlib.h>
26 #include <malloc.h>
27 #include <string.h>
28 #include <lwip/pbuf.h>
29 #include <lk/init.h>
30 
31 #define LOCAL_TRACE 0
32 
33 #define PCNET_INIT_TIMEOUT 20000
34 #define MAX_PACKET_SIZE 1518
35 
36 #define QEMU_IRQ_BUG_WORKAROUND 1
37 
38 struct pcnet_state {
39     int irq;
40     addr_t base;
41 
42     uint8_t padr[6];
43 
44     struct init_block_32 *ib;
45 
46     struct rd_style3 *rd;
47     struct td_style3 *td;
48 
49     struct pbuf **rx_buffers;
50     struct pbuf **tx_buffers;
51 
52     /* queue accounting */
53     int rd_head;
54     int td_head;
55     int td_tail;
56 
57     int rd_count;
58     int td_count;
59 
60     int tx_pending;
61 
62     mutex_t tx_lock;
63 
64     /* bottom half state */
65     event_t event;
66     event_t initialized;
67     bool done;
68 
69     struct netstack_state *netstack_state;
70 };
71 
72 static status_t pcnet_init(struct device *dev);
73 static status_t pcnet_read_pci_config(struct device *dev, pci_location_t loc);
74 
75 static enum handler_return pcnet_irq_handler(void *arg);
76 
77 static int pcnet_thread(void *arg);
78 static bool pcnet_service_tx(struct device *dev);
79 static bool pcnet_service_rx(struct device *dev);
80 
81 static status_t pcnet_set_state(struct device *dev, struct netstack_state *state);
82 static ssize_t pcnet_get_hwaddr(struct device *dev, void *buf, size_t max_len);
83 static ssize_t pcnet_get_mtu(struct device *dev);
84 
85 static status_t pcnet_output(struct device *dev, struct pbuf *p);
86 
87 static struct netif_ops pcnet_ops = {
88     .std = {
89         .init = pcnet_init,
90     },
91 
92     .set_state = pcnet_set_state,
93     .get_hwaddr = pcnet_get_hwaddr,
94     .get_mtu = pcnet_get_mtu,
95 
96     .output = pcnet_output,
97 };
98 
99 DRIVER_EXPORT(netif, &pcnet_ops.std);
100 
pcnet_read_csr(struct device * dev,uint8_t rap)101 static inline uint32_t pcnet_read_csr(struct device *dev, uint8_t rap) {
102     struct pcnet_state *state = dev->state;
103 
104     outpd(state->base + REG_RAP, rap);
105     return inpd(state->base + REG_RDP);
106 }
107 
pcnet_write_csr(struct device * dev,uint8_t rap,uint16_t data)108 static inline void pcnet_write_csr(struct device *dev, uint8_t rap, uint16_t data) {
109     struct pcnet_state *state = dev->state;
110 
111     outpd(state->base + REG_RAP, rap);
112     outpd(state->base + REG_RDP, data);
113 }
114 
pcnet_read_bcr(struct device * dev,uint8_t rap)115 static inline uint32_t pcnet_read_bcr(struct device *dev, uint8_t rap) {
116     struct pcnet_state *state = dev->state;
117 
118     outpd(state->base + REG_RAP, rap);
119     return inpd(state->base + REG_BDP);
120 }
121 
pcnet_write_bcr(struct device * dev,uint8_t rap,uint16_t data)122 static inline void pcnet_write_bcr(struct device *dev, uint8_t rap, uint16_t data) {
123     struct pcnet_state *state = dev->state;
124 
125     outpd(state->base + REG_RAP, rap);
126     outpd(state->base + REG_BDP, data);
127 }
128 
pcnet_init(struct device * dev)129 static status_t pcnet_init(struct device *dev) {
130     status_t res = NO_ERROR;
131     pci_location_t loc;
132     int i;
133 
134     const struct platform_pcnet_config *config = dev->config;
135 
136     if (!config)
137         return ERR_NOT_CONFIGURED;
138 
139     if (pci_bus_mgr_find_device(&loc, config->device_id, config->vendor_id, config->index) != _PCI_SUCCESSFUL) {
140         TRACEF("device not found\n");
141         return ERR_NOT_FOUND;
142     }
143 
144     struct pcnet_state *state = calloc(1, sizeof(struct pcnet_state));
145     if (!state)
146         return ERR_NO_MEMORY;
147 
148     dev->state = state;
149 
150     res = pcnet_read_pci_config(dev, loc);
151     if (res)
152         goto error;
153 
154     for (i=0; i < 6; i++)
155         state->padr[i] = inp(state->base + i);
156 
157     LTRACEF("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", state->padr[0], state->padr[1], state->padr[2],
158             state->padr[3], state->padr[4], state->padr[5]);
159 
160     /* put the controller into 32bit wide mode by performing a 32bit write to CSR0 */
161     outpd(state->base + 0, 0);
162 
163     /* stop the controller for configuration */
164     pcnet_write_csr(dev, 0, CSR0_STOP);
165 
166     /* setup 32bit (style 3) structures, burst, all CSR4 bits valid, TDM1[29] is ADD_FCS */
167     pcnet_write_csr(dev, 58, 3);
168 
169     /* DMA plus enable */
170     pcnet_write_csr(dev, 4, pcnet_read_csr(dev, 4) | CSR4_DMAPLUS);
171 
172     /* allocate 128 tx and 128 rx descriptor rings */
173     state->td_count = 128;
174     state->rd_count = 128;
175     state->td = memalign(16, state->td_count * DESC_SIZE);
176     state->rd = memalign(16, state->rd_count * DESC_SIZE);
177 
178     state->rx_buffers = calloc(state->rd_count, sizeof(struct pbuf *));
179     state->tx_buffers = calloc(state->td_count, sizeof(struct pbuf *));
180 
181     state->tx_pending = 0;
182 
183     if (!state->td || !state->rd || !state->tx_buffers || !state->rx_buffers) {
184         res = ERR_NO_MEMORY;
185         goto error;
186     }
187 
188     memset(state->td, 0, state->td_count * DESC_SIZE);
189     memset(state->rd, 0, state->rd_count * DESC_SIZE);
190 
191     /* allocate temporary init block space */
192     state->ib = memalign(4, sizeof(struct init_block_32));
193     if (!state->ib) {
194         res = ERR_NO_MEMORY;
195         goto error;
196     }
197 
198     LTRACEF("Init block addr: %p\n", state->ib);
199 
200     /* setup init block */
201     state->ib->tlen = 7; // 128 descriptors
202     state->ib->rlen = 7; // 128 descriptors
203     state->ib->mode = 0;
204 
205     state->ib->ladr = ~0;
206     state->ib->tdra = (uint32_t) state->td;
207     state->ib->rdra = (uint32_t) state->rd;
208 
209     memcpy(state->ib->padr, state->padr, 6);
210 
211     /* load the init block address */
212     pcnet_write_csr(dev, 1, (uint32_t) state->ib);
213     pcnet_write_csr(dev, 2, (uint32_t) state->ib >> 16);
214 
215     /* setup receive descriptors */
216     for (i=0; i < state->rd_count; i++) {
217         //LTRACEF("Allocating pbuf %d\n", i);
218         struct pbuf *p = pbuf_alloc(PBUF_RAW, MAX_PACKET_SIZE, PBUF_RAM);
219 
220         state->rd[i].rbadr = (uint32_t) p->payload;
221         state->rd[i].bcnt = -p->tot_len;
222         state->rd[i].ones = 0xf;
223         state->rd[i].own = 1;
224 
225         state->rx_buffers[i] = p;
226     }
227 
228     mutex_init(&state->tx_lock);
229 
230     state->done = false;
231     event_init(&state->event, false, EVENT_FLAG_AUTOUNSIGNAL);
232     event_init(&state->initialized, false, 0);
233 
234     /* start up a thread to process packet activity */
235     thread_resume(thread_create("[pcnet bh]", pcnet_thread, dev, DEFAULT_PRIORITY,
236                                 DEFAULT_STACK_SIZE));
237 
238     register_int_handler(state->irq, pcnet_irq_handler, dev);
239     unmask_interrupt(state->irq);
240 
241 #if QEMU_IRQ_BUG_WORKAROUND
242     register_int_handler(INT_BASE + 15, pcnet_irq_handler, dev);
243     unmask_interrupt(INT_BASE + 15);
244 #endif
245 
246     /* wait for initialization to complete */
247     res = event_wait_timeout(&state->initialized, PCNET_INIT_TIMEOUT);
248     if (res) {
249         /* TODO: cancel bottom half thread and tear down device instance */
250         LTRACEF("Failed to wait for IDON: %d\n", res);
251         return res;
252     }
253 
254     LTRACE_EXIT;
255     return res;
256 
257 error:
258     LTRACEF("Error: %d\n", res);
259 
260     if (state) {
261         free(state->td);
262         free(state->rd);
263         free(state->ib);
264         free(state->tx_buffers);
265         free(state->rx_buffers);
266     }
267 
268     free(state);
269 
270     return res;
271 }
272 
pcnet_read_pci_config(struct device * dev,pci_location_t loc)273 static status_t pcnet_read_pci_config(struct device *dev, pci_location_t loc) {
274     status_t res = NO_ERROR;
275     pci_config_t config;
276     unsigned i;
277 
278     DEBUG_ASSERT(dev->state);
279 
280     struct pcnet_state *state = dev->state;
281 
282     pci_read_config(loc, &config);
283 
284     LTRACEF("Resources:\n");
285 
286     for (i=0; i < countof(config.type0.base_addresses); i++) {
287         if (config.type0.base_addresses[i] & 0x1) {
288             LTRACEF("  BAR %d  I/O REG: %04x\n", i, config.type0.base_addresses[i] & ~0x3);
289 
290             state->base = config.type0.base_addresses[i] & ~0x3;
291             break;
292         }
293     }
294 
295     if (!state->base) {
296         res = ERR_NOT_CONFIGURED;
297         goto error;
298     }
299 
300     if (config.type0.interrupt_line != 0xff) {
301         LTRACEF("  IRQ %u\n", config.type0.interrupt_line);
302 
303         state->irq = config.type0.interrupt_line + INT_BASE;
304     } else {
305         res = ERR_NOT_CONFIGURED;
306         goto error;
307     }
308 
309     LTRACEF("Command: %04x\n", config.command);
310     LTRACEF("Status:  %04x\n", config.status);
311 
312     pci_write_config_half(loc, PCI_CONFIG_COMMAND,
313                           (config.command | PCI_COMMAND_IO_EN | PCI_COMMAND_BUS_MASTER_EN) & ~PCI_COMMAND_MEM_EN);
314 
315 error:
316     return res;
317 }
318 
pcnet_irq_handler(void * arg)319 static enum handler_return pcnet_irq_handler(void *arg) {
320     struct device *dev = arg;
321     struct pcnet_state *state = dev->state;
322 
323     mask_interrupt(state->irq);
324 
325 #if QEMU_IRQ_BUG_WORKAROUND
326     mask_interrupt(INT_BASE + 15);
327 #endif
328 
329     event_signal(&state->event, false);
330 
331     return INT_RESCHEDULE;
332 }
333 
pcnet_thread(void * arg)334 static int pcnet_thread(void *arg) {
335     DEBUG_ASSERT(arg);
336 
337     struct device *dev = arg;
338     struct pcnet_state *state = dev->state;
339 
340     /* kick off init, enable ints, and start operation */
341     pcnet_write_csr(dev, 0, CSR0_INIT | CSR0_IENA | CSR0_STRT);
342 
343     while (!state->done) {
344         LTRACEF("Waiting for event.\n");
345         //event_wait_timeout(&state->event, 5000);
346         event_wait(&state->event);
347 
348         int csr0 = pcnet_read_csr(dev, 0);
349 
350         /* disable interrupts at the controller */
351         pcnet_write_csr(dev, 0, csr0 & ~CSR0_IENA);
352 
353         LTRACEF("CSR0 = %04x\n", csr0);
354 
355 #if LOCAL_TRACE
356         if (csr0 & CSR0_RINT) TRACEF("RINT\n");
357         if (csr0 & CSR0_TINT) TRACEF("TINT\n");
358 #endif
359 
360         if (csr0 & CSR0_IDON) {
361             LTRACEF("IDON\n");
362 
363             /* free the init block that we no longer need */
364             free(state->ib);
365             state->ib = NULL;
366 
367             event_signal(&state->initialized, true);
368         }
369 
370         if (csr0 & CSR0_ERR) {
371             LTRACEF("ERR\n");
372 
373             /* TODO: handle errors, though not many need it */
374 
375             /* clear flags, preserve necessary enables */
376             pcnet_write_csr(dev, 0, csr0 & (CSR0_TXON | CSR0_RXON | CSR0_IENA));
377         }
378 
379         bool again = !!(csr0 & (CSR0_RINT | CSR0_TINT));
380         while (again) {
381             again = pcnet_service_tx(dev) | pcnet_service_rx(dev);
382         }
383 
384         /* enable interrupts at the controller */
385         pcnet_write_csr(dev, 0, CSR0_IENA);
386         unmask_interrupt(state->irq);
387 
388 #if QEMU_IRQ_BUG_WORKAROUND
389         unmask_interrupt(INT_BASE + 15);
390 #endif
391     }
392 
393     return 0;
394 }
395 
pcnet_service_tx(struct device * dev)396 static bool pcnet_service_tx(struct device *dev) {
397     LTRACE_ENTRY;
398 
399     struct pcnet_state *state = dev->state;
400 
401     mutex_acquire(&state->tx_lock);
402 
403     struct td_style3 *td = &state->td[state->td_tail];
404 
405     if (state->tx_pending && td->own == 0) {
406         struct pbuf *p = state->tx_buffers[state->td_tail];
407         DEBUG_ASSERT(p);
408 
409         state->tx_buffers[state->td_tail] = NULL;
410 
411         LTRACEF("Retiring packet: td_tail=%d p=%p tot_len=%u\n", state->td_tail, p, p->tot_len);
412 
413         state->tx_pending--;
414         state->td_tail = (state->td_tail + 1) % state->td_count;
415 
416         if (td->err) {
417             LTRACEF("Descriptor error status encountered\n");
418             hexdump8(td, sizeof(*td));
419         }
420 
421         mutex_release(&state->tx_lock);
422 
423         pbuf_free(p);
424 
425         LTRACE_EXIT;
426         return true;
427     } else {
428         mutex_release(&state->tx_lock);
429 
430 #if 0
431         LTRACEF("Nothing to do for TX.\n");
432         for (int i=0; i < state->td_count; i++)
433             printf("%d ", state->td[i].own);
434         printf("\n");
435 #endif
436 
437         LTRACE_EXIT;
438         return false;
439     }
440 }
441 
pcnet_service_rx(struct device * dev)442 static bool pcnet_service_rx(struct device *dev) {
443     LTRACE_ENTRY;
444 
445     struct pcnet_state *state = dev->state;
446 
447     struct rd_style3 *rd = &state->rd[state->rd_head];
448 
449     if (rd->own == 0) {
450         struct pbuf *p = state->rx_buffers[state->rd_head];
451         DEBUG_ASSERT(p);
452 
453         LTRACEF("Processing RX descriptor %d\n", state->rd_head);
454 
455         if (rd->err) {
456             LTRACEF("Descriptor error status encountered\n");
457             hexdump8(rd, sizeof(*rd));
458         } else {
459             if (rd->mcnt <= p->tot_len) {
460 
461                 pbuf_realloc(p, rd->mcnt);
462 
463 #if LOCAL_TRACE
464                 LTRACEF("payload=%p len=%u\n", p->payload, p->tot_len);
465                 hexdump8(p->payload, p->tot_len);
466 #endif
467 
468                 class_netstack_input(dev, state->netstack_state, p);
469 
470                 p = state->rx_buffers[state->rd_head] = pbuf_alloc(PBUF_RAW, MAX_PACKET_SIZE, PBUF_RAM);
471             } else {
472                 LTRACEF("RX packet size error: mcnt = %u, buf len = %u\n", rd->mcnt, p->tot_len);
473             }
474         }
475 
476         memset(rd, 0, sizeof(*rd));
477         memset(p->payload, 0, p->tot_len);
478 
479         rd->rbadr = (uint32_t) p->payload;
480         rd->bcnt = -p->tot_len;
481         rd->ones = 0xf;
482         rd->own = 1;
483 
484         state->rd_head = (state->rd_head + 1) % state->rd_count;
485 
486         LTRACE_EXIT;
487         return true;
488     } else {
489 #if 0
490         LTRACEF("Nothing to do for RX: rd_head=%d.\n", state->rd_head);
491         for (int i=0; i < state->rd_count; i++)
492             printf("%d ", state->rd[i].own);
493         printf("\n");
494 #endif
495     }
496 
497     LTRACE_EXIT;
498     return false;
499 }
500 
pcnet_set_state(struct device * dev,struct netstack_state * netstack_state)501 static status_t pcnet_set_state(struct device *dev, struct netstack_state *netstack_state) {
502     if (!dev)
503         return ERR_INVALID_ARGS;
504 
505     if (!dev->state)
506         return ERR_NOT_CONFIGURED;
507 
508     struct pcnet_state *state = dev->state;
509 
510     state->netstack_state = netstack_state;
511 
512     return NO_ERROR;
513 }
514 
pcnet_get_hwaddr(struct device * dev,void * buf,size_t max_len)515 static ssize_t pcnet_get_hwaddr(struct device *dev, void *buf, size_t max_len) {
516     if (!dev || !buf)
517         return ERR_INVALID_ARGS;
518 
519     if (!dev->state)
520         return ERR_NOT_CONFIGURED;
521 
522     struct pcnet_state *state = dev->state;
523 
524     memcpy(buf, state->padr, MIN(sizeof(state->padr), max_len));
525 
526     return sizeof(state->padr);
527 }
528 
pcnet_get_mtu(struct device * dev)529 static ssize_t pcnet_get_mtu(struct device *dev) {
530     if (!dev)
531         return ERR_INVALID_ARGS;
532 
533     return 1500;
534 }
535 
pcnet_output(struct device * dev,struct pbuf * p)536 static status_t pcnet_output(struct device *dev, struct pbuf *p) {
537     LTRACE_ENTRY;
538 
539     if (!dev || !p)
540         return ERR_INVALID_ARGS;
541 
542     if (!dev->state)
543         return ERR_NOT_CONFIGURED;
544 
545     status_t res = NO_ERROR;
546     struct pcnet_state *state = dev->state;
547 
548     mutex_acquire(&state->tx_lock);
549 
550     struct td_style3 *td = &state->td[state->td_head];
551 
552     if (td->own) {
553         LTRACEF("TX descriptor ring full\n");
554         res = ERR_NOT_READY; // maybe this should be ERR_NOT_ENOUGH_BUFFER?
555         goto done;
556     }
557 
558     pbuf_ref(p);
559     p = pbuf_coalesce(p, PBUF_RAW);
560 
561 #if LOCAL_TRACE
562     LTRACEF("Queuing packet: td_head=%d p=%p tot_len=%u\n", state->td_head, p, p->tot_len);
563     hexdump8(p->payload, p->tot_len);
564 #endif
565 
566     /* clear flags */
567     memset(td, 0, sizeof(*td));
568 
569     td->tbadr = (uint32_t) p->payload;
570     td->bcnt = -p->tot_len;
571     td->stp = 1;
572     td->enp = 1;
573     td->add_no_fcs = 1;
574     td->ones = 0xf;
575 
576     state->tx_buffers[state->td_head] = p;
577     state->tx_pending++;
578 
579     state->td_head = (state->td_head + 1) % state->td_count;
580 
581     td->own = 1;
582 
583     /* trigger tx */
584     pcnet_write_csr(dev, 0, CSR0_TDMD);
585 
586 done:
587     mutex_release(&state->tx_lock);
588     LTRACE_EXIT;
589     return res;
590 }
591 
592 static const struct platform_pcnet_config pcnet0_config = {
593     .vendor_id = 0x1022,
594     .device_id = 0x2000,
595     .index = 0,
596 };
597 
598 DEVICE_INSTANCE(netif, pcnet0, &pcnet0_config, 0);
599 
pcnet_init_hook(uint level)600 static void pcnet_init_hook(uint level) {
601     status_t err = device_init(device_get_by_name(netif, pcnet0));
602     if (err < 0)
603         return;
604 
605     class_netif_add(device_get_by_name(netif, pcnet0));
606 }
607 
608 LK_INIT_HOOK(pcnet, &pcnet_init_hook, LK_INIT_LEVEL_PLATFORM);
609 
610