1*69cf32a7Stsutsui /* $NetBSD: netif_of.c,v 1.5 2009/01/12 11:32:44 tsutsui Exp $ */
280675955Sthorpej
380675955Sthorpej /*
480675955Sthorpej * Copyright (C) 1995 Wolfgang Solfrank.
580675955Sthorpej * Copyright (C) 1995 TooLs GmbH.
680675955Sthorpej * All rights reserved.
780675955Sthorpej *
880675955Sthorpej * Redistribution and use in source and binary forms, with or without
980675955Sthorpej * modification, are permitted provided that the following conditions
1080675955Sthorpej * are met:
1180675955Sthorpej * 1. Redistributions of source code must retain the above copyright
1280675955Sthorpej * notice, this list of conditions and the following disclaimer.
1380675955Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
1480675955Sthorpej * notice, this list of conditions and the following disclaimer in the
1580675955Sthorpej * documentation and/or other materials provided with the distribution.
1680675955Sthorpej * 3. All advertising materials mentioning features or use of this software
1780675955Sthorpej * must display the following acknowledgement:
1880675955Sthorpej * This product includes software developed by TooLs GmbH.
1980675955Sthorpej * 4. The name of TooLs GmbH may not be used to endorse or promote products
2080675955Sthorpej * derived from this software without specific prior written permission.
2180675955Sthorpej *
2280675955Sthorpej * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2380675955Sthorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2480675955Sthorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2580675955Sthorpej * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2680675955Sthorpej * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2780675955Sthorpej * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2880675955Sthorpej * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2980675955Sthorpej * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3080675955Sthorpej * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3180675955Sthorpej * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3280675955Sthorpej */
3380675955Sthorpej
3480675955Sthorpej /*
3580675955Sthorpej * Open Firmware does most of the job for interfacing to the hardware,
3680675955Sthorpej * so it is easiest to just replace the netif module with
3780675955Sthorpej * this adaptation to the PROM network interface.
3880675955Sthorpej *
3980675955Sthorpej * Note: this is based in part on sys/arch/sparc/stand/netif_sun.c
4080675955Sthorpej */
4180675955Sthorpej
4280675955Sthorpej #include <sys/param.h>
4380675955Sthorpej #include <sys/socket.h>
4480675955Sthorpej
4580675955Sthorpej #include <net/if.h>
4680675955Sthorpej #include <net/if_ether.h>
4780675955Sthorpej
4880675955Sthorpej #include <netinet/in.h>
4980675955Sthorpej #include <netinet/in_systm.h>
5080675955Sthorpej
5180675955Sthorpej #include <lib/libsa/stand.h>
5280675955Sthorpej #include <lib/libsa/net.h>
5380675955Sthorpej
5480675955Sthorpej #include "ofdev.h"
5580675955Sthorpej #include "openfirm.h"
5680675955Sthorpej
5766a5580cSdrochner #include "netif_of.h"
5880675955Sthorpej
5966a5580cSdrochner static struct iodesc sdesc;
6080675955Sthorpej
6180675955Sthorpej struct iodesc *
socktodesc(int sock)6245879fd7Schristos socktodesc(int sock)
6380675955Sthorpej {
6480675955Sthorpej if (sock != 0)
6580675955Sthorpej return NULL;
6666a5580cSdrochner return &sdesc;
6780675955Sthorpej }
6880675955Sthorpej
6980675955Sthorpej int
netif_of_open(struct of_dev * op)7045879fd7Schristos netif_of_open(struct of_dev *op)
7180675955Sthorpej {
7280675955Sthorpej struct iodesc *io;
7380675955Sthorpej
7480675955Sthorpej #ifdef NETIF_DEBUG
7580675955Sthorpej printf("netif_open...");
7680675955Sthorpej #endif
7780675955Sthorpej /* find a free socket */
7866a5580cSdrochner io = &sdesc;
7980675955Sthorpej if (io->io_netif) {
8080675955Sthorpej #ifdef NETIF_DEBUG
8180675955Sthorpej printf("device busy\n");
8280675955Sthorpej #endif
8380675955Sthorpej errno = ENFILE;
8480675955Sthorpej return -1;
8580675955Sthorpej }
8645879fd7Schristos (void)memset(io, 0, sizeof *io);
8780675955Sthorpej
8866a5580cSdrochner io->io_netif = (void *)op;
8980675955Sthorpej
9080675955Sthorpej /* Put our ethernet address in io->myea */
9180675955Sthorpej OF_getprop(OF_instance_to_package(op->handle),
9280675955Sthorpej "mac-address", io->myea, sizeof io->myea);
9380675955Sthorpej
9480675955Sthorpej #ifdef NETIF_DEBUG
9580675955Sthorpej printf("OK\n");
9680675955Sthorpej #endif
9780675955Sthorpej return 0;
9880675955Sthorpej }
9980675955Sthorpej
10066a5580cSdrochner void
netif_of_close(int fd)10145879fd7Schristos netif_of_close(int fd)
10280675955Sthorpej {
10380675955Sthorpej struct iodesc *io;
10480675955Sthorpej
10580675955Sthorpej #ifdef NETIF_DEBUG
10680675955Sthorpej printf("netif_close(%x)...", fd);
10780675955Sthorpej #endif
10880675955Sthorpej
10966a5580cSdrochner #ifdef NETIF_DEBUG
11066a5580cSdrochner if (fd != 0) {
11166a5580cSdrochner printf("EBADF\n");
11266a5580cSdrochner return;
11380675955Sthorpej }
11466a5580cSdrochner #endif
11566a5580cSdrochner
11666a5580cSdrochner io = &sdesc;
11766a5580cSdrochner io->io_netif = NULL;
11866a5580cSdrochner
11980675955Sthorpej #ifdef NETIF_DEBUG
12080675955Sthorpej printf("OK\n");
12180675955Sthorpej #endif
12280675955Sthorpej }
12380675955Sthorpej
12480675955Sthorpej /*
12580675955Sthorpej * Send a packet. The ether header is already there.
12680675955Sthorpej * Return the length sent (or -1 on error).
12780675955Sthorpej */
12880675955Sthorpej ssize_t
netif_put(struct iodesc * desc,void * pkt,size_t len)12945879fd7Schristos netif_put(struct iodesc *desc, void *pkt, size_t len)
13080675955Sthorpej {
13180675955Sthorpej struct of_dev *op;
13280675955Sthorpej ssize_t rv;
13380675955Sthorpej size_t sendlen;
13480675955Sthorpej
13566a5580cSdrochner op = (struct of_dev *)desc->io_netif;
13680675955Sthorpej
13780675955Sthorpej #ifdef NETIF_DEBUG
13880675955Sthorpej {
13980675955Sthorpej struct ether_header *eh;
14080675955Sthorpej
14180675955Sthorpej printf("netif_put: desc=0x%x pkt=0x%x len=%d\n",
14280675955Sthorpej desc, pkt, len);
14380675955Sthorpej eh = pkt;
14480675955Sthorpej printf("dst: %s ", ether_sprintf(eh->ether_dhost));
14580675955Sthorpej printf("src: %s ", ether_sprintf(eh->ether_shost));
14680675955Sthorpej printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
14780675955Sthorpej }
14880675955Sthorpej #endif
14980675955Sthorpej
15080675955Sthorpej sendlen = len;
15180675955Sthorpej if (sendlen < 60) {
15280675955Sthorpej sendlen = 60;
15380675955Sthorpej #ifdef NETIF_DEBUG
15480675955Sthorpej printf("netif_put: length padded to %d\n", sendlen);
15580675955Sthorpej #endif
15680675955Sthorpej }
15780675955Sthorpej
15880675955Sthorpej rv = OF_write(op->handle, pkt, sendlen);
15980675955Sthorpej
16080675955Sthorpej #ifdef NETIF_DEBUG
16180675955Sthorpej printf("netif_put: xmit returned %d\n", rv);
16280675955Sthorpej #endif
16380675955Sthorpej
16480675955Sthorpej return rv;
16580675955Sthorpej }
16680675955Sthorpej
16780675955Sthorpej /*
16880675955Sthorpej * Receive a packet, including the ether header.
16980675955Sthorpej * Return the total length received (or -1 on error).
17080675955Sthorpej */
17180675955Sthorpej ssize_t
netif_get(struct iodesc * desc,void * pkt,size_t maxlen,saseconds_t timo)172*69cf32a7Stsutsui netif_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timo)
17380675955Sthorpej {
17480675955Sthorpej struct of_dev *op;
17580675955Sthorpej int tick0, tmo_ms;
17680675955Sthorpej int len;
17780675955Sthorpej
17866a5580cSdrochner op = (struct of_dev *)desc->io_netif;
17980675955Sthorpej
18080675955Sthorpej #ifdef NETIF_DEBUG
18180675955Sthorpej printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n",
18280675955Sthorpej pkt, maxlen, timo);
18380675955Sthorpej #endif
18480675955Sthorpej
18580675955Sthorpej tmo_ms = timo * 1000;
18680675955Sthorpej tick0 = OF_milliseconds();
18780675955Sthorpej
18880675955Sthorpej do {
18980675955Sthorpej len = OF_read(op->handle, pkt, maxlen);
19080675955Sthorpej } while ((len == -2 || len == 0) &&
19180675955Sthorpej (OF_milliseconds() - tick0 < tmo_ms));
19280675955Sthorpej
19380675955Sthorpej #ifdef NETIF_DEBUG
19480675955Sthorpej printf("netif_get: received len=%d\n", len);
19580675955Sthorpej #endif
19680675955Sthorpej
19780675955Sthorpej if (len < 12)
19880675955Sthorpej return -1;
19980675955Sthorpej
20080675955Sthorpej #ifdef NETIF_DEBUG
20180675955Sthorpej {
20280675955Sthorpej struct ether_header *eh = pkt;
20380675955Sthorpej
20480675955Sthorpej printf("dst: %s ", ether_sprintf(eh->ether_dhost));
20580675955Sthorpej printf("src: %s ", ether_sprintf(eh->ether_shost));
20680675955Sthorpej printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
20780675955Sthorpej }
20880675955Sthorpej #endif
20980675955Sthorpej
21080675955Sthorpej return len;
21180675955Sthorpej }
21280675955Sthorpej
21380675955Sthorpej /*
21480675955Sthorpej * Shouldn't really be here, but is used solely for networking, so...
21580675955Sthorpej */
216*69cf32a7Stsutsui satime_t
getsecs(void)21745879fd7Schristos getsecs(void)
21880675955Sthorpej {
21980675955Sthorpej return OF_milliseconds() / 1000;
22080675955Sthorpej }
221