Annotation of sys/arch/mvmeppc/stand/libsa/bugdev.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: bugdev.c,v 1.4 2006/10/12 12:14:17 krw Exp $ */
2:
3: /*
4: * Copyright (c) 1993 Paul Kranenburg
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Paul Kranenburg.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: #include <sys/param.h>
34: #include <sys/disklabel.h>
35: #include <machine/prom.h>
36:
37: #include <stand.h>
38: #include <ufs.h>
39: #include "rawfs.h"
40: #include "tftpfs.h"
41:
42: #include "libsa.h"
43:
44: int errno;
45: int bootdev_type = BUGDEV_DISK;
46:
47: #if 1
48: #define md_swap_long(x) ( (((x) >> 24) & 0xff) | (((x) >> 8 ) & 0xff00) | \
49: (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000))
50: #else
51: #define md_swap_long(x) (x)
52: #endif
53:
54: struct bugdev_softc {
55: int fd; /* Prom file descriptor */
56: u_int pnum; /* Partition number */
57: u_int poff; /* Partition offset */
58: u_int psize; /* Partition size */
59: short clun;
60: short dlun;
61: } bugdev_softc[1];
62:
63: extern struct fs_ops ufs_file_system;
64: extern struct fs_ops tftp_file_system;
65: extern struct fs_ops raw_file_system;
66:
67: struct fs_ops file_system[1];
68:
69: struct mvmeprom_dskio tape_ioreq;
70:
71: #ifdef BUG_DEBUG
72: unsigned io = 0, mem = 0;
73: #define PCI_BASE 0x80000000
74: #define CFC *(unsigned *)(PCI_BASE + 0xcfc)
75: #define CF8 *(unsigned *)(PCI_BASE + 0xcf8)
76: #define BUS_SHIFT 16
77: #define DEVICE_SHIFT 11
78: #define FNC_SHIFT 8
79:
80: unsigned
81: bugpci_make_tag(bus, dev, fnc)
82: int bus, dev, fnc;
83: {
84: return (bus << BUS_SHIFT) | (dev << DEVICE_SHIFT) | (fnc << FNC_SHIFT);
85: }
86:
87: static unsigned
88: bugpci_gen_config_reg(tag, offset)
89: unsigned tag;
90: int offset;
91: {
92: unsigned reg;
93:
94: /* config mechanism #2, type 0
95: /* standard cf8/cfc config */
96: reg = 0x80000000 | tag | offset;
97:
98: return reg;
99: }
100:
101: /*#define DEBUG_CONFIG */
102: unsigned
103: bugpci_conf_read(bus, dev, func, offset)
104: int bus, dev, func, offset;
105: {
106:
107: unsigned data;
108: unsigned reg, tag, xx;
109:
110: if(offset & 3 || offset < 0 || offset >= 0x100) {
111: printf ("bugpci_conf_read: bad reg %x\n", offset);
112: return(~0);
113: }
114:
115: tag = bugpci_make_tag(bus, dev, func);
116: reg = bugpci_gen_config_reg(tag, offset);
117: reg = md_swap_long(reg);
118: /* if invalid tag, return -1 */
119: if (reg == 0xffffffff) {
120: return 0xffffffff;
121: }
122:
123: CF8 = reg;
124: xx = CF8;
125: data = CFC;
126: data = md_swap_long(data);
127:
128: CF8 = 0;
129:
130: return(data);
131: }
132:
133: void
134: bugpci_conf_write(bus, dev, func, offset, data)
135: int bus, dev, func, offset;
136: unsigned data;
137: {
138: unsigned reg, tag, xx;
139:
140: tag = bugpci_make_tag(bus, dev, func);
141: reg = bugpci_gen_config_reg(tag, offset);
142: reg = md_swap_long(reg);
143:
144: /* if invalid tag, return ??? */
145: if (reg == 0xffffffff) {
146: return;
147: }
148:
149: CF8 = reg;
150: xx = CF8;
151: data = md_swap_long(data);
152: CFC = data;
153: CF8 = 0;
154: xx = CF8;
155: }
156: #endif
157:
158: static u_long
159: get_long(p)
160: const void *p;
161: {
162: const unsigned char *cp = p;
163:
164: return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
165: }
166:
167: /*
168: * Find a valid disklabel.
169: */
170: static int
171: search_label(devp, off, buf, lp, off0)
172: void *devp;
173: u_long off;
174: char *buf;
175: struct disklabel *lp;
176: u_long off0;
177: {
178: size_t read;
179: struct dos_partition *p;
180: int i;
181: u_long poff;
182: static int recursion;
183:
184: if (dsk_strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
185: || read != DEV_BSIZE)
186: return ERDLAB;
187:
188: if (buf[510] != 0x55 || buf[511] != 0xaa)
189: return ERDLAB;
190:
191: if (recursion++ <= 1)
192: off0 += off;
193: for (p = (struct dos_partition *)(buf + DOSPARTOFF), i = 4;
194: --i >= 0; p++) {
195: if (p->dp_typ == DOSPTYP_OPENBSD) {
196: poff = get_long(&p->dp_start) + off0;
197: if (dsk_strategy(devp, F_READ, poff + LABELSECTOR,
198: DEV_BSIZE, buf, &read) == 0
199: && read == DEV_BSIZE) {
200: if (!getdisklabel(buf, lp)) {
201: recursion--;
202: return 0;
203: }
204: }
205: if (dsk_strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
206: || read != DEV_BSIZE) {
207: recursion--;
208: return ERDLAB;
209: }
210: } else if (p->dp_typ == DOSPTYP_EXTEND) {
211: poff = get_long(&p->dp_start);
212: if (!search_label(devp, poff, buf, lp, off0)) {
213: recursion--;
214: return 0;
215: }
216: if (dsk_strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
217: || read != DEV_BSIZE) {
218: recursion--;
219: return ERDLAB;
220: }
221: }
222: }
223: recursion--;
224: return ERDLAB;
225: }
226:
227: int dsk_read_disklabel(devp)
228: void *devp;
229: {
230: static char iobuf[MAXBSIZE];
231: struct disklabel label;
232: int error = 0;
233: int i;
234:
235: register struct bugdev_softc *pp = (struct bugdev_softc *)devp;
236:
237: #ifdef DEBUG
238: printf("dsk_open:\n");
239: #endif
240: /* First try to find a disklabel without MBR partitions */
241: if (dsk_strategy(pp, F_READ, LABELSECTOR, DEV_BSIZE, iobuf, &i) != 0
242: || i != DEV_BSIZE
243: || getdisklabel(iobuf, &label)) {
244: /* Else try MBR partitions */
245: error = search_label(pp, 0, iobuf, &label, 0);
246: if (error && error != ERDLAB)
247: return (error);
248: }
249: if (error == ERDLAB) {
250: if (pp->pnum)
251: /* User specified a partition, but there is none */
252: return (error);
253: /* No, label, just use complete disk */
254: pp->poff = 0;
255: } else {
256: pp->poff = label.d_partitions[pp->pnum].p_offset;
257: pp->psize = label.d_partitions[pp->pnum].p_size;
258: }
259: return(0);
260: }
261:
262:
263: int
264: devopen(f, fname, file)
265: struct open_file *f;
266: const char *fname;
267: char **file;
268: {
269: register struct bugdev_softc *pp = &bugdev_softc[0];
270: int error;
271: char *dev, *cp;
272:
273: pp->clun = (short)bugargs.ctrl_lun;
274: pp->dlun = (short)bugargs.dev_lun;
275: pp->poff = 0;
276: pp->psize = 0;
277: pp->fd = 0;
278: pp->pnum = 0;
279:
280: f->f_devdata = (void *)pp;
281:
282: switch (bootdev_type) {
283: case BUGDEV_DISK:
284: dev = bugargs.arg_start;
285: /*
286: * Extract partition # from boot device string.
287: */
288: for (cp = dev; *cp; cp++) /* void */;
289: while (*cp != '/' && cp > dev) {
290: if (*cp == ':')
291: pp->pnum = *(cp+1) - 'a';
292: --cp;
293: }
294:
295: error = dsk_read_disklabel(pp);
296: if (error)
297: return(error);
298:
299: bcopy(&ufs_file_system, file_system, sizeof file_system[0]);
300: break;
301:
302: case BUGDEV_NET:
303: bcopy(&tftp_file_system, file_system, sizeof file_system[0]);
304: break;
305:
306: case BUGDEV_TAPE:
307: bcopy(&raw_file_system, file_system, sizeof file_system[0]);
308: break;
309: }
310:
311: f->f_dev = &devsw[bootdev_type];
312: nfsys = 1;
313: *file = (char *)fname;
314: return (0);
315: }
316:
317: /* silly block scale factor */
318: #define BUG_BLOCK_SIZE 256
319: #define BUG_SCALE (512/BUG_BLOCK_SIZE)
320: int
321: dsk_strategy(devdata, func, dblk, size, buf, rsize)
322: void *devdata;
323: int func;
324: daddr_t dblk;
325: size_t size;
326: void *buf;
327: size_t *rsize;
328: {
329: struct mvmeprom_dskio dio;
330: register struct bugdev_softc *pp = (struct bugdev_softc *)devdata;
331: daddr_t blk = dblk + pp->poff;
332:
333: twiddle();
334:
335: dio.ctrl_lun = pp->clun;
336: dio.dev_lun = pp->dlun;
337: dio.status = 0;
338: dio.pbuffer = buf;
339: dio.blk_num = blk * BUG_SCALE;
340: dio.blk_cnt = size / BUG_BLOCK_SIZE; /* assumed size in bytes */
341: dio.flag = 0;
342: dio.addr_mod = 0;
343: #ifdef DEBUG
344: printf("dsk_strategy: size=%d blk=%d buf=%x\n", size, blk, buf);
345: printf("ctrl %d dev %d\n", dio.ctrl_lun, dio.dev_lun);
346: #endif
347: mvmeprom_diskrd(&dio);
348:
349: *rsize = dio.blk_cnt * BUG_BLOCK_SIZE;
350: #ifdef DEBUG
351: printf("rsize %d status %x\n", *rsize, dio.status);
352: #endif
353:
354: if (dio.status)
355: return (EIO);
356: return (0);
357: }
358:
359: int
360: dsk_open(f)
361: struct open_file *f;
362: {
363: #ifdef DEBUG
364: register struct bugdev_softc *pp = (struct bugdev_softc *)f->f_devdata;
365: printf("dsk_open:\n");
366: printf("using mvmebug ctrl %d dev %d\n",
367: pp->clun, pp->dlun);
368: #endif
369: return (0);
370: }
371:
372: int
373: dsk_close(f)
374: struct open_file *f;
375: {
376: return (EIO);
377: }
378:
379: int
380: dsk_ioctl(f, cmd, data)
381: struct open_file *f;
382: u_long cmd;
383: void *data;
384: {
385: return (EIO);
386: }
387:
388: #define NFR_TIMEOUT 5
389: /* netboot stuff */
390: int
391: net_strategy(devdata, func, nblk, size, buf, rsize)
392: void *devdata;
393: int func;
394: daddr_t nblk;
395: size_t size;
396: void *buf;
397: size_t *rsize;
398: {
399: int attempts = 0;
400: struct mvmeprom_netfread nfr;
401: register struct bugdev_softc *pp = (struct bugdev_softc *)devdata;
402:
403: retry:
404:
405: attempts+=1;
406:
407: nfr.clun = pp->clun;
408: nfr.dlun = pp->dlun;
409: nfr.status = 0;
410: nfr.addr = buf;
411: nfr.bytes = 0;
412: nfr.blk = nblk;
413: nfr.timeout = NFR_TIMEOUT;
414: #ifdef DEBUG
415: printf("net_strategy: size=%d blk=%d buf=%x\n", size, nblk, buf);
416: printf("ctrl %d dev %d\n", nfr.clun, nfr.dlun);
417: #endif
418: mvmeprom_netfread(&nfr);
419:
420: #ifdef BUG_DEBUG
421: io = bugpci_conf_read(0, 14, 0, 0x10) & ~0xf;
422: mem = bugpci_conf_read(0, 14, 0, 0x14) & ~0xf;
423:
424: printf(" IO @ %x\n", io);
425: printf("MEM @ %x\n", mem);
426:
427: #define PRINT_REG(regname, x) printf("%s = 0x%x\n", regname, \
428: md_swap_long(*(unsigned *)(io + x)))
429:
430: PRINT_REG("CSR0", 0x00);
431: PRINT_REG("CSR1", 0x08);
432: PRINT_REG("CSR2", 0x10);
433: PRINT_REG("CSR3", 0x18);
434: PRINT_REG("CSR4", 0x20);
435: PRINT_REG("CSR5", 0x28);
436: PRINT_REG("CSR6", 0x30);
437: PRINT_REG("CSR7", 0x38);
438: PRINT_REG("CSR8", 0x40);
439: PRINT_REG("CSR9", 0x48);
440: PRINT_REG("CSR10", 0x50);
441: PRINT_REG("CSR11", 0x58);
442: PRINT_REG("CSR12", 0x60);
443: PRINT_REG("CSR13", 0x68);
444: PRINT_REG("CSR14", 0x70);
445: PRINT_REG("CSR15", 0x78);
446: #endif
447: if (rsize) {
448: *rsize = nfr.bytes;
449: }
450: #ifdef DEBUG
451: printf("rsize %d status %x\n", *rsize, nfr.status);
452: #endif
453:
454: if (nfr.status)
455: if (attempts < 10)
456: goto retry;
457: else
458: return (EIO);
459: return (0);
460: }
461:
462: int
463: net_open(struct open_file *f, ...)
464: {
465: va_list ap;
466: struct mvmeprom_netfopen nfo;
467: register struct bugdev_softc *pp = (struct bugdev_softc *)f->f_devdata;
468: char *filename;
469: short nfoerr = 0;
470: va_start(ap, f);
471: filename = va_arg(ap, char *);
472: va_end(ap);
473:
474: #ifdef DEBUG
475: printf("net_open: using mvmebug ctrl %d dev %d, filename: %s\n",
476: pp->clun, pp->dlun, filename);
477: #endif
478: nfo.clun = pp->clun;
479: nfo.dlun = pp->dlun;
480: nfo.status = 0;
481: strlcpy(nfo.filename, filename, sizeof nfo.filename);
482: /* .NETFOPN syscall */
483: mvmeprom_netfopen(&nfo);
484:
485: #ifdef DEBUG
486: if (nfo.status) {
487: nfoerr = nfo.status;
488: printf("net_open: ci err = 0x%x, cd err = 0x%x\n",
489: ((nfoerr >> 8) & 0x0F), (nfoerr & 0x0F));
490: }
491: #endif
492: return (nfo.status);
493: }
494:
495: int
496: net_close(f)
497: struct open_file *f;
498: {
499: return (EIO);
500: }
501:
502: int
503: net_ioctl(f, cmd, data)
504: struct open_file *f;
505: u_long cmd;
506: void *data;
507: {
508: return (EIO);
509: }
510:
511: int
512: tape_open(struct open_file *f, ...)
513: {
514: va_list ap;
515: int error = 0;
516: int part;
517: struct mvmeprom_dskio *ti;
518: char *fname; /* partition number, i.e. "1" */
519:
520: va_start(ap, f);
521: fname = va_arg(ap, char *);
522: va_end(ap);
523:
524: /*
525: * Set the tape segment number to the one indicated
526: * by the single digit fname passed in above.
527: */
528: if ((fname[0] < '0') && (fname[0] > '9')) {
529: return ENOENT;
530: }
531: part = fname[0] - '0';
532: fname = NULL;
533:
534: /*
535: * Setup our part of the saioreq.
536: * (determines what gets opened)
537: */
538: ti = &tape_ioreq;
539: bzero((caddr_t)ti, sizeof(*ti));
540:
541: ti->ctrl_lun = bugargs.ctrl_lun;
542: ti->dev_lun = bugargs.dev_lun;
543: ti->status = 0;
544: ti->pbuffer = NULL;
545: ti->blk_num = part;
546: ti->blk_cnt = 0;
547: ti->flag = 0;
548: ti->addr_mod = 0;
549:
550: f->f_devdata = ti;
551:
552: return (0);
553: }
554:
555: int
556: tape_close(f)
557: struct open_file *f;
558: {
559: struct mvmeprom_dskio *ti;
560:
561:
562: ti = f->f_devdata;
563: f->f_devdata = NULL;
564: return 0;
565: }
566:
567: #define MVMEPROM_SCALE (512/MVMEPROM_BLOCK_SIZE)
568:
569: int
570: tape_strategy(devdata, flag, dblk, size, buf, rsize)
571: void *devdata;
572: int flag;
573: daddr_t dblk;
574: size_t size;
575: void *buf;
576: size_t *rsize;
577: {
578: struct mvmeprom_dskio *ti;
579: int ret;
580:
581: ti = devdata;
582:
583: if (flag != F_READ)
584: return(EROFS);
585:
586: ti->status = 0;
587: ti->pbuffer = buf;
588: /* don't change block #, set in open */
589: ti->blk_cnt = size / (512 / MVMEPROM_SCALE);
590:
591: ret = mvmeprom_diskrd(ti);
592:
593: if (ret != 0)
594: return (EIO);
595:
596: *rsize = (ti->blk_cnt / MVMEPROM_SCALE) * 512;
597: ti->flag |= IGNORE_FILENUM; /* ignore next time */
598:
599: return (0);
600: }
601:
602: int
603: tape_ioctl(f, cmd, data)
604: struct open_file *f;
605: u_long cmd;
606: void *data;
607: {
608: return EIO;
609: }
610:
611:
CVSweb