1/*	$OpenBSD: netif_of.c,v 1.6 2014/08/21 14:24:08 mpi Exp $	*/
2/*	$NetBSD: netif_of.c,v 1.1 1997/04/16 20:29:19 thorpej Exp $	*/
3
4/*
5 * Copyright (C) 1995 Wolfgang Solfrank.
6 * Copyright (C) 1995 TooLs GmbH.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by TooLs GmbH.
20 * 4. The name of TooLs GmbH may not be used to endorse or promote products
21 *    derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/*
36 * Open Firmware does most of the job for interfacing to the hardware,
37 * so it is easiest to just replace the netif module with
38 * this adaptation to the PROM network interface.
39 *
40 * Note: this is based in part on sys/arch/sparc/stand/netif_sun.c
41 */
42
43#include <sys/param.h>
44#include <sys/socket.h>
45
46#if 0			/* XXX thorpej */
47#include <string.h>
48#include <time.h>
49#endif
50
51#include <net/if.h>
52
53#include <netinet/in.h>
54#include <netinet/if_ether.h>
55
56#include <lib/libsa/stand.h>
57#include <lib/libsa/net.h>
58#include <lib/libsa/netif.h>
59
60#include <macppc/stand/ofdev.h>
61#include <macppc/stand/openfirm.h>
62
63static struct netif netif_of;
64
65struct iodesc sockets[SOPEN_MAX];
66
67struct iodesc *
68socktodesc(int sock)
69{
70	if (sock != 0)
71		return NULL;
72	return sockets;
73}
74
75int
76netif_open(void *machdep_hint)
77{
78	struct of_dev *op = machdep_hint;
79	struct iodesc *io;
80
81#ifdef	NETIF_DEBUG
82	printf("netif_open...");
83#endif
84	/* find a free socket */
85	io = sockets;
86	if (io->io_netif) {
87#ifdef	NETIF_DEBUG
88		printf("device busy\n");
89#endif
90		errno = ENFILE;
91		return -1;
92	}
93	bzero(io, sizeof *io);
94
95	netif_of.nif_devdata = op;
96	io->io_netif = &netif_of;
97
98	/* Put our ethernet address in io->myea */
99	OF_getprop(OF_instance_to_package(op->handle),
100		   "local-mac-address", io->myea, sizeof io->myea) == -1 &&
101	OF_getprop(OF_instance_to_package(op->handle),
102		   "mac-address", io->myea, sizeof io->myea);
103
104#ifdef	NETIF_DEBUG
105	printf("OK\n");
106#endif
107	return 0;
108}
109
110int
111netif_close(int fd)
112{
113	struct iodesc *io;
114	struct netif *ni;
115
116#ifdef	NETIF_DEBUG
117	printf("netif_close(%x)...", fd);
118#endif
119	if (fd != 0) {
120#ifdef	NETIF_DEBUG
121		printf("EBADF\n");
122#endif
123		errno = EBADF;
124		return -1;
125	}
126
127	io = &sockets[fd];
128	ni = io->io_netif;
129	if (ni != NULL) {
130		ni->nif_devdata = NULL;
131		io->io_netif = NULL;
132	}
133#ifdef	NETIF_DEBUG
134	printf("OK\n");
135#endif
136	return 0;
137}
138
139/*
140 * Send a packet.  The ether header is already there.
141 * Return the length sent (or -1 on error).
142 */
143ssize_t
144netif_put(struct iodesc *desc, void *pkt, size_t len)
145{
146	struct of_dev *op;
147	ssize_t rv;
148	size_t sendlen;
149
150	op = desc->io_netif->nif_devdata;
151
152#ifdef	NETIF_DEBUG
153	{
154		struct ether_header *eh;
155
156		printf("netif_put: desc=0x%x pkt=0x%x len=%d\n",
157		       desc, pkt, len);
158		eh = pkt;
159		printf("dst: %s ", ether_sprintf(eh->ether_dhost));
160		printf("src: %s ", ether_sprintf(eh->ether_shost));
161		printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
162	}
163#endif
164
165	sendlen = len;
166	if (sendlen < 60) {
167		sendlen = 60;
168#ifdef	NETIF_DEBUG
169		printf("netif_put: length padded to %d\n", sendlen);
170#endif
171	}
172
173	if (op->dmabuf) {
174		bcopy(pkt, op->dmabuf, sendlen);
175		pkt = op->dmabuf;
176	}
177	rv = OF_write(op->handle, pkt, sendlen);
178
179#ifdef	NETIF_DEBUG
180	printf("netif_put: xmit returned %d\n", rv);
181#endif
182
183	return rv;
184}
185
186/*
187 * Receive a packet, including the ether header.
188 * Return the total length received (or -1 on error).
189 */
190ssize_t
191netif_get(struct iodesc *desc, void *pkt, size_t maxlen, time_t timo)
192{
193	struct of_dev *op;
194	int tick0, tmo_ms;
195	int len;
196
197	op = desc->io_netif->nif_devdata;
198
199#ifdef	NETIF_DEBUG
200	printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n",
201	   pkt, maxlen, timo);
202#endif
203
204	tmo_ms = timo * 1000;
205	tick0 = OF_milliseconds();
206
207	do {
208		len = OF_read(op->handle, pkt, maxlen);
209	} while ((len == -2 || len == 0) &&
210	     ((OF_milliseconds() - tick0) < tmo_ms));
211
212#ifdef	NETIF_DEBUG
213	printf("netif_get: received len=%d\n", len);
214#endif
215
216	if (len < 12)
217		return -1;
218
219#ifdef	NETIF_DEBUG
220	{
221		struct ether_header *eh = pkt;
222
223		printf("dst: %s ", ether_sprintf(eh->ether_dhost));
224		printf("src: %s ", ether_sprintf(eh->ether_shost));
225		printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
226	}
227#endif
228
229	return len;
230}
231
232/*
233 * Shouldn't really be here, but is used solely for networking, so...
234 */
235time_t
236getsecs()
237{
238	return OF_milliseconds() / 1000;
239}
240