xref: /inferno-os/os/boot/pc/sdbios.c (revision 8a8c2d742b51525f66c2210e3c8a251de10022ff)
1*8a8c2d74SCharles.Forsyth /*
2*8a8c2d74SCharles.Forsyth  * boot driver for BIOS devices with partitions
3*8a8c2d74SCharles.Forsyth  * devbios must be called first
4*8a8c2d74SCharles.Forsyth  */
5*8a8c2d74SCharles.Forsyth #include "u.h"
6*8a8c2d74SCharles.Forsyth #include "lib.h"
7*8a8c2d74SCharles.Forsyth #include "mem.h"
8*8a8c2d74SCharles.Forsyth #include "dat.h"
9*8a8c2d74SCharles.Forsyth #include "fns.h"
10*8a8c2d74SCharles.Forsyth #include "io.h"
11*8a8c2d74SCharles.Forsyth #include "ureg.h"
12*8a8c2d74SCharles.Forsyth #include "error.h"
13*8a8c2d74SCharles.Forsyth 
14*8a8c2d74SCharles.Forsyth #include "sd.h"
15*8a8c2d74SCharles.Forsyth #include "fs.h"
16*8a8c2d74SCharles.Forsyth 
17*8a8c2d74SCharles.Forsyth long	biosread(Fs *, void *, long);
18*8a8c2d74SCharles.Forsyth vlong	biosseek(Fs *fs, vlong off);
19*8a8c2d74SCharles.Forsyth 
20*8a8c2d74SCharles.Forsyth extern SDifc sdbiosifc;
21*8a8c2d74SCharles.Forsyth extern int onlybios0, biosinited;
22*8a8c2d74SCharles.Forsyth 
23*8a8c2d74SCharles.Forsyth int
biosverify(SDunit *)24*8a8c2d74SCharles.Forsyth biosverify(SDunit* )
25*8a8c2d74SCharles.Forsyth {
26*8a8c2d74SCharles.Forsyth 	if (onlybios0 || !biosinited)
27*8a8c2d74SCharles.Forsyth 		return 0;
28*8a8c2d74SCharles.Forsyth 	return 1;
29*8a8c2d74SCharles.Forsyth }
30*8a8c2d74SCharles.Forsyth 
31*8a8c2d74SCharles.Forsyth int
biosonline(SDunit * unit)32*8a8c2d74SCharles.Forsyth biosonline(SDunit* unit)
33*8a8c2d74SCharles.Forsyth {
34*8a8c2d74SCharles.Forsyth 	if (onlybios0 || !biosinited || !unit)
35*8a8c2d74SCharles.Forsyth 		return 0;
36*8a8c2d74SCharles.Forsyth 	unit->sectors = 1UL << 30;	/* a bunch */
37*8a8c2d74SCharles.Forsyth 	unit->secsize = 512;		/* conventional */
38*8a8c2d74SCharles.Forsyth 	return 1;
39*8a8c2d74SCharles.Forsyth }
40*8a8c2d74SCharles.Forsyth 
41*8a8c2d74SCharles.Forsyth static int
biosrio(SDreq * r)42*8a8c2d74SCharles.Forsyth biosrio(SDreq* r)
43*8a8c2d74SCharles.Forsyth {
44*8a8c2d74SCharles.Forsyth 	int nb;
45*8a8c2d74SCharles.Forsyth 	long got;
46*8a8c2d74SCharles.Forsyth 	vlong len, off;
47*8a8c2d74SCharles.Forsyth 	uchar *p;
48*8a8c2d74SCharles.Forsyth 	Fs fs;			/* just for fs->dev, which is zero */
49*8a8c2d74SCharles.Forsyth 
50*8a8c2d74SCharles.Forsyth 	if (onlybios0 || !biosinited)
51*8a8c2d74SCharles.Forsyth 		return SDeio;
52*8a8c2d74SCharles.Forsyth 	/*
53*8a8c2d74SCharles.Forsyth 	 * Most SCSI commands can be passed unchanged except for
54*8a8c2d74SCharles.Forsyth 	 * the padding on the end. The few which require munging
55*8a8c2d74SCharles.Forsyth 	 * are not used internally. Mode select/sense(6) could be
56*8a8c2d74SCharles.Forsyth 	 * converted to the 10-byte form but it's not worth the
57*8a8c2d74SCharles.Forsyth 	 * effort. Read/write(6) are easy.
58*8a8c2d74SCharles.Forsyth 	 */
59*8a8c2d74SCharles.Forsyth 	r->rlen = 0;
60*8a8c2d74SCharles.Forsyth 	r->status = SDok;
61*8a8c2d74SCharles.Forsyth 	switch(r->cmd[0]){
62*8a8c2d74SCharles.Forsyth 	case 0x08:			/* read */
63*8a8c2d74SCharles.Forsyth 	case 0x28:			/* read */
64*8a8c2d74SCharles.Forsyth 		if (r->cmd[0] == 0x08)
65*8a8c2d74SCharles.Forsyth 			panic("biosrio: 0x08 read op\n");
66*8a8c2d74SCharles.Forsyth 		off = r->cmd[2]<<24 | r->cmd[3]<<16 | r->cmd[4]<<8 | r->cmd[5];
67*8a8c2d74SCharles.Forsyth 		nb = r->cmd[7]<<8 | r->cmd[8];	/* often 4 */
68*8a8c2d74SCharles.Forsyth 		USED(nb);		/* is nb*512 == r->dlen? */
69*8a8c2d74SCharles.Forsyth 		memset(&fs, 0, sizeof fs);
70*8a8c2d74SCharles.Forsyth 		biosseek(&fs, off*512);
71*8a8c2d74SCharles.Forsyth 		got = biosread(&fs, r->data, r->dlen);
72*8a8c2d74SCharles.Forsyth 		if (got < 0)
73*8a8c2d74SCharles.Forsyth 			r->status = SDeio;
74*8a8c2d74SCharles.Forsyth 		else
75*8a8c2d74SCharles.Forsyth 			r->rlen = got;
76*8a8c2d74SCharles.Forsyth 		break;
77*8a8c2d74SCharles.Forsyth 	case 0x0A:			/* write */
78*8a8c2d74SCharles.Forsyth 	case 0x2A:			/* write */
79*8a8c2d74SCharles.Forsyth 		r->status = SDeio;	/* boot programs don't write */
80*8a8c2d74SCharles.Forsyth 		break;
81*8a8c2d74SCharles.Forsyth 	case 0x25:			/* read capacity */
82*8a8c2d74SCharles.Forsyth 		/*
83*8a8c2d74SCharles.Forsyth 		 * Read capacity returns the LBA of the last sector.
84*8a8c2d74SCharles.Forsyth 		 */
85*8a8c2d74SCharles.Forsyth 		len = r->unit->sectors - 1;
86*8a8c2d74SCharles.Forsyth 		p = r->data;
87*8a8c2d74SCharles.Forsyth 		*p++ = len>>24;
88*8a8c2d74SCharles.Forsyth 		*p++ = len>>16;
89*8a8c2d74SCharles.Forsyth 		*p++ = len>>8;
90*8a8c2d74SCharles.Forsyth 		*p++ = len;
91*8a8c2d74SCharles.Forsyth 		len = r->unit->secsize;
92*8a8c2d74SCharles.Forsyth 		*p++ = len>>24;
93*8a8c2d74SCharles.Forsyth 		*p++ = len>>16;
94*8a8c2d74SCharles.Forsyth 		*p++ = len>>8;
95*8a8c2d74SCharles.Forsyth 		*p = len;
96*8a8c2d74SCharles.Forsyth 		r->data = (char *)r->data + 8;
97*8a8c2d74SCharles.Forsyth 		return SDok;
98*8a8c2d74SCharles.Forsyth 	case 0x9E:			/* long read capacity */
99*8a8c2d74SCharles.Forsyth 		/*
100*8a8c2d74SCharles.Forsyth 		 * Read capacity returns the LBA of the last sector.
101*8a8c2d74SCharles.Forsyth 		 */
102*8a8c2d74SCharles.Forsyth 		len = r->unit->sectors - 1;
103*8a8c2d74SCharles.Forsyth 		p = r->data;
104*8a8c2d74SCharles.Forsyth 		*p++ = len>>56;
105*8a8c2d74SCharles.Forsyth 		*p++ = len>>48;
106*8a8c2d74SCharles.Forsyth 		*p++ = len>>40;
107*8a8c2d74SCharles.Forsyth 		*p++ = len>>32;
108*8a8c2d74SCharles.Forsyth 		*p++ = len>>24;
109*8a8c2d74SCharles.Forsyth 		*p++ = len>>16;
110*8a8c2d74SCharles.Forsyth 		*p++ = len>>8;
111*8a8c2d74SCharles.Forsyth 		*p++ = len;
112*8a8c2d74SCharles.Forsyth 		len = r->unit->secsize;
113*8a8c2d74SCharles.Forsyth 		*p++ = len>>24;
114*8a8c2d74SCharles.Forsyth 		*p++ = len>>16;
115*8a8c2d74SCharles.Forsyth 		*p++ = len>>8;
116*8a8c2d74SCharles.Forsyth 		*p = len;
117*8a8c2d74SCharles.Forsyth 		r->data = (char *)r->data + 8;
118*8a8c2d74SCharles.Forsyth 		return SDok;
119*8a8c2d74SCharles.Forsyth 	/* ignore others */
120*8a8c2d74SCharles.Forsyth 	}
121*8a8c2d74SCharles.Forsyth 	return r->status;
122*8a8c2d74SCharles.Forsyth }
123*8a8c2d74SCharles.Forsyth 
124*8a8c2d74SCharles.Forsyth SDev*
biosid(SDev * sdev)125*8a8c2d74SCharles.Forsyth biosid(SDev* sdev)
126*8a8c2d74SCharles.Forsyth {
127*8a8c2d74SCharles.Forsyth 	for (; sdev; sdev = sdev->next)
128*8a8c2d74SCharles.Forsyth 		if (sdev->ifc == &sdbiosifc)
129*8a8c2d74SCharles.Forsyth 			sdev->idno = 'B';
130*8a8c2d74SCharles.Forsyth 	return sdev;
131*8a8c2d74SCharles.Forsyth }
132*8a8c2d74SCharles.Forsyth 
133*8a8c2d74SCharles.Forsyth static SDev*
biospnp(void)134*8a8c2d74SCharles.Forsyth biospnp(void)
135*8a8c2d74SCharles.Forsyth {
136*8a8c2d74SCharles.Forsyth 	SDev *sdev;
137*8a8c2d74SCharles.Forsyth 
138*8a8c2d74SCharles.Forsyth 	/* 9pxeload can't use bios int 13 calls; they wedge the machine */
139*8a8c2d74SCharles.Forsyth 	if (pxe || getconf("*nobiosload") != nil || onlybios0 || !biosinited)
140*8a8c2d74SCharles.Forsyth 		return nil;
141*8a8c2d74SCharles.Forsyth 	if((sdev = malloc(sizeof(SDev))) != nil) {
142*8a8c2d74SCharles.Forsyth 		sdev->ifc = &sdbiosifc;
143*8a8c2d74SCharles.Forsyth 		sdev->index = -1;
144*8a8c2d74SCharles.Forsyth 		sdev->nunit = 1;
145*8a8c2d74SCharles.Forsyth 	}
146*8a8c2d74SCharles.Forsyth 	return sdev;
147*8a8c2d74SCharles.Forsyth }
148*8a8c2d74SCharles.Forsyth 
149*8a8c2d74SCharles.Forsyth SDifc sdbiosifc = {
150*8a8c2d74SCharles.Forsyth 	"bios",				/* name */
151*8a8c2d74SCharles.Forsyth 
152*8a8c2d74SCharles.Forsyth 	biospnp,			/* pnp */
153*8a8c2d74SCharles.Forsyth 	nil,				/* legacy */
154*8a8c2d74SCharles.Forsyth 	biosid,				/* id */
155*8a8c2d74SCharles.Forsyth 	nil,				/* enable */
156*8a8c2d74SCharles.Forsyth 	nil,				/* disable */
157*8a8c2d74SCharles.Forsyth 
158*8a8c2d74SCharles.Forsyth 	biosverify,			/* verify */
159*8a8c2d74SCharles.Forsyth 	biosonline,			/* online */
160*8a8c2d74SCharles.Forsyth 	biosrio,			/* rio */
161*8a8c2d74SCharles.Forsyth 	nil,				/* rctl */
162*8a8c2d74SCharles.Forsyth 	nil,				/* wctl */
163*8a8c2d74SCharles.Forsyth 
164*8a8c2d74SCharles.Forsyth 	scsibio,			/* bio */
165*8a8c2d74SCharles.Forsyth };
166