tools/llvm: Do not build with symbols
[minix3.git] / minix / net / lwip / driver.c
blobd5c69445e0628a05d4c977d24399f8d0c774fbae
1 /*
2 * This file implements handling of meesagges send by drivers
3 */
5 #include <stdio.h>
6 #include <stdlib.h>
8 #include <minix/ipc.h>
9 #include <minix/com.h>
10 #include <minix/sysutil.h>
11 #include <minix/safecopies.h>
12 #include <minix/netsock.h>
14 #include <sys/ioc_net.h>
15 #include <net/gen/in.h>
16 #include <net/gen/ip_io.h>
17 #include <net/gen/route.h>
18 #include <net/gen/ether.h>
19 #include <net/gen/eth_io.h>
21 #include <lwip/pbuf.h>
22 #include <lwip/netif.h>
23 #include <netif/etharp.h>
25 #include "proto.h"
26 #include "driver.h"
28 #if 0
29 #define debug_drv_print(str, ...) printf("LWIP %s:%d : " str "\n", \
30 __func__, __LINE__, ##__VA_ARGS__)
31 #else
32 #define debug_drv_print(...) debug_print(__VA_ARGS__)
33 #endif
35 #define RAW_BUF_SIZE (32 << 10)
37 static struct nic devices[MAX_DEVS];
39 static ip_addr_t ip_addr_none = { IPADDR_NONE };
40 extern endpoint_t lwip_ep;
42 void nic_assign_driver(const char * dev_type,
43 unsigned int dev_num,
44 const char * driver_name,
45 unsigned int instance,
46 int is_default)
48 struct nic * nic;
50 if (strcmp(dev_type, "eth") != 0) {
51 printf("LWIP : Cannot handle other than ethernet devices, "
52 "ignoring '%s%d'\n", dev_type, dev_num);
53 return;
56 nic = &devices[dev_num];
57 snprintf(nic->name, NIC_NAME_LEN, "%s%d", dev_type, dev_num);
58 nic->name[NIC_NAME_LEN - 1] = '\0';
59 snprintf(nic->drv_name, DRV_NAME_LEN, "%s_%d", driver_name, instance);
60 nic->drv_name[DRV_NAME_LEN - 1] = '\0';
61 nic->is_default = is_default;
62 nic->netif.name[0] = 'e';
63 nic->netif.name[1] = 't';
64 nic->netif.num = dev_num;
66 debug_print("/dev/%s driven by %s default = %d",
67 nic->name, nic->drv_name, is_default);
70 static struct nic * lookup_nic_by_drv_ep(endpoint_t ep)
72 int i;
74 for (i = 0; i < MAX_DEVS; i++) {
75 if (devices[i].drv_ep == ep)
76 return &devices[i];
79 return NULL;
82 static struct nic * lookup_nic_by_drv_name(const char * name)
84 int i;
86 for (i = 0; i < MAX_DEVS; i++) {
87 if (strcmp(devices[i].drv_name, name) == 0)
88 return &devices[i];
91 return NULL;
94 static struct nic * lookup_nic_default(void)
96 int i;
98 for (i = 0; i < MAX_DEVS; i++) {
99 if (devices[i].is_default)
100 return &devices[i];
103 return NULL;
106 void nic_init_all(void)
108 int i;
109 unsigned int g;
111 for (i = 0; i < MAX_DEVS; i++) {
112 devices[i].drv_ep = NONE;
113 devices[i].is_default = 0;
115 if (cpf_getgrants(&devices[i].rx_iogrant, 1) != 1)
116 panic("Cannot initialize grants");
117 if (cpf_getgrants(&devices[i].rx_iovec[0].iov_grant, 1) != 1)
118 panic("Cannot initialize grants");
119 if (cpf_getgrants(&devices[i].tx_iogrant, 1) != 1)
120 panic("Cannot initialize grants");
121 for (g = 0; g < TX_IOVEC_NUM; g++) {
122 cp_grant_id_t * gid = &devices[i].tx_iovec[g].iov_grant;
123 if (cpf_getgrants(gid, 1) != 1)
124 panic("Cannot initialize grants");
126 devices[i].raw_socket = NULL;
130 static void driver_setup_read(struct nic * nic)
132 message m;
134 debug_print("device /dev/%s", nic->name);
135 //assert(nic->rx_pbuf == NULL);
136 if (!(nic->rx_pbuf == NULL)) {
137 panic("device /dev/%s rx_pbuf %p", nic->name, nic->rx_pbuf);
140 if (!(nic->rx_pbuf = pbuf_alloc(PBUF_RAW, ETH_MAX_PACK_SIZE + ETH_CRC_SIZE, PBUF_RAM)))
141 panic("Cannot allocate rx pbuf");
143 if (cpf_setgrant_direct(nic->rx_iovec[0].iov_grant,
144 nic->drv_ep, (vir_bytes) nic->rx_pbuf->payload,
145 nic->rx_pbuf->len, CPF_WRITE) != OK)
146 panic("Failed to set grant");
147 nic->rx_iovec[0].iov_size = nic->rx_pbuf->len;
149 m.m_type = DL_READV_S;
150 m.m_net_netdrv_dl_readv_s.count = 1;
151 m.m_net_netdrv_dl_readv_s.grant = nic->rx_iogrant;
153 if (asynsend(nic->drv_ep, &m) != OK)
154 panic("asynsend to the driver failed!");
157 static void nic_up(struct nic * nic, message * m)
159 memcpy(nic->netif.hwaddr, m->m_netdrv_net_dl_conf.hw_addr,
160 sizeof(nic->netif.hwaddr));
162 debug_print("device %s is up MAC : %02x:%02x:%02x:%02x:%02x:%02x",
163 nic->name,
164 nic->netif.hwaddr[0],
165 nic->netif.hwaddr[1],
166 nic->netif.hwaddr[2],
167 nic->netif.hwaddr[3],
168 nic->netif.hwaddr[4],
169 nic->netif.hwaddr[5]);
171 driver_setup_read(nic);
173 netif_set_link_up(&nic->netif);
174 netif_set_up(&nic->netif);
177 int driver_tx(struct nic * nic)
179 struct packet_q * pkt;
180 unsigned int len;
181 message m;
183 int err;
185 debug_print("device /dev/%s", nic->name);
186 assert(nic->tx_buffer);
188 pkt = driver_tx_head(nic);
189 if (pkt == NULL) {
190 debug_print("no packets enqueued");
191 return 0;
194 assert(pkt->buf_len <= nic->max_pkt_sz);
196 if ((len = pkt->buf_len) < nic->min_pkt_sz)
197 len = nic->min_pkt_sz;
198 err = cpf_setgrant_direct(nic->tx_iovec[0].iov_grant,
199 nic->drv_ep, (vir_bytes) pkt->buf,
200 len, CPF_READ);
201 debug_print("packet len %d", len);
202 if (err != OK)
203 panic("Failed to set grant");
204 nic->tx_iovec[0].iov_size = len;
206 if (cpf_setgrant_direct(nic->tx_iogrant, nic->drv_ep,
207 (vir_bytes) &nic->tx_iovec,
208 sizeof(iovec_s_t), CPF_READ) != OK)
209 panic("Failed to set grant");
211 m.m_type = DL_WRITEV_S;
212 m.m_net_netdrv_dl_writev_s.count = 1;
213 m.m_net_netdrv_dl_writev_s.grant = nic->tx_iogrant;
215 if (asynsend(nic->drv_ep, &m) != OK)
216 panic("asynsend to the driver failed!");
217 nic->state = DRV_SENDING;
219 debug_print("packet sent to driver");
221 return 1;
224 static void nic_pkt_sent(struct nic * nic)
226 debug_print("device /dev/%s", nic->name);
227 assert(nic->state != DRV_IDLE);
229 /* packet has been sent, we are not intereted anymore */
230 driver_tx_dequeue(nic);
232 * Try to transmit the next packet. Failure means that no packet is
233 * enqueued and thus the device is entering idle state
235 if (!driver_tx(nic))
236 nic->state = DRV_IDLE;
239 __unused static void print_pkt(unsigned char * pkt, int len)
241 int i = 0;
243 printf("--- PKT ---\n");
245 while (i < len) {
246 int x;
248 for (x = 0; x < 8 && i < len; x++, i++)
249 printf("%02x ", pkt[i]);
251 kputc(' ');
253 for (x = 0; x < 8 && i < len; x++, i++)
254 printf("%02x ", pkt[i]);
256 kputc('\n');
259 printf("--- PKT END ---\n");
262 static int raw_receive(struct sock_req *req,
263 struct pbuf *pbuf)
265 struct pbuf * p;
266 unsigned int rem_len = req->size;
267 unsigned int written = 0;
268 int err;
270 debug_print("user buffer size : %d\n", rem_len);
272 for (p = pbuf; p && rem_len; p = p->next) {
273 size_t cp_len;
275 cp_len = (rem_len < p->len) ? rem_len : p->len;
276 err = copy_to_user(req->endpt, p->payload, cp_len,
277 req->grant, written);
278 if (err != OK)
279 return err;
281 written += cp_len;
282 rem_len -= cp_len;
285 debug_print("copied %d bytes\n", written);
286 return written;
289 int raw_socket_input(struct pbuf * pbuf, struct nic * nic)
291 struct socket * sock;
292 struct pbuf * pbuf_new;
294 if ((sock = nic->raw_socket) == NULL)
295 return 0;
297 debug_print("socket num : %ld", get_sock_num(sock));
299 if (sock->flags & SOCK_FLG_OP_PENDING) {
300 int ret;
301 /* we are resuming a suspended operation */
302 ret = raw_receive(&sock->req, pbuf);
304 send_req_reply(&sock->req, ret);
305 sock->flags &= ~SOCK_FLG_OP_PENDING;
307 if (ret > 0)
308 return 0;
311 /* Do not enqueue more data than allowed */
312 if (sock->recv_data_size > RAW_BUF_SIZE) {
313 return 0;
317 * nobody is waiting for the data or an error occured above, we enqueue
318 * the packet. We store a copy of this packet
320 pbuf_new = pbuf_alloc(PBUF_RAW, pbuf->tot_len, PBUF_RAM);
321 if (pbuf_new == NULL) {
322 debug_print("LWIP : cannot allocated new pbuf\n");
323 return 0;
326 if (pbuf_copy(pbuf_new, pbuf) != ERR_OK) {
327 debug_print("LWIP : cannot copy pbuf\n");
328 return 0;
332 * If we didn't managed to enqueue the packet we report it as not
333 * consumed
335 if (sock_enqueue_data(sock, pbuf_new, pbuf_new->tot_len) != OK) {
336 pbuf_free(pbuf_new);
339 return 0;
342 static void nic_pkt_received(struct nic * nic, unsigned int size)
344 assert(nic->netif.input);
346 #if 0
347 print_pkt((unsigned char *) nic->rx_pbuf->payload, 64 /*nic->rx_pbuf->len */);
348 #endif
350 assert(nic->rx_pbuf->tot_len == nic->rx_pbuf->len);
351 nic->rx_pbuf->tot_len = nic->rx_pbuf->len = size - ETH_CRC_SIZE;
353 nic->netif.input(nic->rx_pbuf, &nic->netif);
354 nic->rx_pbuf = NULL;
355 driver_setup_read(nic);
358 void driver_request(message * m)
360 struct nic * nic;
362 if ((nic = lookup_nic_by_drv_ep(m->m_source)) == NULL) {
363 printf("LWIP : request from unknown driver %d\n", m->m_source);
364 return;
367 switch (m->m_type) {
368 case DL_CONF_REPLY:
369 if (m->m_netdrv_net_dl_conf.stat == OK)
370 nic_up(nic, m);
371 break;
372 case DL_TASK_REPLY:
374 if (!(m->m_netdrv_net_dl_task.flags & DL_PACK_SEND) &&
375 !(m->m_netdrv_net_dl_task.flags & DL_PACK_RECV)) {
376 printf("void reply from driver\n");
377 break;
380 if (m->m_netdrv_net_dl_task.flags & DL_PACK_SEND)
381 nic_pkt_sent(nic);
382 if (m->m_netdrv_net_dl_task.flags & DL_PACK_RECV)
383 nic_pkt_received(nic, m->m_netdrv_net_dl_task.count);
384 break;
385 case DL_STAT_REPLY:
386 break;
387 default:
388 printf("LWIP : unexpected request %d from driver %d\n",
389 m->m_type, m->m_source);
393 void driver_up(const char * label, endpoint_t ep)
395 struct nic * nic;
397 nic = lookup_nic_by_drv_name(label);
399 if (nic) {
400 debug_print("LWIP : driver '%s' / %d is up for /dev/%s\n",
401 label, ep, nic->name);
402 nic->drv_ep = ep;
403 } else {
404 printf("LWIP : WARNING unexpected driver '%s' up event\n",
405 label);
406 return;
409 nic->state = DRV_IDLE;
412 * FIXME
414 * We set the initial ip to 0.0.0.0 to make dhcpd broadcasing work
415 * at the very begining. dhcp should use raw socket but it is a little
416 * tricy in the current dhcp implementation
418 if (!netif_add(&nic->netif, (ip_addr_t *) __UNCONST( &ip_addr_any),
419 &ip_addr_none, &ip_addr_none, nic, ethernetif_init, ethernet_input)) {
420 printf("LWIP : failed to add device /dev/%s\n", nic->name);
421 nic->drv_ep = NONE;
423 if (nic->is_default)
424 netif_set_default(&nic->netif);
426 /* FIXME we support ethernet only, 2048 is safe */
427 nic->tx_buffer = debug_malloc(2048);
428 if (nic->tx_buffer == NULL)
429 panic("Cannot allocate tx_buffer");
430 /* When driver restarts, the rx_pbuf is likely ready to receive data
431 * from its previous instance. We free the buffer here, nobody depends
432 * on it. A new one is allocated when we send a new read request to the
433 * driver.
435 if (nic->rx_pbuf) {
436 pbuf_free(nic->rx_pbuf);
437 nic->rx_pbuf = NULL;
440 /* prepare the RX grant once and forever */
441 if (cpf_setgrant_direct(nic->rx_iogrant,
442 nic->drv_ep,
443 (vir_bytes) &nic->rx_iovec,
444 1 * sizeof(iovec_s_t), CPF_READ) != OK)
445 panic("Failed to set grant");
448 static void raw_recv_free(__unused void * data)
450 pbuf_free((struct pbuf *) data);
453 static int nic_op_close(struct socket * sock)
455 struct nic * nic = (struct nic *)sock->data;
457 debug_drv_print("socket %ld", get_sock_num(sock));
459 sock_dequeue_data_all(sock, raw_recv_free);
460 sock->ops = NULL;
462 if (nic->raw_socket == sock) {
463 nic->raw_socket = NULL;
464 debug_drv_print("no active raw sock at %s", nic->name);
467 return OK;
470 static int nic_ioctl_set_conf(__unused struct socket * sock,
471 struct nic * nic,
472 endpoint_t endpt,
473 cp_grant_id_t grant)
475 nwio_ipconf_t ipconf;
476 int err;
478 err = copy_from_user(endpt, &ipconf, sizeof(ipconf), grant, 0);
479 if (err != OK)
480 return err;
482 if (ipconf.nwic_flags & NWIC_IPADDR_SET)
483 netif_set_ipaddr(&nic->netif,
484 (ip_addr_t *)&ipconf.nwic_ipaddr);
485 if (ipconf.nwic_flags & NWIC_NETMASK_SET)
486 netif_set_netmask(&nic->netif,
487 (ip_addr_t *)&ipconf.nwic_netmask);
488 nic->flags = ipconf.nwic_flags;
489 if (nic->flags & NWEO_EN_BROAD)
490 nic->netif.flags |= NETIF_FLAG_BROADCAST;
493 return OK;
496 static int nic_ioctl_get_conf(__unused struct socket * sock,
497 struct nic * nic,
498 endpoint_t endpt,
499 cp_grant_id_t grant)
501 nwio_ipconf_t ipconf;
503 ipconf.nwic_flags = nic->flags;
504 ipconf.nwic_ipaddr = nic->netif.ip_addr.addr;
505 ipconf.nwic_netmask = nic->netif.netmask.addr;
506 ipconf.nwic_mtu = nic->netif.mtu;
508 return copy_to_user(endpt, &ipconf, sizeof(ipconf), grant, 0);
511 static int nic_ioctl_set_gateway(__unused struct socket * sock,
512 struct nic * nic,
513 endpoint_t endpt,
514 cp_grant_id_t grant)
516 nwio_route_t route;
517 int err;
519 err = copy_from_user(endpt, &route, sizeof(route), grant, 0);
520 if (err != OK)
521 return err;
523 netif_set_gw(&nic->netif, (ip_addr_t *)&route.nwr_gateway);
525 return OK;
528 static int nic_ioctl_get_ethstat(__unused struct socket * sock,
529 struct nic * nic,
530 endpoint_t endpt,
531 cp_grant_id_t grant)
533 nwio_ethstat_t ethstat;
535 debug_drv_print("device /dev/%s", nic->name);
537 * The device is not up yet, there is nothing to report or it is not
538 * an ethernet device
540 if (!nic->netif.flags & NETIF_FLAG_UP ||
541 !(nic->netif.flags & (NETIF_FLAG_ETHERNET |
542 NETIF_FLAG_ETHARP))) {
543 printf("LWIP no such device FUCK\n");
544 return ENODEV;
547 memset(&ethstat, 0, sizeof(ethstat));
548 memcpy(&ethstat.nwes_addr, nic->netif.hwaddr, 6);
550 return copy_to_user(endpt, &ethstat, sizeof(ethstat), grant, 0);
553 static int nic_ioctl_set_ethopt(struct socket * sock,
554 struct nic * nic,
555 endpoint_t endpt,
556 cp_grant_id_t grant)
558 int err;
559 nwio_ethopt_t ethopt;
561 assert(nic);
563 if (!sock)
564 return EINVAL;
566 debug_drv_print("device /dev/%s", nic->name);
568 * The device is not up yet, there is nothing to report or it is not
569 * an ethernet device
571 if (!nic->netif.flags & NETIF_FLAG_UP ||
572 !(nic->netif.flags & (NETIF_FLAG_ETHERNET |
573 NETIF_FLAG_ETHARP))) {
574 return ENODEV;
577 err = copy_from_user(endpt, &ethopt, sizeof(ethopt), grant, 0);
578 if (err != OK)
579 return err;
581 /* we want to get data from this sock */
582 if (ethopt.nweo_flags & NWEO_COPY) {
583 if (nic->raw_socket)
584 return EBUSY;
586 nic->raw_socket = sock;
587 debug_drv_print("active raw sock %ld at %s",
588 get_sock_num(sock), nic->name);
591 return OK;
594 static int nic_do_ioctl(struct socket * sock, struct nic * nic,
595 struct sock_req * req)
597 int r;
599 debug_print("device /dev/%s req %c %ld %ld",
600 nic->name,
601 (unsigned char) (req->req >> 8),
602 req->req & 0xff, _MINIX_IOCTL_SIZE(req->req));
604 debug_drv_print("socket %ld", sock ? get_sock_num(sock) : -1);
606 switch (req->req) {
607 case NWIOSIPCONF:
608 r = nic_ioctl_set_conf(sock, nic, req->endpt, req->grant);
609 break;
610 case NWIOGIPCONF:
611 r = nic_ioctl_get_conf(sock, nic, req->endpt, req->grant);
612 break;
613 case NWIOSIPOROUTE:
614 r = nic_ioctl_set_gateway(sock, nic, req->endpt, req->grant);
615 break;
616 case NWIOGETHSTAT:
617 r = nic_ioctl_get_ethstat(sock, nic, req->endpt, req->grant);
618 break;
619 case NWIOSETHOPT:
620 r = nic_ioctl_set_ethopt(sock, nic, req->endpt, req->grant);
621 break;
622 default:
623 r = ENOTTY;
626 return r;
629 int nic_default_ioctl(struct sock_req *req)
631 struct nic * nic = lookup_nic_default();
633 if (nic == NULL) {
634 debug_print("No default nic, reporting error");
635 return ENOTTY;
638 return nic_do_ioctl(NULL, nic, req);
641 static int nic_op_ioctl(struct socket * sock, struct sock_req * req,
642 __unused int blk)
644 return nic_do_ioctl(sock, (struct nic *)sock->data, req);
647 static int nic_op_read(struct socket * sock, struct sock_req * req, int blk)
649 debug_drv_print("sock num %ld", get_sock_num(sock));
651 if (sock->recv_head) {
652 /* data available receive immeditely */
654 struct pbuf * pbuf;
655 int ret;
657 pbuf = sock->recv_head->data;
659 ret = raw_receive(req, pbuf);
661 if (ret > 0) {
662 sock_dequeue_data(sock);
663 sock->recv_data_size -= pbuf->tot_len;
664 pbuf_free(pbuf);
666 return ret;
667 } else if (!blk)
668 return EAGAIN;
669 else {
670 /* store the request so we know how to reply */
671 sock->req = *req;
672 /* operation is being processes */
673 sock->flags |= SOCK_FLG_OP_PENDING;
675 debug_print("no data to read, suspending");
676 return EDONTREPLY;
680 static int nic_op_write(struct socket * sock, struct sock_req * req,
681 __unused int blk)
683 int ret;
684 struct pbuf * pbuf;
685 struct nic * nic = (struct nic *)sock->data;
687 assert(nic);
688 debug_print("device %s data size %u", nic->name, req->size);
690 pbuf = pbuf_alloc(PBUF_RAW, req->size, PBUF_RAM);
691 if (!pbuf)
692 return ENOMEM;
694 if ((ret = copy_from_user(req->endpt, pbuf->payload, req->size,
695 req->grant, 0)) != OK) {
696 pbuf_free(pbuf);
697 return ret;
700 if ((ret = nic->netif.linkoutput(&nic->netif, pbuf) != ERR_OK)) {
701 debug_print("raw linkoutput failed %d", ret);
702 ret = EIO;
703 } else
704 ret = req->size;
706 pbuf_free(pbuf);
708 return ret;
711 static struct sock_ops nic_ops = {
712 .write = nic_op_write,
713 .read = nic_op_read,
714 .close = nic_op_close,
715 .ioctl = nic_op_ioctl,
716 .select = generic_op_select,
717 .select_reply = generic_op_select_reply
720 int nic_open(devminor_t minor)
722 struct socket * sock;
724 debug_print("device %d", minor);
726 if (minor > MAX_DEVS || devices[minor].drv_ep == NONE)
727 return ENODEV;
729 sock = get_unused_sock();
731 if (sock == NULL)
732 return ENODEV;
733 if (sock->ops != NULL)
734 return EBUSY;
736 sock->ops = &nic_ops;
737 sock->select_ep = NONE;
738 sock->recv_data_size = 0;
739 sock->data = &devices[minor];
741 return get_sock_num(sock);
744 static int driver_pkt_enqueue(struct packet_q ** head,
745 struct packet_q ** tail,
746 struct pbuf * pbuf)
748 struct packet_q * pkt;
749 char * b;
751 pkt = (struct packet_q *) malloc(sizeof(struct packet_q) + pbuf->tot_len);
752 if (!pkt)
753 return ENOMEM;
755 pkt->next = NULL;
756 pkt->buf_len = pbuf->tot_len;
758 for (b = pkt->buf; pbuf; pbuf = pbuf->next) {
759 memcpy(b, pbuf->payload, pbuf->len);
760 b += pbuf->len;
763 if (*head == NULL)
764 *head = *tail = pkt;
765 else {
766 (*tail)->next = pkt;
767 *tail = pkt;
770 return OK;
773 int driver_tx_enqueue(struct nic * nic, struct pbuf * pbuf)
775 debug_print("device /dev/%s", nic->name);
776 return driver_pkt_enqueue(&nic->tx_head, &nic->tx_tail, pbuf);
779 static void driver_pkt_dequeue(struct packet_q ** head,
780 struct packet_q ** tail)
782 struct packet_q * pkt;
784 /* we always dequeue only if there is something to dequeue */
785 assert(*head);
787 pkt = *head;
789 if ((*head = pkt->next) == NULL)
790 *tail = NULL;
792 debug_free(pkt);
795 void driver_tx_dequeue(struct nic * nic)
797 debug_print("device /dev/%s", nic->name);
798 driver_pkt_dequeue(&nic->tx_head, &nic->tx_tail);
801 struct packet_q * driver_tx_head(struct nic * nic)
803 debug_print("device /dev/%s", nic->name);
805 if (!nic->tx_head)
806 return NULL;
807 return nic->tx_head;