/* * 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 */};
/*
* 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;
}
int
biosverify(SDunit* )
{
if (!biosinited)
return 0;
return 1;
}
int
biosonline(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 int
biosrio(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 */
};