66e4c4cc5c8a994a250a9b099fbf8312a67b6a92
[dragonfly.git] / sys / boot / alpha / libalpha / srmnet.c
1 /* 
2  * $FreeBSD: src/sys/boot/alpha/libalpha/srmnet.c,v 1.4 1999/09/06 18:32:40 dfr Exp $
3  * $DragonFly: src/sys/boot/alpha/libalpha/Attic/srmnet.c,v 1.2 2003/06/17 04:28:16 dillon Exp $
4  * From: $NetBSD: if_prom.c,v 1.10 1997/09/06 14:08:33 drochner Exp $ 
5  */
6
7 /*
8  * Copyright (c) 1997 Christopher G. Demetriou.  All rights reserved.
9  * Copyright (c) 1993 Adam Glass
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *      This product includes software developed by Adam Glass.
23  * 4. The name of the Author may not be used to endorse or promote products
24  *    derived from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38
39 #include <sys/param.h>
40 #include <sys/types.h>
41
42 #include <netinet/in.h>
43 #include <netinet/in_systm.h>
44
45 #include <stand.h>
46 #include <net.h>
47 #include <netif.h>
48 #include <machine/prom.h>
49 #include "bbinfo.h"
50
51 int prom_probe();
52 int prom_match();
53 void prom_init();
54 int prom_get();
55 int prom_put();
56 void prom_end();
57
58 extern struct netif_stats       prom_stats[];
59
60 struct netif_dif prom_ifs[] = {
61 /*      dif_unit        dif_nsel        dif_stats       dif_private     */
62     {   0,              1,              &prom_stats[0], 0,              },
63 };
64
65 struct netif_stats prom_stats[NENTS(prom_ifs)];
66
67 struct netbbinfo netbbinfo = {
68     0xfeedbabedeadbeef,                 /* magic number */
69     0,                                  /* set */
70     {0, 0, 0, 0, 0, 0},                 /* ether address */
71     0,                                  /* force */
72     { 0, },                                     /* pad2 */
73     0,                                  /* cksum */
74     0xfeedbeefdeadbabe,                 /* magic number */
75 };
76
77 struct netif_driver srmnet = {
78     "prom",                     /* netif_bname */
79     prom_match,         /* netif_match */
80     prom_probe,         /* netif_probe */
81     prom_init,          /* netif_init */
82     prom_get,           /* netif_get */
83     prom_put,           /* netif_put */
84     prom_end,           /* netif_end */
85     prom_ifs,           /* netif_ifs */
86     NENTS(prom_ifs)             /* netif_nifs */
87 };
88
89 int netfd = 0, broken_firmware;
90
91 int
92 prom_match(nif, machdep_hint)
93     struct netif *nif;
94     void *machdep_hint;
95 {
96
97     return (1);
98 }
99
100 int
101 prom_probe(nif, machdep_hint)
102     struct netif *nif;
103     void *machdep_hint;
104 {
105
106     return 0;
107 }
108
109 int
110 prom_put(desc, pkt, len)
111     struct iodesc *desc;
112     void *pkt;
113     int len;
114 {
115
116     prom_write(netfd, len, pkt, 0);
117
118     return len;
119 }
120
121
122 int
123 prom_get(desc, pkt, len, timeout)
124     struct iodesc *desc;
125     void *pkt;
126     int len;
127     time_t timeout;
128 {
129     prom_return_t ret;
130     time_t t;
131     int cc;
132     char hate[2000];
133
134     t = getsecs();
135     cc = 0;
136     while (((getsecs() - t) < timeout) && !cc) {
137         if (broken_firmware)
138             ret.bits = prom_read(netfd, 0, hate, 0);
139         else
140             ret.bits = prom_read(netfd, sizeof hate, hate, 0);
141         if (ret.u.status == 0)
142             cc = ret.u.retval;
143     }
144     if (broken_firmware)
145         cc = min(cc, len);
146     else
147         cc = len;
148     bcopy(hate, pkt, cc);
149
150     return cc;
151 }
152
153 extern char *strchr();
154
155 void
156 prom_init(desc, machdep_hint)
157     struct iodesc *desc;
158     void *machdep_hint;
159 {
160     prom_return_t ret;
161     char devname[64];
162     int devlen, i;
163     int netbbinfovalid;
164     char *enet_addr;
165     u_int64_t *qp, csum;
166
167     broken_firmware = 0;
168
169     csum = 0;
170     for (i = 0, qp = (u_int64_t *)&netbbinfo;
171          i < (sizeof netbbinfo / sizeof (u_int64_t)); i++, qp++)
172         csum += *qp;
173     netbbinfovalid = (csum == 0);
174     if (netbbinfovalid)
175         netbbinfovalid = netbbinfo.set;
176
177 #if 0
178     printf("netbbinfo ");
179     if (!netbbinfovalid)
180         printf("invalid\n");
181     else
182         printf("valid: force = %d, ea = %s\n", netbbinfo.force,
183                ether_sprintf(netbbinfo.ether_addr));
184 #endif
185
186     ret.bits = prom_getenv(PROM_E_BOOTED_DEV, devname, sizeof(devname));
187     devlen = ret.u.retval;
188
189     /* Ethernet address is the 9th component of the booted_dev string. */
190     enet_addr = devname;
191     for (i = 0; i < 8; i++) {
192         enet_addr = strchr(enet_addr, ' ');
193         if (enet_addr == NULL) {
194             printf("boot: boot device name does not contain ethernet address.\n");
195             goto punt;
196         }
197         enet_addr++;
198     }
199     if (enet_addr != NULL) {
200         int hv, lv;
201
202 #define dval(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
203                  (((c) >= 'A' && (c) <= 'F') ? (10 + (c) - 'A') : \
204                   (((c) >= 'a' && (c) <= 'f') ? (10 + (c) - 'a') : -1)))
205
206             for (i = 0; i < 6; i++) {
207                 hv = dval(*enet_addr); enet_addr++;
208                 lv = dval(*enet_addr); enet_addr++;
209                 enet_addr++;
210
211                 if (hv == -1 || lv == -1) {
212                     printf("boot: boot device name contains bogus ethernet address.\n");
213                     goto punt;
214                 }
215
216                 desc->myea[i] = (hv << 4) | lv;
217             }
218 #undef dval
219     }
220
221     if (netbbinfovalid && netbbinfo.force) {
222         printf("boot: using hard-coded ethernet address (forced).\n");
223         bcopy(netbbinfo.ether_addr, desc->myea, sizeof desc->myea);
224     }
225
226  gotit:
227     printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea));
228
229     ret.bits = prom_open(devname, devlen + 1);
230     if (ret.u.status) {
231         printf("prom_init: open failed: %d\n", ret.u.status);
232         goto reallypunt;
233     }
234     netfd = ret.u.retval;
235     return;
236
237  punt:
238     broken_firmware = 1;
239     if (netbbinfovalid) {
240         printf("boot: using hard-coded ethernet address.\n");
241         bcopy(netbbinfo.ether_addr, desc->myea, sizeof desc->myea);
242         goto gotit;
243     }
244
245  reallypunt:
246     printf("\n");
247     printf("Boot device name was: \"%s\"\n", devname);
248     printf("\n");
249     printf("Your firmware may be too old to network-boot FreeBSD/alpha,\n");
250     printf("or you might have to hard-code an ethernet address into\n");
251     printf("your network boot block with setnetbootinfo(8).\n");
252     halt();
253 }
254
255 void
256 prom_end(nif)
257     struct netif *nif;
258 {
259     prom_close(netfd);
260 }