1 1.31 riastrad /* $NetBSD: promdev.c,v 1.31 2025/01/17 10:35:47 riastradh Exp $ */ 2 1.1 mrg 3 1.1 mrg /* 4 1.1 mrg * Copyright (c) 1993 Paul Kranenburg 5 1.1 mrg * Copyright (c) 1995 Gordon W. Ross 6 1.1 mrg * All rights reserved. 7 1.1 mrg * 8 1.1 mrg * Redistribution and use in source and binary forms, with or without 9 1.1 mrg * modification, are permitted provided that the following conditions 10 1.1 mrg * are met: 11 1.1 mrg * 1. Redistributions of source code must retain the above copyright 12 1.1 mrg * notice, this list of conditions and the following disclaimer. 13 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 mrg * notice, this list of conditions and the following disclaimer in the 15 1.1 mrg * documentation and/or other materials provided with the distribution. 16 1.1 mrg * 3. All advertising materials mentioning features or use of this software 17 1.1 mrg * must display the following acknowledgement: 18 1.1 mrg * This product includes software developed by Paul Kranenburg. 19 1.1 mrg * 4. The name of the author may not be used to endorse or promote products 20 1.1 mrg * derived from this software without specific prior written permission 21 1.1 mrg * 22 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 1.1 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 1.1 mrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 1.1 mrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 1.1 mrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 1.1 mrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 1.1 mrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 1.1 mrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 1.1 mrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 mrg */ 33 1.1 mrg 34 1.1 mrg /* 35 1.1 mrg * Note: the `#ifndef BOOTXX' in here serve to queeze the code size 36 1.1 mrg * of the 1st-stage boot program. 37 1.1 mrg */ 38 1.1 mrg #include <sys/param.h> 39 1.1 mrg #include <sys/reboot.h> 40 1.8 christos #include <sys/systm.h> 41 1.1 mrg #include <machine/oldmon.h> 42 1.7 pk #include <machine/promlib.h> 43 1.1 mrg #include <machine/ctlreg.h> 44 1.6 pk #include <sparc/sparc/asm.h> 45 1.6 pk #include <machine/pte.h> 46 1.1 mrg 47 1.1 mrg #include <lib/libsa/stand.h> 48 1.22 tsutsui #include <lib/libsa/net.h> 49 1.15 mrg #include <lib/libkern/libkern.h> 50 1.1 mrg #include <sparc/stand/common/promdev.h> 51 1.25 christos #include <sparc/stand/common/isfloppy.h> 52 1.1 mrg 53 1.19 jdc #ifndef BOOTXX 54 1.19 jdc #include <sys/disklabel.h> 55 1.19 jdc #include <dev/sun/disklabel.h> 56 1.19 jdc #include <dev/raidframe/raidframevar.h> 57 1.19 jdc #endif 58 1.19 jdc 59 1.7 pk /* OBP V0-3 PROM vector */ 60 1.7 pk #define obpvec ((struct promvec *)romp) 61 1.7 pk 62 1.20 uwe int obp_close(struct open_file *); 63 1.20 uwe int obp_strategy(void *, int, daddr_t, size_t, void *, size_t *); 64 1.20 uwe int obp_v0_strategy(void *, int, daddr_t, size_t, void *, size_t *); 65 1.20 uwe ssize_t obp_v0_xmit(struct promdata *, void *, size_t); 66 1.20 uwe ssize_t obp_v0_recv(struct promdata *, void *, size_t); 67 1.20 uwe int obp_v2_strategy(void *, int, daddr_t, size_t, void *, size_t *); 68 1.20 uwe ssize_t obp_v2_xmit(struct promdata *, void *, size_t); 69 1.20 uwe ssize_t obp_v2_recv(struct promdata *, void *, size_t); 70 1.20 uwe int oldmon_close(struct open_file *); 71 1.20 uwe int oldmon_strategy(void *, int, daddr_t, size_t, void *, size_t *); 72 1.20 uwe void oldmon_iclose(struct saioreq *); 73 1.20 uwe int oldmon_iopen(struct promdata *); 74 1.20 uwe ssize_t oldmon_xmit(struct promdata *, void *, size_t); 75 1.20 uwe ssize_t oldmon_recv(struct promdata *, void *, size_t); 76 1.1 mrg 77 1.20 uwe static char *oldmon_mapin(u_long, int, int); 78 1.7 pk #ifndef BOOTXX 79 1.20 uwe static char *mygetpropstring(int, char *); 80 1.20 uwe static int getdevtype(int, char *); 81 1.31 riastrad void israidlabel(char *buf); 82 1.30 jdc 83 1.30 jdc static daddr_t doffset = 0; 84 1.30 jdc static int raidchecked = 0; 85 1.30 jdc 86 1.7 pk #endif 87 1.1 mrg 88 1.18 mrg extern struct fs_ops file_system_nfs[]; 89 1.18 mrg extern struct fs_ops file_system_ufs[]; 90 1.1 mrg 91 1.7 pk #define null_devopen (void *)sparc_noop 92 1.7 pk #define null_devioctl (void *)sparc_noop 93 1.7 pk 94 1.7 pk #if 0 95 1.7 pk struct devsw devsw[]; 96 1.7 pk int ndevs = (sizeof(devsw)/sizeof(devsw[0])); 97 1.7 pk #endif 98 1.1 mrg 99 1.7 pk struct devsw oldmon_devsw = 100 1.7 pk { "oldmon", oldmon_strategy, null_devopen, oldmon_close, null_devioctl }; 101 1.7 pk struct devsw obp_v0_devsw = 102 1.7 pk { "obp v0", obp_v0_strategy, null_devopen, obp_close, null_devioctl }; 103 1.7 pk struct devsw obp_v2_devsw = 104 1.7 pk { "obp v2", obp_v2_strategy, null_devopen, obp_close, null_devioctl }; 105 1.1 mrg 106 1.1 mrg 107 1.16 martin char prom_bootdevice[MAX_PROM_PATH]; 108 1.7 pk static int saveecho; 109 1.1 mrg 110 1.19 jdc #ifndef BOOTXX 111 1.30 jdc void 112 1.30 jdc israidlabel(char *buf) 113 1.30 jdc { 114 1.30 jdc char *partition; 115 1.30 jdc int part = 0; 116 1.30 jdc struct disklabel *dlp; 117 1.30 jdc 118 1.30 jdc /* Check the disklabel to see if the boot partition is type RAID. 119 1.30 jdc * 120 1.30 jdc * For machines with prom_version() == PROM_OLDMON, we 121 1.30 jdc * only handle boot from RAID for the first disk partition 122 1.30 jdc * because we only know the boot device but not the partition. 123 1.30 jdc */ 124 1.30 jdc if (prom_version() != PROM_OLDMON) { 125 1.30 jdc if ((partition = strchr(prom_bootdevice, ':')) != NULL && 126 1.30 jdc *++partition >= 'a' && 127 1.30 jdc *partition <= 'a' + MAXPARTITIONS) 128 1.30 jdc part = *partition - 'a'; 129 1.30 jdc } 130 1.30 jdc 131 1.30 jdc #ifdef DEBUG_PROM 132 1.30 jdc printf("israidlabel: Checking disklabel for RAID partition (%c)\n", 133 1.30 jdc 'a' + part); 134 1.30 jdc #endif 135 1.30 jdc 136 1.30 jdc #ifdef NOTDEF_DEBUG 137 1.30 jdc { 138 1.30 jdc int x = 0; 139 1.30 jdc char *p = (char *) buf; 140 1.30 jdc 141 1.30 jdc printf("Disklabel sector (%d):\n", LABELSECTOR); 142 1.30 jdc printf("00000000 "); 143 1.30 jdc while (x < DEV_BSIZE) { 144 1.30 jdc if (*p >= 0x00 && *p < 0x10) 145 1.30 jdc printf("0%x ", *p & 0xff); 146 1.30 jdc else 147 1.30 jdc printf("%x ", *p & 0xff); 148 1.30 jdc x++; 149 1.30 jdc if (x && !(x % 8)) 150 1.30 jdc printf(" "); 151 1.30 jdc if (x && !(x % 16)) { 152 1.30 jdc if(x < 0x100) 153 1.30 jdc printf("\n000000%x ", x); 154 1.30 jdc else 155 1.30 jdc printf("\n00000%x ", x); 156 1.30 jdc } 157 1.30 jdc p++; 158 1.30 jdc } 159 1.30 jdc printf("\n"); 160 1.30 jdc } 161 1.30 jdc #endif 162 1.30 jdc /* Check for NetBSD disk label. */ 163 1.30 jdc dlp = (struct disklabel *) (buf + LABELOFFSET); 164 1.30 jdc if (dlp->d_magic == DISKMAGIC && !dkcksum(dlp) && 165 1.30 jdc dlp->d_partitions[part].p_fstype == FS_RAID) { 166 1.30 jdc #ifdef DEBUG_PROM 167 1.30 jdc printf("israidlabel: found RAID partition, " 168 1.30 jdc "adjusting offset to %ld\n", RF_PROTECTED_SECTORS); 169 1.19 jdc #endif 170 1.30 jdc doffset = RF_PROTECTED_SECTORS; 171 1.30 jdc } 172 1.30 jdc } 173 1.30 jdc #endif /* BOOTXX */ 174 1.19 jdc 175 1.1 mrg void 176 1.20 uwe putchar(int c) 177 1.1 mrg { 178 1.31 riastrad 179 1.7 pk if (c == '\n') 180 1.7 pk prom_putchar('\r'); 181 1.7 pk prom_putchar(c); 182 1.7 pk } 183 1.1 mrg 184 1.7 pk void 185 1.20 uwe _rtt(void) 186 1.7 pk { 187 1.20 uwe 188 1.7 pk prom_halt(); 189 1.1 mrg } 190 1.1 mrg 191 1.1 mrg int 192 1.20 uwe devopen(struct open_file *f, const char *fname, char **file) 193 1.1 mrg { 194 1.11 mrg int error = 0, fd = 0; 195 1.1 mrg struct promdata *pd; 196 1.1 mrg 197 1.1 mrg pd = (struct promdata *)alloc(sizeof *pd); 198 1.7 pk f->f_devdata = (void *)pd; 199 1.1 mrg 200 1.7 pk switch (prom_version()) { 201 1.7 pk case PROM_OLDMON: 202 1.30 jdc #ifdef DEBUG_PROM 203 1.30 jdc printf("devopen: PROM_OLDMON\n"); 204 1.30 jdc #endif 205 1.7 pk error = oldmon_iopen(pd); 206 1.1 mrg #ifndef BOOTXX 207 1.7 pk pd->xmit = oldmon_xmit; 208 1.7 pk pd->recv = oldmon_recv; 209 1.1 mrg #endif 210 1.7 pk f->f_dev = &oldmon_devsw; 211 1.7 pk saveecho = *romVectorPtr->echo; 212 1.7 pk *romVectorPtr->echo = 0; 213 1.7 pk break; 214 1.7 pk 215 1.7 pk case PROM_OBP_V0: 216 1.7 pk case PROM_OBP_V2: 217 1.7 pk case PROM_OBP_V3: 218 1.7 pk case PROM_OPENFIRM: 219 1.16 martin if (*prom_bootdevice == '\0') { 220 1.7 pk error = ENXIO; 221 1.7 pk break; 222 1.7 pk } 223 1.7 pk fd = prom_open(prom_bootdevice); 224 1.1 mrg if (fd == 0) { 225 1.1 mrg error = ENXIO; 226 1.7 pk break; 227 1.7 pk } 228 1.7 pk pd->fd = fd; 229 1.7 pk switch (prom_version()) { 230 1.7 pk case PROM_OBP_V0: 231 1.30 jdc #ifdef DEBUG_PROM 232 1.30 jdc printf("devopen: PROM_OBP_V0\n"); 233 1.30 jdc #endif 234 1.1 mrg #ifndef BOOTXX 235 1.7 pk pd->xmit = obp_v0_xmit; 236 1.7 pk pd->recv = obp_v0_recv; 237 1.1 mrg #endif 238 1.7 pk f->f_dev = &obp_v0_devsw; 239 1.7 pk break; 240 1.7 pk case PROM_OBP_V2: 241 1.7 pk case PROM_OBP_V3: 242 1.7 pk case PROM_OPENFIRM: 243 1.30 jdc #ifdef DEBUG_PROM 244 1.30 jdc printf("devopen: PROM_OBP_V2+\n"); 245 1.30 jdc #endif 246 1.7 pk #ifndef BOOTXX 247 1.7 pk pd->xmit = obp_v2_xmit; 248 1.7 pk pd->recv = obp_v2_recv; 249 1.7 pk #endif 250 1.7 pk f->f_dev = &obp_v2_devsw; 251 1.1 mrg } 252 1.1 mrg } 253 1.1 mrg 254 1.1 mrg if (error) { 255 1.1 mrg printf("Can't open device `%s'\n", prom_bootdevice); 256 1.1 mrg return (error); 257 1.1 mrg } 258 1.1 mrg 259 1.1 mrg #ifdef BOOTXX 260 1.1 mrg pd->devtype = DT_BLOCK; 261 1.1 mrg #else /* BOOTXX */ 262 1.1 mrg pd->devtype = getdevtype(fd, prom_bootdevice); 263 1.1 mrg /* Assume type BYTE is a raw device */ 264 1.1 mrg if (pd->devtype != DT_BYTE) 265 1.1 mrg *file = (char *)fname; 266 1.1 mrg 267 1.1 mrg if (pd->devtype == DT_NET) { 268 1.21 tsutsui nfsys = 1; 269 1.21 tsutsui memcpy(file_system, file_system_nfs, 270 1.21 tsutsui sizeof(struct fs_ops) * nfsys); 271 1.1 mrg if ((error = net_open(pd)) != 0) { 272 1.7 pk printf("Can't open NFS network connection on `%s'\n", 273 1.1 mrg prom_bootdevice); 274 1.7 pk return (error); 275 1.1 mrg } 276 1.30 jdc } else 277 1.21 tsutsui memcpy(file_system, file_system_ufs, 278 1.21 tsutsui sizeof(struct fs_ops) * nfsys); 279 1.19 jdc 280 1.30 jdc /* Don't check disklabel for RAID on floppy boot */ 281 1.30 jdc if (bootdev_isfloppy(prom_bootdevice)) 282 1.30 jdc raidchecked = 1; 283 1.1 mrg #endif /* BOOTXX */ 284 1.7 pk return (0); 285 1.7 pk } 286 1.7 pk 287 1.7 pk 288 1.7 pk int 289 1.20 uwe obp_v0_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 290 1.20 uwe void *buf, size_t *rsize) 291 1.7 pk { 292 1.7 pk int n, error = 0; 293 1.7 pk struct promdata *pd = (struct promdata *)devdata; 294 1.7 pk int fd = pd->fd; 295 1.19 jdc #ifndef BOOTXX 296 1.30 jdc char labelbuf[DEV_BSIZE]; 297 1.19 jdc #endif 298 1.30 jdc 299 1.7 pk #ifdef DEBUG_PROM 300 1.30 jdc if (dblk < 3000) 301 1.26 uwe printf("promstrategy: size=%zd dblk=%d\n", size, (int)dblk); 302 1.7 pk #endif 303 1.7 pk 304 1.7 pk #define prom_bread(fd, nblk, dblk, buf) \ 305 1.7 pk (*obpvec->pv_v0devops.v0_rbdev)(fd, nblk, dblk, buf) 306 1.7 pk #define prom_bwrite(fd, nblk, dblk, buf) \ 307 1.7 pk (*obpvec->pv_v0devops.v0_wbdev)(fd, nblk, dblk, buf) 308 1.7 pk 309 1.7 pk #ifndef BOOTXX /* We know it's a block device, so save some space */ 310 1.7 pk if (pd->devtype != DT_BLOCK) { 311 1.7 pk printf("promstrategy: non-block device not supported\n"); 312 1.7 pk error = EINVAL; 313 1.7 pk } 314 1.30 jdc 315 1.30 jdc if (!raidchecked && flag == F_READ) { 316 1.30 jdc prom_bread(fd, btodb(DEV_BSIZE), LABELSECTOR, &labelbuf[0]); 317 1.30 jdc israidlabel(&labelbuf[0]); 318 1.30 jdc raidchecked = 1; 319 1.30 jdc } 320 1.30 jdc dblk += doffset; 321 1.7 pk #endif 322 1.7 pk 323 1.7 pk n = (flag == F_READ) 324 1.7 pk ? prom_bread(fd, btodb(size), dblk, buf) 325 1.7 pk : prom_bwrite(fd, btodb(size), dblk, buf); 326 1.7 pk 327 1.7 pk *rsize = dbtob(n); 328 1.7 pk 329 1.7 pk #ifdef DEBUG_PROM 330 1.30 jdc if (dblk < 3000) 331 1.26 uwe printf("rsize = %zx\n", *rsize); 332 1.7 pk #endif 333 1.7 pk return (error); 334 1.1 mrg } 335 1.1 mrg 336 1.1 mrg int 337 1.20 uwe obp_v2_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 338 1.20 uwe void *buf, size_t *rsize) 339 1.1 mrg { 340 1.1 mrg int error = 0; 341 1.1 mrg struct promdata *pd = (struct promdata *)devdata; 342 1.1 mrg int fd = pd->fd; 343 1.19 jdc #ifndef BOOTXX 344 1.30 jdc char labelbuf[DEV_BSIZE]; 345 1.19 jdc #endif 346 1.30 jdc 347 1.1 mrg #ifdef DEBUG_PROM 348 1.30 jdc if (dblk < 3000) 349 1.26 uwe printf("promstrategy: size=%zd dblk=%d\n", size, (int)dblk); 350 1.1 mrg #endif 351 1.1 mrg 352 1.30 jdc #ifndef BOOTXX 353 1.30 jdc if (!raidchecked && flag == F_READ) { 354 1.30 jdc prom_seek(fd, dbtob(LABELSECTOR)); 355 1.30 jdc prom_read(fd, &labelbuf[0], DEV_BSIZE); 356 1.30 jdc israidlabel(&labelbuf[0]); 357 1.30 jdc raidchecked = 1; 358 1.30 jdc } 359 1.30 jdc dblk += doffset; 360 1.30 jdc 361 1.30 jdc /* We know it's a block device, so save some space */ 362 1.7 pk if (pd->devtype == DT_BLOCK) 363 1.7 pk #endif 364 1.7 pk prom_seek(fd, dbtob(dblk)); 365 1.7 pk 366 1.7 pk *rsize = (flag == F_READ) 367 1.7 pk ? prom_read(fd, buf, size) 368 1.7 pk : prom_write(fd, buf, size); 369 1.1 mrg 370 1.1 mrg #ifdef DEBUG_PROM 371 1.30 jdc if (dblk < 3000) 372 1.26 uwe printf("rsize = %zx\n", *rsize); 373 1.1 mrg #endif 374 1.7 pk return (error); 375 1.1 mrg } 376 1.1 mrg 377 1.1 mrg /* 378 1.1 mrg * On old-monitor machines, things work differently. 379 1.1 mrg */ 380 1.1 mrg int 381 1.20 uwe oldmon_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 382 1.20 uwe void *buf, size_t *rsize) 383 1.1 mrg { 384 1.1 mrg struct promdata *pd = devdata; 385 1.1 mrg struct saioreq *si; 386 1.1 mrg struct om_boottable *ops; 387 1.1 mrg char *dmabuf; 388 1.1 mrg int si_flag; 389 1.1 mrg size_t xcnt; 390 1.30 jdc #ifndef BOOTXX 391 1.30 jdc char labelbuf[DEV_BSIZE]; 392 1.30 jdc #endif 393 1.1 mrg 394 1.1 mrg si = pd->si; 395 1.1 mrg ops = si->si_boottab; 396 1.1 mrg 397 1.19 jdc #ifndef BOOTXX 398 1.19 jdc dblk += doffset; 399 1.19 jdc #endif 400 1.1 mrg #ifdef DEBUG_PROM 401 1.30 jdc if (dblk < 3000) 402 1.26 uwe printf("prom_strategy: size=%zd dblk=%d\n", size, (int)dblk); 403 1.1 mrg #endif 404 1.31 riastrad 405 1.30 jdc #ifndef BOOTXX 406 1.30 jdc if (!raidchecked && flag == F_READ) { 407 1.30 jdc dmabuf = dvma_mapin(&labelbuf[0], DEV_BSIZE); 408 1.30 jdc si->si_bn = LABELSECTOR; 409 1.30 jdc si->si_cc = DEV_BSIZE; 410 1.30 jdc si_flag = SAIO_F_READ; 411 1.30 jdc xcnt = (*ops->b_strategy)(si, si_flag); 412 1.30 jdc dvma_mapout(dmabuf, DEV_BSIZE); 413 1.30 jdc israidlabel(&labelbuf[0]); 414 1.30 jdc raidchecked = 1; 415 1.30 jdc } 416 1.30 jdc dblk += doffset; 417 1.30 jdc #endif 418 1.1 mrg 419 1.1 mrg dmabuf = dvma_mapin(buf, size); 420 1.30 jdc 421 1.1 mrg si->si_bn = dblk; 422 1.1 mrg si->si_ma = dmabuf; 423 1.1 mrg si->si_cc = size; 424 1.1 mrg 425 1.1 mrg si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE; 426 1.1 mrg xcnt = (*ops->b_strategy)(si, si_flag); 427 1.1 mrg dvma_mapout(dmabuf, size); 428 1.1 mrg 429 1.1 mrg #ifdef DEBUG_PROM 430 1.30 jdc if (dblk < 3000) 431 1.26 uwe printf("disk_strategy: xcnt = %zx\n", xcnt); 432 1.1 mrg #endif 433 1.1 mrg 434 1.1 mrg if (xcnt <= 0) 435 1.1 mrg return (EIO); 436 1.1 mrg 437 1.1 mrg *rsize = xcnt; 438 1.1 mrg return (0); 439 1.1 mrg } 440 1.1 mrg 441 1.1 mrg int 442 1.20 uwe obp_close(struct open_file *f) 443 1.1 mrg { 444 1.1 mrg struct promdata *pd = f->f_devdata; 445 1.1 mrg register int fd = pd->fd; 446 1.1 mrg 447 1.1 mrg #ifndef BOOTXX 448 1.1 mrg if (pd->devtype == DT_NET) 449 1.1 mrg net_close(pd); 450 1.1 mrg #endif 451 1.7 pk prom_close(fd); 452 1.1 mrg return 0; 453 1.1 mrg } 454 1.1 mrg 455 1.1 mrg int 456 1.20 uwe oldmon_close(struct open_file *f) 457 1.1 mrg { 458 1.1 mrg struct promdata *pd = f->f_devdata; 459 1.1 mrg 460 1.1 mrg #ifndef BOOTXX 461 1.1 mrg if (pd->devtype == DT_NET) 462 1.1 mrg net_close(pd); 463 1.1 mrg #endif 464 1.7 pk oldmon_iclose(pd->si); 465 1.1 mrg pd->si = NULL; 466 1.7 pk *romVectorPtr->echo = saveecho; /* Hmm, probably must go somewhere else */ 467 1.1 mrg return 0; 468 1.1 mrg } 469 1.1 mrg 470 1.1 mrg #ifndef BOOTXX 471 1.1 mrg ssize_t 472 1.20 uwe obp_v0_xmit(struct promdata *pd, void *buf, size_t len) 473 1.7 pk { 474 1.7 pk 475 1.7 pk return ((*obpvec->pv_v0devops.v0_wnet)(pd->fd, len, buf)); 476 1.7 pk } 477 1.7 pk 478 1.7 pk ssize_t 479 1.20 uwe obp_v2_xmit(struct promdata *pd, void *buf, size_t len) 480 1.1 mrg { 481 1.7 pk 482 1.7 pk return (prom_write(pd->fd, buf, len)); 483 1.1 mrg } 484 1.1 mrg 485 1.1 mrg ssize_t 486 1.20 uwe obp_v0_recv(struct promdata *pd, void *buf, size_t len) 487 1.1 mrg { 488 1.1 mrg 489 1.7 pk return ((*obpvec->pv_v0devops.v0_rnet)(pd->fd, len, buf)); 490 1.7 pk } 491 1.7 pk 492 1.7 pk ssize_t 493 1.20 uwe obp_v2_recv(struct promdata *pd, void *buf, size_t len) 494 1.7 pk { 495 1.7 pk int n; 496 1.7 pk 497 1.7 pk n = prom_read(pd->fd, buf, len); 498 1.7 pk 499 1.7 pk /* OBP V2 & V3 may return -2 */ 500 1.1 mrg return (n == -2 ? 0 : n); 501 1.1 mrg } 502 1.1 mrg 503 1.1 mrg ssize_t 504 1.20 uwe oldmon_xmit(struct promdata *pd, void *buf, size_t len) 505 1.1 mrg { 506 1.1 mrg struct saioreq *si; 507 1.1 mrg struct saif *sif; 508 1.1 mrg char *dmabuf; 509 1.1 mrg int rv; 510 1.1 mrg 511 1.1 mrg si = pd->si; 512 1.1 mrg sif = si->si_sif; 513 1.1 mrg if (sif == NULL) { 514 1.1 mrg printf("xmit: not a network device\n"); 515 1.1 mrg return (-1); 516 1.1 mrg } 517 1.1 mrg dmabuf = dvma_mapin(buf, len); 518 1.1 mrg rv = sif->sif_xmit(si->si_devdata, dmabuf, len); 519 1.1 mrg dvma_mapout(dmabuf, len); 520 1.1 mrg 521 1.1 mrg return (ssize_t)(rv ? -1 : len); 522 1.1 mrg } 523 1.1 mrg 524 1.1 mrg ssize_t 525 1.20 uwe oldmon_recv(struct promdata *pd, void *buf, size_t len) 526 1.1 mrg { 527 1.1 mrg struct saioreq *si; 528 1.1 mrg struct saif *sif; 529 1.1 mrg char *dmabuf; 530 1.1 mrg int rv; 531 1.1 mrg 532 1.1 mrg si = pd->si; 533 1.1 mrg sif = si->si_sif; 534 1.1 mrg dmabuf = dvma_mapin(buf, len); 535 1.1 mrg rv = sif->sif_poll(si->si_devdata, dmabuf); 536 1.1 mrg dvma_mapout(dmabuf, len); 537 1.1 mrg 538 1.1 mrg return (ssize_t)rv; 539 1.1 mrg } 540 1.1 mrg 541 1.1 mrg int 542 1.20 uwe getchar(void) 543 1.1 mrg { 544 1.20 uwe 545 1.7 pk return (prom_getchar()); 546 1.1 mrg } 547 1.1 mrg 548 1.22 tsutsui satime_t 549 1.20 uwe getsecs(void) 550 1.1 mrg { 551 1.20 uwe 552 1.7 pk (void)prom_peekchar(); 553 1.7 pk return (prom_ticks() / 1000); 554 1.1 mrg } 555 1.1 mrg 556 1.1 mrg /* 557 1.1 mrg * A number of well-known devices on sun4s. 558 1.1 mrg */ 559 1.1 mrg static struct dtab { 560 1.1 mrg char *name; 561 1.1 mrg int type; 562 1.1 mrg } dtab[] = { 563 1.1 mrg { "sd", DT_BLOCK }, 564 1.1 mrg { "st", DT_BLOCK }, 565 1.1 mrg { "xd", DT_BLOCK }, 566 1.1 mrg { "xy", DT_BLOCK }, 567 1.1 mrg { "fd", DT_BLOCK }, 568 1.1 mrg { "le", DT_NET }, 569 1.1 mrg { "ie", DT_NET }, 570 1.1 mrg { NULL, 0 } 571 1.1 mrg }; 572 1.1 mrg 573 1.1 mrg int 574 1.20 uwe getdevtype(int fd, char *name) 575 1.1 mrg { 576 1.7 pk struct dtab *dp; 577 1.7 pk int node; 578 1.7 pk char *cp; 579 1.7 pk 580 1.7 pk switch (prom_version()) { 581 1.7 pk case PROM_OLDMON: 582 1.7 pk case PROM_OBP_V0: 583 1.1 mrg for (dp = dtab; dp->name; dp++) { 584 1.1 mrg if (name[0] == dp->name[0] && 585 1.1 mrg name[1] == dp->name[1]) 586 1.7 pk return (dp->type); 587 1.1 mrg } 588 1.7 pk break; 589 1.1 mrg 590 1.7 pk case PROM_OBP_V2: 591 1.7 pk case PROM_OBP_V3: 592 1.10 pk case PROM_OPENFIRM: 593 1.10 pk node = prom_instance_to_package(fd); 594 1.7 pk cp = mygetpropstring(node, "device_type"); 595 1.7 pk if (strcmp(cp, "block") == 0) 596 1.7 pk return (DT_BLOCK); 597 1.28 martin if (strcmp(cp, "scsi") == 0) 598 1.28 martin return (DT_BLOCK); 599 1.7 pk else if (strcmp(cp, "network") == 0) 600 1.7 pk return (DT_NET); 601 1.7 pk else if (strcmp(cp, "byte") == 0) 602 1.7 pk return (DT_BYTE); 603 1.7 pk break; 604 1.1 mrg } 605 1.7 pk return (0); 606 1.1 mrg } 607 1.1 mrg 608 1.1 mrg /* 609 1.1 mrg * Return a string property. There is a (small) limit on the length; 610 1.1 mrg * the string is fetched into a static buffer which is overwritten on 611 1.1 mrg * subsequent calls. 612 1.1 mrg */ 613 1.1 mrg char * 614 1.20 uwe mygetpropstring(int node, char *name) 615 1.1 mrg { 616 1.7 pk int len; 617 1.7 pk static char buf[64]; 618 1.1 mrg 619 1.7 pk len = prom_proplen(node, name); 620 1.27 martin if (len > sizeof(buf)) 621 1.27 martin len = sizeof(buf)-1; 622 1.7 pk if (len > 0) 623 1.7 pk _prom_getprop(node, name, buf, len); 624 1.7 pk else 625 1.1 mrg len = 0; 626 1.7 pk 627 1.7 pk buf[len] = '\0'; /* usually unnecessary */ 628 1.7 pk return (buf); 629 1.1 mrg } 630 1.1 mrg #endif /* BOOTXX */ 631 1.1 mrg 632 1.1 mrg /* 633 1.1 mrg * Old monitor routines 634 1.1 mrg */ 635 1.1 mrg 636 1.1 mrg struct saioreq prom_si; 637 1.1 mrg static int promdev_inuse; 638 1.1 mrg 639 1.1 mrg int 640 1.20 uwe oldmon_iopen(struct promdata *pd) 641 1.1 mrg { 642 1.1 mrg struct om_bootparam *bp; 643 1.1 mrg struct om_boottable *ops; 644 1.1 mrg struct devinfo *dip; 645 1.1 mrg struct saioreq *si; 646 1.1 mrg int error; 647 1.1 mrg 648 1.1 mrg if (promdev_inuse) 649 1.7 pk return (EMFILE); 650 1.1 mrg 651 1.7 pk bp = *romVectorPtr->bootParam; 652 1.1 mrg ops = bp->bootTable; 653 1.1 mrg dip = ops->b_devinfo; 654 1.1 mrg 655 1.1 mrg #ifdef DEBUG_PROM 656 1.1 mrg printf("Boot device type: %s\n", ops->b_desc); 657 1.1 mrg printf("d_devbytes=%d\n", dip->d_devbytes); 658 1.1 mrg printf("d_dmabytes=%d\n", dip->d_dmabytes); 659 1.1 mrg printf("d_localbytes=%d\n", dip->d_localbytes); 660 1.1 mrg printf("d_stdcount=%d\n", dip->d_stdcount); 661 1.26 uwe printf("d_stdaddrs[%d]=%lx\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]); 662 1.1 mrg printf("d_devtype=%d\n", dip->d_devtype); 663 1.1 mrg printf("d_maxiobytes=%d\n", dip->d_maxiobytes); 664 1.1 mrg #endif 665 1.1 mrg 666 1.1 mrg dvma_init(); 667 1.1 mrg 668 1.1 mrg si = &prom_si; 669 1.7 pk memset(si, 0, sizeof(*si)); 670 1.1 mrg si->si_boottab = ops; 671 1.1 mrg si->si_ctlr = bp->ctlrNum; 672 1.1 mrg si->si_unit = bp->unitNum; 673 1.1 mrg si->si_boff = bp->partNum; 674 1.1 mrg 675 1.7 pk if (si->si_ctlr > dip->d_stdcount) 676 1.7 pk return (ECTLR); 677 1.1 mrg 678 1.1 mrg if (dip->d_devbytes) { 679 1.7 pk si->si_devaddr = oldmon_mapin(dip->d_stdaddrs[si->si_ctlr], 680 1.1 mrg dip->d_devbytes, dip->d_devtype); 681 1.1 mrg #ifdef DEBUG_PROM 682 1.26 uwe printf("prom_iopen: devaddr=%p pte=0x%x\n", 683 1.1 mrg si->si_devaddr, 684 1.6 pk getpte4((u_long)si->si_devaddr & ~PGOFSET)); 685 1.1 mrg #endif 686 1.1 mrg } 687 1.1 mrg 688 1.1 mrg if (dip->d_dmabytes) { 689 1.1 mrg si->si_dmaaddr = dvma_alloc(dip->d_dmabytes); 690 1.1 mrg #ifdef DEBUG_PROM 691 1.26 uwe printf("prom_iopen: dmaaddr=%p\n", si->si_dmaaddr); 692 1.1 mrg #endif 693 1.1 mrg } 694 1.1 mrg 695 1.1 mrg if (dip->d_localbytes) { 696 1.1 mrg si->si_devdata = alloc(dip->d_localbytes); 697 1.1 mrg #ifdef DEBUG_PROM 698 1.26 uwe printf("prom_iopen: devdata=%p\n", si->si_devdata); 699 1.1 mrg #endif 700 1.1 mrg } 701 1.1 mrg 702 1.1 mrg /* OK, call the PROM device open routine. */ 703 1.1 mrg error = (*ops->b_open)(si); 704 1.1 mrg if (error != 0) { 705 1.7 pk printf("prom_iopen: \"%s\" error=%d\n", ops->b_desc, error); 706 1.1 mrg return (ENXIO); 707 1.1 mrg } 708 1.1 mrg #ifdef DEBUG_PROM 709 1.1 mrg printf("prom_iopen: succeeded, error=%d\n", error); 710 1.1 mrg #endif 711 1.1 mrg 712 1.1 mrg pd->si = si; 713 1.1 mrg promdev_inuse++; 714 1.1 mrg return (0); 715 1.1 mrg } 716 1.1 mrg 717 1.1 mrg void 718 1.20 uwe oldmon_iclose(struct saioreq *si) 719 1.1 mrg { 720 1.1 mrg struct om_boottable *ops; 721 1.1 mrg struct devinfo *dip; 722 1.1 mrg 723 1.1 mrg if (promdev_inuse == 0) 724 1.1 mrg return; 725 1.1 mrg 726 1.1 mrg ops = si->si_boottab; 727 1.1 mrg dip = ops->b_devinfo; 728 1.1 mrg 729 1.1 mrg (*ops->b_close)(si); 730 1.1 mrg 731 1.1 mrg if (si->si_dmaaddr) { 732 1.1 mrg dvma_free(si->si_dmaaddr, dip->d_dmabytes); 733 1.1 mrg si->si_dmaaddr = NULL; 734 1.1 mrg } 735 1.1 mrg 736 1.1 mrg promdev_inuse = 0; 737 1.1 mrg } 738 1.1 mrg 739 1.1 mrg static struct mapinfo { 740 1.1 mrg int maptype; 741 1.1 mrg int pgtype; 742 1.1 mrg int base; 743 1.7 pk } oldmon_mapinfo[] = { 744 1.7 pk #define PG_COMMON (PG_V|PG_W|PG_S|PG_NC) 745 1.7 pk { MAP_MAINMEM, PG_OBMEM | PG_COMMON, 0 }, 746 1.7 pk { MAP_OBIO, PG_OBIO | PG_COMMON, 0 }, 747 1.7 pk { MAP_MBMEM, PG_VME16 | PG_COMMON, 0xFF000000 }, 748 1.31 riastrad { MAP_MBIO, PG_VME16 | PG_COMMON, 0xFFFF0000 }, 749 1.7 pk { MAP_VME16A16D, PG_VME16 | PG_COMMON, 0xFFFF0000 }, 750 1.7 pk { MAP_VME16A32D, PG_VME32 | PG_COMMON, 0xFFFF0000 }, 751 1.7 pk { MAP_VME24A16D, PG_VME16 | PG_COMMON, 0xFF000000 }, 752 1.7 pk { MAP_VME24A32D, PG_VME32 | PG_COMMON, 0xFF000000 }, 753 1.7 pk { MAP_VME32A16D, PG_VME16 | PG_COMMON, 0 }, 754 1.7 pk { MAP_VME32A32D, PG_VME32 | PG_COMMON, 0 }, 755 1.1 mrg }; 756 1.7 pk static int oldmon_mapinfo_cnt = 757 1.7 pk sizeof(oldmon_mapinfo) / sizeof(oldmon_mapinfo[0]); 758 1.1 mrg 759 1.1 mrg /* The virtual address we will use for PROM device mappings. */ 760 1.1 mrg static u_long prom_devmap = MONSHORTSEG; 761 1.1 mrg 762 1.1 mrg static char * 763 1.20 uwe oldmon_mapin(u_long physaddr, int length, int maptype) 764 1.1 mrg { 765 1.1 mrg int i, pa, pte, va; 766 1.1 mrg 767 1.1 mrg if (length > (4*NBPG)) 768 1.13 provos panic("oldmon_mapin: length=%d", length); 769 1.1 mrg 770 1.7 pk for (i = 0; i < oldmon_mapinfo_cnt; i++) 771 1.7 pk if (oldmon_mapinfo[i].maptype == maptype) 772 1.1 mrg goto found; 773 1.13 provos panic("oldmon_mapin: invalid maptype %d", maptype); 774 1.7 pk 775 1.1 mrg found: 776 1.7 pk pte = oldmon_mapinfo[i].pgtype; 777 1.7 pk pa = oldmon_mapinfo[i].base; 778 1.1 mrg pa += physaddr; 779 1.7 pk pte |= ((pa >> SUN4_PGSHIFT) & PG_PFNUM); 780 1.1 mrg 781 1.1 mrg va = prom_devmap; 782 1.1 mrg do { 783 1.6 pk setpte4(va, pte); 784 1.1 mrg va += NBPG; 785 1.1 mrg pte += 1; 786 1.1 mrg length -= NBPG; 787 1.1 mrg } while (length > 0); 788 1.31 riastrad return ((char *)(prom_devmap | (pa & PGOFSET))); 789 1.1 mrg } 790