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