1 /*
2 * read-only sd driver for BIOS devices with partitions.
3 * will probably only work with bootstrap kernels, as the normal kernel
4 * deals directly with the clock and disk controllers, which seems
5 * to confuse many BIOSes.
6 *
7 * devbios must be initialised first and no disks may be accessed
8 * via non-BIOS means.
9 */
10
11 #include "u.h"
12 #include "../port/lib.h"
13 #include "mem.h"
14 #include "dat.h"
15 #include "fns.h"
16 #include "io.h"
17 #include "ureg.h"
18 #include "pool.h"
19 #include "../port/error.h"
20 #include "../port/netif.h"
21 #include "../port/sd.h"
22 #include "dosfs.h"
23
24 long biosread0(Bootfs *, void *, long);
25 vlong biosseek(Bootfs *fs, vlong off);
26
27 extern SDifc sdbiosifc;
28 extern int biosndevs;
29
30 uchar *
putbeul(ulong ul,uchar * p)31 putbeul(ulong ul, uchar *p)
32 {
33 *p++ = ul >> 24;
34 *p++ = ul >> 16;
35 *p++ = ul >> 8;
36 *p++ = ul;
37 return p;
38 }
39
40 uchar *
putbeuvl(uvlong uvl,uchar * p)41 putbeuvl(uvlong uvl, uchar *p)
42 {
43 *p++ = uvl >> 56;
44 *p++ = uvl >> 48;
45 *p++ = uvl >> 40;
46 *p++ = uvl >> 32;
47 *p++ = uvl >> 24;
48 *p++ = uvl >> 16;
49 *p++ = uvl >> 8;
50 *p++ = uvl;
51 return p;
52 }
53
54 int
biosverify(SDunit *)55 biosverify(SDunit* )
56 {
57 if (!biosinited)
58 return 0;
59 return 1;
60 }
61
62 int
biosonline(SDunit * unit)63 biosonline(SDunit* unit)
64 {
65 uint subno = unit->subno;
66
67 if (!biosinited)
68 panic("sdbios: biosonline: sdbios not inited");
69 if (unit == nil)
70 return 0;
71 unit->secsize = biossectsz(subno);
72 if (unit->secsize <= 0) {
73 print("sdbios: biosonline: implausible sector size on medium\n");
74 return 0;
75 }
76 unit->sectors = biossize(subno);
77 if (unit->sectors <= 0) {
78 unit->sectors = 0;
79 print("sdbios: biosonline: no sectors on medium\n");
80 return 0;
81 }
82 return 1;
83 }
84
85 static int
biosrio(SDreq * r)86 biosrio(SDreq* r)
87 {
88 int nb;
89 long got;
90 vlong off;
91 uchar *p;
92 Bootfs fs; /* just for fs->dev, which is zero */
93 SDunit *unit;
94
95 if (!biosinited)
96 return SDeio;
97 unit = r->unit;
98 /*
99 * Most SCSI commands can be passed unchanged except for
100 * the padding on the end. The few which require munging
101 * are not used internally. Mode select/sense(6) could be
102 * converted to the 10-byte form but it's not worth the
103 * effort. Read/write(6) are easy.
104 */
105 r->rlen = 0;
106 r->status = SDok;
107 switch(r->cmd[0]){
108 case ScmdRead:
109 case ScmdExtread:
110 if (r->cmd[0] == ScmdRead)
111 panic("biosrio: ScmdRead read op");
112 off = r->cmd[2]<<24 | r->cmd[3]<<16 | r->cmd[4]<<8 | r->cmd[5];
113 nb = r->cmd[7]<<8 | r->cmd[8]; /* often 4 */
114 USED(nb); /* is nb*unit->secsize == r->dlen? */
115 memset(&fs, 0, sizeof fs);
116 biosseek(&fs, off * unit->secsize);
117 got = biosread0(&fs, r->data, r->dlen);
118 if (got < 0)
119 r->status = SDeio;
120 else
121 r->rlen = got;
122 break;
123 case ScmdWrite:
124 case ScmdExtwrite:
125 r->status = SDeio; /* boot programs don't write */
126 break;
127
128 /*
129 * Read capacity returns the LBA of the last sector.
130 */
131 case ScmdRcapacity:
132 p = putbeul(r->unit->sectors - 1, r->data);
133 r->data = putbeul(r->unit->secsize, p);
134 return SDok;
135 case ScmdRcapacity16:
136 p = putbeuvl(r->unit->sectors - 1, r->data);
137 r->data = putbeul(r->unit->secsize, p);
138 return SDok;
139 /* ignore others */
140 }
141 return r->status;
142 }
143
144 /* this is called between biosreset and biosinit */
145 static SDev*
biospnp(void)146 biospnp(void)
147 {
148 SDev *sdev;
149
150 if (!biosinited)
151 panic("sdbios: biospnp: bios devbios not yet inited");
152 if((sdev = malloc(sizeof(SDev))) != nil) {
153 sdev->ifc = &sdbiosifc;
154 sdev->idno = 'B';
155 sdev->nunit = biosndevs;
156 iprint("sdbios: biospnp: %d unit(s) at sd%C0\n",
157 sdev->nunit, sdev->idno);
158 }
159 return sdev;
160 }
161
162 SDifc sdbiosifc = {
163 "bios", /* name */
164
165 biospnp, /* pnp */
166 nil, /* legacy */
167 nil, /* enable */
168 nil, /* disable */
169
170 biosverify, /* verify */
171 biosonline, /* online */
172 biosrio, /* rio */
173 nil, /* rctl */
174 nil, /* wctl */
175
176 scsibio, /* bio */
177 nil, /* probe */
178 nil, /* clear */
179 nil, /* rtopctl */
180 nil, /* wtopctl */
181 };
182