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