1 /*
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell.
7 *
8 * %sccs.include.redist.c%
9 *
10 * @(#)rz.c 8.1 (Berkeley) 06/10/93
11 */
12
13 #include <stand/stand.h>
14 #include <sys/param.h>
15 #include <sys/disklabel.h>
16
17 struct rz_softc {
18 int sc_fd; /* PROM file id */
19 int sc_ctlr; /* controller number */
20 int sc_unit; /* disk unit number */
21 int sc_part; /* disk partition number */
22 struct disklabel sc_label; /* disk label for this disk */
23 };
24
25 int
rzstrategy(devdata,rw,bn,reqcnt,addr,cnt)26 rzstrategy(devdata, rw, bn, reqcnt, addr, cnt)
27 void *devdata;
28 int rw;
29 daddr_t bn;
30 u_int reqcnt;
31 char *addr;
32 u_int *cnt; /* out: number of bytes transfered */
33 {
34 register struct rz_softc *sc = (struct rz_softc *)devdata;
35 register int part = sc->sc_part;
36 register struct partition *pp = &sc->sc_label.d_partitions[part];
37 register int s;
38 long offset;
39
40 offset = bn * DEV_BSIZE;
41 /*
42 * Partial-block transfers not handled.
43 */
44 if (reqcnt & (DEV_BSIZE - 1)) {
45 *cnt = 0;
46 return (EINVAL);
47 }
48
49 offset += pp->p_offset * DEV_BSIZE;
50 if (prom_lseek(sc->sc_fd, offset, 0) < 0)
51 return (EIO);
52 s = prom_read(sc->sc_fd, addr, reqcnt);
53 if (s < 0)
54 return (EIO);
55
56 *cnt = s;
57 return (0);
58 }
59
60 int
rzopen(f,ctlr,unit,part)61 rzopen(f, ctlr, unit, part)
62 struct open_file *f;
63 int ctlr, unit, part;
64 {
65 register struct rz_softc *sc;
66 register struct disklabel *lp;
67 register int i;
68 char *msg;
69 char buf[DEV_BSIZE];
70 int cnt;
71 static char device[] = "rz(0,0,0)";
72
73 if (unit >= 8 || part >= 8)
74 return (ENXIO);
75 device[5] = '0' + unit;
76 /* NOTE: only support reads for now */
77 if ((i = prom_open(device, 0)) < 0)
78 return (ENXIO);
79
80 sc = alloc(sizeof(struct rz_softc));
81 bzero(sc, sizeof(struct rz_softc));
82 f->f_devdata = (void *)sc;
83
84 sc->sc_fd = i;
85 sc->sc_ctlr = ctlr;
86 sc->sc_unit = unit;
87 sc->sc_part = part;
88
89 /* try to read disk label and partition table information */
90 lp = &sc->sc_label;
91 lp->d_secsize = DEV_BSIZE;
92 lp->d_secpercyl = 1;
93 lp->d_npartitions = MAXPARTITIONS;
94 lp->d_partitions[part].p_offset = 0;
95 lp->d_partitions[part].p_size = 0x7fffffff;
96 i = rzstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt);
97 if (i || cnt != DEV_BSIZE) {
98 printf("rz%d: error reading disk label\n", unit);
99 goto bad;
100 } else {
101 msg = getdisklabel(buf, lp);
102 if (msg) {
103 printf("rz%d: %s\n", unit, msg);
104 goto bad;
105 }
106 }
107
108 if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) {
109 bad:
110 free(sc, sizeof(struct rz_softc));
111 return (ENXIO);
112 }
113 return (0);
114 }
115
116 rzclose(f)
117 struct open_file *f;
118 {
119 free(f->f_devdata, sizeof(struct rz_softc));
120 f->f_devdata = (void *)0;
121 return (0);
122 }
123