191 lines · 4.1 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * read-only sd driver for BIOS devices with partitions. * will probably only work with bootstrap kernels, as the normal kernel * deals directly with the clock and disk controllers, which seems * to confuse many BIOSes. * * devbios must be initialised first and no disks may be accessed * via non-BIOS means. */ #include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"ureg.h"#include	"pool.h"#include	"../port/error.h"#include	"../port/netif.h"#include	"../port/sd.h"#include	"dosfs.h"#include	<disk.h> long	biosread0(Bootfs *, void *, long);vlong	biosseek(Bootfs *fs, vlong off); extern SDifc sdbiosifc;extern int biosndevs; uchar *putbeul(ulong ul, uchar *p){	*p++ = ul >> 24;	*p++ = ul >> 16;	*p++ = ul >> 8;	*p++ = ul;	return p;} uchar *putbeuvl(uvlong uvl, uchar *p){	*p++ = uvl >> 56;	*p++ = uvl >> 48;	*p++ = uvl >> 40;	*p++ = uvl >> 32;	*p++ = uvl >> 24;	*p++ = uvl >> 16;	*p++ = uvl >> 8;	*p++ = uvl;	return p;} intbiosverify(SDunit* ){	if (!biosinited)		return 0;	return 1;} intbiosonline(SDunit* unit){	uint subno = unit->subno; 	if (!biosinited)		panic("sdbios: biosonline: sdbios not inited");	if (unit == nil)		return 0;	unit->secsize = biossectsz(subno);	if (unit->secsize <= 0) {		print("sdbios: biosonline: implausible sector size on medium\n");		return 0;	}	unit->sectors = biossize(subno);	if (unit->sectors <= 0) {		unit->sectors = 0;		print("sdbios: biosonline: no sectors on medium\n");		return 0;	}	return 1;} static intbiosrio(SDreq* r){	int nb;	long got;	vlong off;	uchar *p;	Bootfs fs;			/* just for fs->dev, which is zero */	SDunit *unit; 	if (!biosinited)		return SDeio;	unit = r->unit;	/*	 * Most SCSI commands can be passed unchanged except for	 * the padding on the end. The few which require munging	 * are not used internally. Mode select/sense(6) could be	 * converted to the 10-byte form but it's not worth the	 * effort. Read/write(6) are easy.	 */	r->rlen = 0;	r->status = SDok;	switch(r->cmd[0]){	case ScmdRead:	case ScmdExtread:		if (r->cmd[0] == ScmdRead)			panic("biosrio: ScmdRead read op");		off = r->cmd[2]<<24 | r->cmd[3]<<16 | r->cmd[4]<<8 | r->cmd[5];		nb =  r->cmd[7]<<8  | r->cmd[8];	/* often 4 */		USED(nb);		/* is nb*unit->secsize == r->dlen? */		memset(&fs, 0, sizeof fs);		biosseek(&fs, off * unit->secsize);		got = biosread0(&fs, r->data, r->dlen);		if (got < 0)			r->status = SDeio;		else			r->rlen = got;		break;	case ScmdWrite:	case ScmdExtwrite:		r->status = SDeio;	/* boot programs don't write */		break; 		/*		 * Read capacity returns the LBA of the last sector.		 */	case ScmdRcapacity:		p = putbeul(r->unit->sectors - 1, r->data);		r->data = putbeul(r->unit->secsize, p);		return SDok;	case ScmdRcapacity16:		p = putbeuvl(r->unit->sectors - 1, r->data);		r->data = putbeul(r->unit->secsize, p);		return SDok;	/* ignore others */	}	return r->status;} /* this is called between biosreset and biosinit */static SDev*biospnp(void){	SDev *sdev; 	if (!biosinited)		panic("sdbios: biospnp: bios devbios not yet inited");	if((sdev = malloc(sizeof(SDev))) != nil) {		sdev->ifc = &sdbiosifc;		sdev->idno = 'B';		sdev->nunit = biosndevs;		iprint("sdbios: biospnp: %d unit(s) at sd%C0\n",			sdev->nunit, sdev->idno);	}	return sdev;} SDifc sdbiosifc = {	"bios",				/* name */ 	biospnp,			/* pnp */	nil,				/* legacy */	nil,				/* enable */	nil,				/* disable */ 	biosverify,			/* verify */	biosonline,			/* online */	biosrio,			/* rio */	nil,				/* rctl */	nil,				/* wctl */ 	scsibio,			/* bio */	nil,				/* probe */	nil,				/* clear */	nil,				/* rtopctl */	nil,				/* wtopctl */};