174a4d8c2SCharles.Forsyth /*
274a4d8c2SCharles.Forsyth * Storage Device.
374a4d8c2SCharles.Forsyth */
474a4d8c2SCharles.Forsyth #include "u.h"
574a4d8c2SCharles.Forsyth #include "mem.h"
674a4d8c2SCharles.Forsyth #include "lib.h"
774a4d8c2SCharles.Forsyth #include "dat.h"
874a4d8c2SCharles.Forsyth #include "fns.h"
974a4d8c2SCharles.Forsyth #include "io.h"
1074a4d8c2SCharles.Forsyth #include "ureg.h"
1174a4d8c2SCharles.Forsyth #include "error.h"
1274a4d8c2SCharles.Forsyth
1374a4d8c2SCharles.Forsyth #include "sd.h"
1474a4d8c2SCharles.Forsyth #include "fs.h"
1574a4d8c2SCharles.Forsyth
1674a4d8c2SCharles.Forsyth #define parttrace 0
1774a4d8c2SCharles.Forsyth
1874a4d8c2SCharles.Forsyth
1974a4d8c2SCharles.Forsyth extern SDifc* sdifc[];
2074a4d8c2SCharles.Forsyth
2174a4d8c2SCharles.Forsyth static SDev* sdlist;
2274a4d8c2SCharles.Forsyth static SDunit** sdunit;
2374a4d8c2SCharles.Forsyth static int sdnunit;
2474a4d8c2SCharles.Forsyth static int _sdmask;
2574a4d8c2SCharles.Forsyth static int cdmask;
2674a4d8c2SCharles.Forsyth static int sdmask;
2774a4d8c2SCharles.Forsyth
2874a4d8c2SCharles.Forsyth enum {
2974a4d8c2SCharles.Forsyth Rawcmd,
3074a4d8c2SCharles.Forsyth Rawdata,
3174a4d8c2SCharles.Forsyth Rawstatus,
3274a4d8c2SCharles.Forsyth };
3374a4d8c2SCharles.Forsyth
3474a4d8c2SCharles.Forsyth void
sdaddpart(SDunit * unit,char * name,uvlong start,uvlong end)35*8a8c2d74SCharles.Forsyth sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end)
3674a4d8c2SCharles.Forsyth {
3774a4d8c2SCharles.Forsyth SDpart *pp;
3874a4d8c2SCharles.Forsyth int i, partno;
3974a4d8c2SCharles.Forsyth
4074a4d8c2SCharles.Forsyth if(parttrace)
41*8a8c2d74SCharles.Forsyth print("add %d %s %s %lld %lld\n", unit->npart, unit->name, name, start, end);
4274a4d8c2SCharles.Forsyth /*
4374a4d8c2SCharles.Forsyth * Check name not already used
4474a4d8c2SCharles.Forsyth * and look for a free slot.
4574a4d8c2SCharles.Forsyth */
4674a4d8c2SCharles.Forsyth if(unit->part != nil){
4774a4d8c2SCharles.Forsyth partno = -1;
4874a4d8c2SCharles.Forsyth for(i = 0; i < SDnpart; i++){
4974a4d8c2SCharles.Forsyth pp = &unit->part[i];
5074a4d8c2SCharles.Forsyth if(!pp->valid){
5174a4d8c2SCharles.Forsyth if(partno == -1)
5274a4d8c2SCharles.Forsyth partno = i;
5374a4d8c2SCharles.Forsyth break;
5474a4d8c2SCharles.Forsyth }
5574a4d8c2SCharles.Forsyth if(strcmp(name, pp->name) == 0){
5674a4d8c2SCharles.Forsyth if(pp->start == start && pp->end == end){
5774a4d8c2SCharles.Forsyth if(parttrace)
5874a4d8c2SCharles.Forsyth print("already present\n");
5974a4d8c2SCharles.Forsyth return;
6074a4d8c2SCharles.Forsyth }
6174a4d8c2SCharles.Forsyth }
6274a4d8c2SCharles.Forsyth }
6374a4d8c2SCharles.Forsyth }else{
6474a4d8c2SCharles.Forsyth if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil){
6574a4d8c2SCharles.Forsyth if(parttrace)
6674a4d8c2SCharles.Forsyth print("malloc failed\n");
6774a4d8c2SCharles.Forsyth return;
6874a4d8c2SCharles.Forsyth }
6974a4d8c2SCharles.Forsyth partno = 0;
7074a4d8c2SCharles.Forsyth }
7174a4d8c2SCharles.Forsyth
7274a4d8c2SCharles.Forsyth /*
7374a4d8c2SCharles.Forsyth * Check there is a free slot and size and extent are valid.
7474a4d8c2SCharles.Forsyth */
7574a4d8c2SCharles.Forsyth if(partno == -1 || start > end || end > unit->sectors){
76*8a8c2d74SCharles.Forsyth print("cannot add %s!%s [%llud,%llud) to disk [0,%llud): %s\n",
7774a4d8c2SCharles.Forsyth unit->name, name, start, end, unit->sectors,
7874a4d8c2SCharles.Forsyth partno==-1 ? "no free partitions" : "partition boundaries out of range");
7974a4d8c2SCharles.Forsyth return;
8074a4d8c2SCharles.Forsyth }
8174a4d8c2SCharles.Forsyth pp = &unit->part[partno];
8274a4d8c2SCharles.Forsyth pp->start = start;
8374a4d8c2SCharles.Forsyth pp->end = end;
8474a4d8c2SCharles.Forsyth strncpy(pp->name, name, NAMELEN);
8574a4d8c2SCharles.Forsyth pp->valid = 1;
8674a4d8c2SCharles.Forsyth unit->npart++;
8774a4d8c2SCharles.Forsyth }
8874a4d8c2SCharles.Forsyth
8974a4d8c2SCharles.Forsyth void
sddelpart(SDunit * unit,char * name)9074a4d8c2SCharles.Forsyth sddelpart(SDunit* unit, char* name)
9174a4d8c2SCharles.Forsyth {
9274a4d8c2SCharles.Forsyth int i;
9374a4d8c2SCharles.Forsyth SDpart *pp;
9474a4d8c2SCharles.Forsyth
9574a4d8c2SCharles.Forsyth if(parttrace)
9674a4d8c2SCharles.Forsyth print("del %d %s %s\n", unit->npart, unit->name, name);
9774a4d8c2SCharles.Forsyth /*
9874a4d8c2SCharles.Forsyth * Look for the partition to delete.
9974a4d8c2SCharles.Forsyth * Can't delete if someone still has it open.
10074a4d8c2SCharles.Forsyth * If it's the last valid partition zap the
10174a4d8c2SCharles.Forsyth * whole table.
10274a4d8c2SCharles.Forsyth */
10374a4d8c2SCharles.Forsyth pp = unit->part;
10474a4d8c2SCharles.Forsyth for(i = 0; i < SDnpart; i++){
10574a4d8c2SCharles.Forsyth if(strncmp(name, pp->name, NAMELEN) == 0)
10674a4d8c2SCharles.Forsyth break;
10774a4d8c2SCharles.Forsyth pp++;
10874a4d8c2SCharles.Forsyth }
10974a4d8c2SCharles.Forsyth if(i >= SDnpart)
11074a4d8c2SCharles.Forsyth return;
11174a4d8c2SCharles.Forsyth pp->valid = 0;
11274a4d8c2SCharles.Forsyth
11374a4d8c2SCharles.Forsyth unit->npart--;
11474a4d8c2SCharles.Forsyth if(unit->npart == 0){
11574a4d8c2SCharles.Forsyth free(unit->part);
11674a4d8c2SCharles.Forsyth unit->part = nil;
11774a4d8c2SCharles.Forsyth }
11874a4d8c2SCharles.Forsyth }
11974a4d8c2SCharles.Forsyth
12074a4d8c2SCharles.Forsyth static int
sdinitpart(SDunit * unit)12174a4d8c2SCharles.Forsyth sdinitpart(SDunit* unit)
12274a4d8c2SCharles.Forsyth {
12374a4d8c2SCharles.Forsyth unit->sectors = unit->secsize = 0;
12474a4d8c2SCharles.Forsyth unit->npart = 0;
12574a4d8c2SCharles.Forsyth if(unit->part){
12674a4d8c2SCharles.Forsyth free(unit->part);
12774a4d8c2SCharles.Forsyth unit->part = nil;
12874a4d8c2SCharles.Forsyth }
12974a4d8c2SCharles.Forsyth
13074a4d8c2SCharles.Forsyth if(unit->inquiry[0] & 0xC0)
13174a4d8c2SCharles.Forsyth return 0;
13274a4d8c2SCharles.Forsyth switch(unit->inquiry[0] & 0x1F){
13374a4d8c2SCharles.Forsyth case 0x00: /* DA */
13474a4d8c2SCharles.Forsyth case 0x04: /* WORM */
13574a4d8c2SCharles.Forsyth case 0x05: /* CD-ROM */
13674a4d8c2SCharles.Forsyth case 0x07: /* MO */
13774a4d8c2SCharles.Forsyth break;
13874a4d8c2SCharles.Forsyth default:
13974a4d8c2SCharles.Forsyth return 0;
14074a4d8c2SCharles.Forsyth }
14174a4d8c2SCharles.Forsyth
14274a4d8c2SCharles.Forsyth if(unit->dev->ifc->online == nil || unit->dev->ifc->online(unit) == 0)
14374a4d8c2SCharles.Forsyth return 0;
14474a4d8c2SCharles.Forsyth sdaddpart(unit, "data", 0, unit->sectors);
14574a4d8c2SCharles.Forsyth return 1;
14674a4d8c2SCharles.Forsyth }
14774a4d8c2SCharles.Forsyth
14874a4d8c2SCharles.Forsyth static SDunit*
sdgetunit(SDev * sdev,int subno)14974a4d8c2SCharles.Forsyth sdgetunit(SDev* sdev, int subno)
15074a4d8c2SCharles.Forsyth {
15174a4d8c2SCharles.Forsyth int index;
15274a4d8c2SCharles.Forsyth SDunit *unit;
15374a4d8c2SCharles.Forsyth
15474a4d8c2SCharles.Forsyth /*
15574a4d8c2SCharles.Forsyth * Associate a unit with a given device and sub-unit
15674a4d8c2SCharles.Forsyth * number on that device.
15774a4d8c2SCharles.Forsyth * The device will be probed if it has not already been
15874a4d8c2SCharles.Forsyth * successfully accessed.
15974a4d8c2SCharles.Forsyth */
16074a4d8c2SCharles.Forsyth qlock(&sdqlock);
16174a4d8c2SCharles.Forsyth index = sdev->index+subno;
16274a4d8c2SCharles.Forsyth unit = sdunit[index];
16374a4d8c2SCharles.Forsyth if(unit == nil){
16474a4d8c2SCharles.Forsyth if((unit = malloc(sizeof(SDunit))) == nil){
16574a4d8c2SCharles.Forsyth qunlock(&sdqlock);
16674a4d8c2SCharles.Forsyth return nil;
16774a4d8c2SCharles.Forsyth }
16874a4d8c2SCharles.Forsyth
16974a4d8c2SCharles.Forsyth if(sdev->enabled == 0 && sdev->ifc->enable)
17074a4d8c2SCharles.Forsyth sdev->ifc->enable(sdev);
17174a4d8c2SCharles.Forsyth sdev->enabled = 1;
17274a4d8c2SCharles.Forsyth
17374a4d8c2SCharles.Forsyth snprint(unit->name, NAMELEN, "sd%c%d", sdev->idno, subno);
17474a4d8c2SCharles.Forsyth unit->subno = subno;
17574a4d8c2SCharles.Forsyth unit->dev = sdev;
17674a4d8c2SCharles.Forsyth
17774a4d8c2SCharles.Forsyth /*
17874a4d8c2SCharles.Forsyth * No need to lock anything here as this is only
17974a4d8c2SCharles.Forsyth * called before the unit is made available in the
18074a4d8c2SCharles.Forsyth * sdunit[] array.
18174a4d8c2SCharles.Forsyth */
18274a4d8c2SCharles.Forsyth if(unit->dev->ifc->verify(unit) == 0){
18374a4d8c2SCharles.Forsyth qunlock(&sdqlock);
18474a4d8c2SCharles.Forsyth free(unit);
18574a4d8c2SCharles.Forsyth return nil;
18674a4d8c2SCharles.Forsyth }
18774a4d8c2SCharles.Forsyth sdunit[index] = unit;
18874a4d8c2SCharles.Forsyth }
18974a4d8c2SCharles.Forsyth qunlock(&sdqlock);
19074a4d8c2SCharles.Forsyth
19174a4d8c2SCharles.Forsyth return unit;
19274a4d8c2SCharles.Forsyth }
19374a4d8c2SCharles.Forsyth
19474a4d8c2SCharles.Forsyth static SDunit*
sdindex2unit(int index)19574a4d8c2SCharles.Forsyth sdindex2unit(int index)
19674a4d8c2SCharles.Forsyth {
19774a4d8c2SCharles.Forsyth SDev *sdev;
19874a4d8c2SCharles.Forsyth
19974a4d8c2SCharles.Forsyth /*
20074a4d8c2SCharles.Forsyth * Associate a unit with a given index into the top-level
20174a4d8c2SCharles.Forsyth * device directory.
20274a4d8c2SCharles.Forsyth * The device will be probed if it has not already been
20374a4d8c2SCharles.Forsyth * successfully accessed.
20474a4d8c2SCharles.Forsyth */
20574a4d8c2SCharles.Forsyth for(sdev = sdlist; sdev != nil; sdev = sdev->next){
20674a4d8c2SCharles.Forsyth if(index >= sdev->index && index < sdev->index+sdev->nunit)
20774a4d8c2SCharles.Forsyth return sdgetunit(sdev, index-sdev->index);
20874a4d8c2SCharles.Forsyth }
20974a4d8c2SCharles.Forsyth
21074a4d8c2SCharles.Forsyth return nil;
21174a4d8c2SCharles.Forsyth }
21274a4d8c2SCharles.Forsyth
21374a4d8c2SCharles.Forsyth static void
_sddetach(void)21474a4d8c2SCharles.Forsyth _sddetach(void)
21574a4d8c2SCharles.Forsyth {
21674a4d8c2SCharles.Forsyth SDev *sdev;
21774a4d8c2SCharles.Forsyth
21874a4d8c2SCharles.Forsyth for(sdev = sdlist; sdev != nil; sdev = sdev->next){
21974a4d8c2SCharles.Forsyth if(sdev->enabled == 0)
22074a4d8c2SCharles.Forsyth continue;
22174a4d8c2SCharles.Forsyth if(sdev->ifc->disable)
22274a4d8c2SCharles.Forsyth sdev->ifc->disable(sdev);
22374a4d8c2SCharles.Forsyth sdev->enabled = 0;
22474a4d8c2SCharles.Forsyth }
22574a4d8c2SCharles.Forsyth }
22674a4d8c2SCharles.Forsyth
227*8a8c2d74SCharles.Forsyth static void
sddump(void)228*8a8c2d74SCharles.Forsyth sddump(void)
229*8a8c2d74SCharles.Forsyth {
230*8a8c2d74SCharles.Forsyth SDev *sdev;
231*8a8c2d74SCharles.Forsyth
232*8a8c2d74SCharles.Forsyth print("sdevs:\n");
233*8a8c2d74SCharles.Forsyth for(sdev = sdlist; sdev != nil; sdev = sdev->next){
234*8a8c2d74SCharles.Forsyth print("sdev %c index %d nunit %d: ",
235*8a8c2d74SCharles.Forsyth sdev->idno, sdev->index, sdev->nunit);
236*8a8c2d74SCharles.Forsyth print("\n");
237*8a8c2d74SCharles.Forsyth }
238*8a8c2d74SCharles.Forsyth }
239*8a8c2d74SCharles.Forsyth
24074a4d8c2SCharles.Forsyth static int
_sdinit(void)24174a4d8c2SCharles.Forsyth _sdinit(void)
24274a4d8c2SCharles.Forsyth {
24374a4d8c2SCharles.Forsyth ulong m;
24474a4d8c2SCharles.Forsyth int i;
24574a4d8c2SCharles.Forsyth SDev *sdev, *tail;
24674a4d8c2SCharles.Forsyth SDunit *unit;
24774a4d8c2SCharles.Forsyth
24874a4d8c2SCharles.Forsyth /*
24974a4d8c2SCharles.Forsyth * Probe all configured controllers and make a list
25074a4d8c2SCharles.Forsyth * of devices found, accumulating a possible maximum number
25174a4d8c2SCharles.Forsyth * of units attached and marking each device with an index
25274a4d8c2SCharles.Forsyth * into the linear top-level directory array of units.
25374a4d8c2SCharles.Forsyth */
25474a4d8c2SCharles.Forsyth tail = nil;
25574a4d8c2SCharles.Forsyth for(i = 0; sdifc[i] != nil; i++){
25674a4d8c2SCharles.Forsyth if((sdev = sdifc[i]->pnp()) == nil)
25774a4d8c2SCharles.Forsyth continue;
25874a4d8c2SCharles.Forsyth if(sdlist != nil)
25974a4d8c2SCharles.Forsyth tail->next = sdev;
26074a4d8c2SCharles.Forsyth else
26174a4d8c2SCharles.Forsyth sdlist = sdev;
26274a4d8c2SCharles.Forsyth for(tail = sdev; tail->next != nil; tail = tail->next){
263*8a8c2d74SCharles.Forsyth tail->index = sdnunit;
26474a4d8c2SCharles.Forsyth sdnunit += tail->nunit;
26574a4d8c2SCharles.Forsyth }
26674a4d8c2SCharles.Forsyth tail->index = sdnunit;
26774a4d8c2SCharles.Forsyth sdnunit += tail->nunit;
26874a4d8c2SCharles.Forsyth }
26974a4d8c2SCharles.Forsyth /*
27074a4d8c2SCharles.Forsyth * Legacy and option code goes here. This will be hard...
27174a4d8c2SCharles.Forsyth */
27274a4d8c2SCharles.Forsyth
27374a4d8c2SCharles.Forsyth /*
27474a4d8c2SCharles.Forsyth * The maximum number of possible units is known, allocate
27574a4d8c2SCharles.Forsyth * placeholders for their datastructures; the units will be
27674a4d8c2SCharles.Forsyth * probed and structures allocated when attached.
27774a4d8c2SCharles.Forsyth * Allocate controller names for the different types.
27874a4d8c2SCharles.Forsyth */
27974a4d8c2SCharles.Forsyth if(sdnunit == 0)
28074a4d8c2SCharles.Forsyth return 0;
28174a4d8c2SCharles.Forsyth if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)
28274a4d8c2SCharles.Forsyth return 0;
28374a4d8c2SCharles.Forsyth sddetach = _sddetach;
28474a4d8c2SCharles.Forsyth
28574a4d8c2SCharles.Forsyth for(i = 0; sdifc[i] != nil; i++){
28674a4d8c2SCharles.Forsyth if(sdifc[i]->id)
28774a4d8c2SCharles.Forsyth sdifc[i]->id(sdlist);
28874a4d8c2SCharles.Forsyth }
289*8a8c2d74SCharles.Forsyth if (0)
290*8a8c2d74SCharles.Forsyth sddump();
29174a4d8c2SCharles.Forsyth
29274a4d8c2SCharles.Forsyth m = 0;
29374a4d8c2SCharles.Forsyth cdmask = sdmask = 0;
29474a4d8c2SCharles.Forsyth for(i=0; i<sdnunit && i < 32; i++) {
29574a4d8c2SCharles.Forsyth unit = sdindex2unit(i);
29674a4d8c2SCharles.Forsyth if(unit == nil)
29774a4d8c2SCharles.Forsyth continue;
29874a4d8c2SCharles.Forsyth sdinitpart(unit);
29974a4d8c2SCharles.Forsyth partition(unit);
30074a4d8c2SCharles.Forsyth if(unit->npart > 0){ /* BUG */
30174a4d8c2SCharles.Forsyth if((unit->inquiry[0] & 0x1F) == 0x05)
30274a4d8c2SCharles.Forsyth cdmask |= (1<<i);
30374a4d8c2SCharles.Forsyth else
30474a4d8c2SCharles.Forsyth sdmask |= (1<<i);
30574a4d8c2SCharles.Forsyth m |= (1<<i);
30674a4d8c2SCharles.Forsyth }
30774a4d8c2SCharles.Forsyth }
30874a4d8c2SCharles.Forsyth
30974a4d8c2SCharles.Forsyth //notesdinfo();
31074a4d8c2SCharles.Forsyth _sdmask = m;
31174a4d8c2SCharles.Forsyth return m;
31274a4d8c2SCharles.Forsyth }
31374a4d8c2SCharles.Forsyth
31474a4d8c2SCharles.Forsyth int
cdinit(void)31574a4d8c2SCharles.Forsyth cdinit(void)
31674a4d8c2SCharles.Forsyth {
31774a4d8c2SCharles.Forsyth if(sdnunit == 0)
31874a4d8c2SCharles.Forsyth _sdinit();
31974a4d8c2SCharles.Forsyth return cdmask;
32074a4d8c2SCharles.Forsyth }
32174a4d8c2SCharles.Forsyth
32274a4d8c2SCharles.Forsyth int
sdinit(void)32374a4d8c2SCharles.Forsyth sdinit(void)
32474a4d8c2SCharles.Forsyth {
32574a4d8c2SCharles.Forsyth if(sdnunit == 0)
32674a4d8c2SCharles.Forsyth _sdinit();
32774a4d8c2SCharles.Forsyth return sdmask;
32874a4d8c2SCharles.Forsyth }
32974a4d8c2SCharles.Forsyth
33074a4d8c2SCharles.Forsyth void
sdinitdev(int i,char * s)33174a4d8c2SCharles.Forsyth sdinitdev(int i, char *s)
33274a4d8c2SCharles.Forsyth {
33374a4d8c2SCharles.Forsyth SDunit *unit;
33474a4d8c2SCharles.Forsyth
33574a4d8c2SCharles.Forsyth unit = sdindex2unit(i);
33674a4d8c2SCharles.Forsyth strcpy(s, unit->name);
33774a4d8c2SCharles.Forsyth }
33874a4d8c2SCharles.Forsyth
33974a4d8c2SCharles.Forsyth void
sdprintdevs(int i)34074a4d8c2SCharles.Forsyth sdprintdevs(int i)
34174a4d8c2SCharles.Forsyth {
34274a4d8c2SCharles.Forsyth char *s;
34374a4d8c2SCharles.Forsyth SDunit *unit;
34474a4d8c2SCharles.Forsyth
34574a4d8c2SCharles.Forsyth unit = sdindex2unit(i);
34674a4d8c2SCharles.Forsyth for(i=0; i<unit->npart; i++){
34774a4d8c2SCharles.Forsyth s = unit->part[i].name;
34874a4d8c2SCharles.Forsyth if(strncmp(s, "dos", 3) == 0
34974a4d8c2SCharles.Forsyth || strncmp(s, "9fat", 4) == 0
35074a4d8c2SCharles.Forsyth || strncmp(s, "fs", 2) == 0)
35174a4d8c2SCharles.Forsyth print(" %s!%s", unit->name, s);
35274a4d8c2SCharles.Forsyth }
35374a4d8c2SCharles.Forsyth }
35474a4d8c2SCharles.Forsyth
35574a4d8c2SCharles.Forsyth SDpart*
sdfindpart(SDunit * unit,char * name)35674a4d8c2SCharles.Forsyth sdfindpart(SDunit *unit, char *name)
35774a4d8c2SCharles.Forsyth {
35874a4d8c2SCharles.Forsyth int i;
35974a4d8c2SCharles.Forsyth
36074a4d8c2SCharles.Forsyth if(parttrace)
36174a4d8c2SCharles.Forsyth print("findpart %d %s %s\t\n", unit->npart, unit->name, name);
36274a4d8c2SCharles.Forsyth for(i=0; i<unit->npart; i++) {
36374a4d8c2SCharles.Forsyth if(parttrace)
36474a4d8c2SCharles.Forsyth print("%s...", unit->part[i].name);
36574a4d8c2SCharles.Forsyth if(strcmp(unit->part[i].name, name) == 0){
36674a4d8c2SCharles.Forsyth if(parttrace)
36774a4d8c2SCharles.Forsyth print("\n");
36874a4d8c2SCharles.Forsyth return &unit->part[i];
36974a4d8c2SCharles.Forsyth }
37074a4d8c2SCharles.Forsyth }
37174a4d8c2SCharles.Forsyth if(parttrace)
37274a4d8c2SCharles.Forsyth print("not found\n");
37374a4d8c2SCharles.Forsyth return nil;
37474a4d8c2SCharles.Forsyth }
37574a4d8c2SCharles.Forsyth
37674a4d8c2SCharles.Forsyth typedef struct Scsicrud Scsicrud;
37774a4d8c2SCharles.Forsyth struct Scsicrud {
37874a4d8c2SCharles.Forsyth Fs fs;
37974a4d8c2SCharles.Forsyth vlong offset;
38074a4d8c2SCharles.Forsyth SDunit *unit;
38174a4d8c2SCharles.Forsyth SDpart *part;
38274a4d8c2SCharles.Forsyth };
38374a4d8c2SCharles.Forsyth
38474a4d8c2SCharles.Forsyth long
sdread(Fs * vcrud,void * v,long n)38574a4d8c2SCharles.Forsyth sdread(Fs *vcrud, void *v, long n)
38674a4d8c2SCharles.Forsyth {
38774a4d8c2SCharles.Forsyth Scsicrud *crud;
38874a4d8c2SCharles.Forsyth long x;
38974a4d8c2SCharles.Forsyth
39074a4d8c2SCharles.Forsyth crud = (Scsicrud*)vcrud;
39174a4d8c2SCharles.Forsyth x = sdbio(crud->unit, crud->part, v, n, crud->offset);
39274a4d8c2SCharles.Forsyth if(x > 0)
39374a4d8c2SCharles.Forsyth crud->offset += x;
39474a4d8c2SCharles.Forsyth return x;
39574a4d8c2SCharles.Forsyth }
39674a4d8c2SCharles.Forsyth
39774a4d8c2SCharles.Forsyth vlong
sdseek(Fs * vcrud,vlong seek)39874a4d8c2SCharles.Forsyth sdseek(Fs *vcrud, vlong seek)
39974a4d8c2SCharles.Forsyth {
40074a4d8c2SCharles.Forsyth ((Scsicrud*)vcrud)->offset = seek;
40174a4d8c2SCharles.Forsyth return seek;
40274a4d8c2SCharles.Forsyth }
40374a4d8c2SCharles.Forsyth
40474a4d8c2SCharles.Forsyth void*
sdgetfspart(int i,char * s,int chatty)40574a4d8c2SCharles.Forsyth sdgetfspart(int i, char *s, int chatty)
40674a4d8c2SCharles.Forsyth {
40774a4d8c2SCharles.Forsyth SDunit *unit;
40874a4d8c2SCharles.Forsyth SDpart *p;
40974a4d8c2SCharles.Forsyth Scsicrud *crud;
41074a4d8c2SCharles.Forsyth
41174a4d8c2SCharles.Forsyth if(cdmask&(1<<i)){
41274a4d8c2SCharles.Forsyth if(strcmp(s, "cdboot") != 0)
41374a4d8c2SCharles.Forsyth return nil;
41474a4d8c2SCharles.Forsyth }else if(sdmask&(1<<i)){
41574a4d8c2SCharles.Forsyth if(strcmp(s, "cdboot") == 0)
41674a4d8c2SCharles.Forsyth return nil;
41774a4d8c2SCharles.Forsyth }
41874a4d8c2SCharles.Forsyth
41974a4d8c2SCharles.Forsyth unit = sdindex2unit(i);
42074a4d8c2SCharles.Forsyth if((p = sdfindpart(unit, s)) == nil){
42174a4d8c2SCharles.Forsyth if(chatty)
42274a4d8c2SCharles.Forsyth print("unknown partition %s!%s\n", unit->name, s);
42374a4d8c2SCharles.Forsyth return nil;
42474a4d8c2SCharles.Forsyth }
42574a4d8c2SCharles.Forsyth if(p->crud == nil) {
42674a4d8c2SCharles.Forsyth crud = malloc(sizeof(Scsicrud));
42774a4d8c2SCharles.Forsyth crud->fs.dev = i;
42874a4d8c2SCharles.Forsyth crud->fs.diskread = sdread;
42974a4d8c2SCharles.Forsyth crud->fs.diskseek = sdseek;
43074a4d8c2SCharles.Forsyth // crud->start = 0;
43174a4d8c2SCharles.Forsyth crud->unit = unit;
43274a4d8c2SCharles.Forsyth crud->part = p;
43374a4d8c2SCharles.Forsyth if(dosinit(&crud->fs) < 0 && dosinit(&crud->fs) < 0 && kfsinit(&crud->fs) < 0){
43474a4d8c2SCharles.Forsyth if(chatty)
43574a4d8c2SCharles.Forsyth print("partition %s!%s does not contain a DOS or KFS file system\n",
43674a4d8c2SCharles.Forsyth unit->name, s);
43774a4d8c2SCharles.Forsyth return nil;
43874a4d8c2SCharles.Forsyth }
43974a4d8c2SCharles.Forsyth p->crud = crud;
44074a4d8c2SCharles.Forsyth }
44174a4d8c2SCharles.Forsyth return p->crud;
44274a4d8c2SCharles.Forsyth }
44374a4d8c2SCharles.Forsyth
44474a4d8c2SCharles.Forsyth /*
44574a4d8c2SCharles.Forsyth * Leave partitions around for devsd to pick up.
44674a4d8c2SCharles.Forsyth * (Needed by boot process; more extensive
44774a4d8c2SCharles.Forsyth * partitioning is done by termrc or cpurc).
44874a4d8c2SCharles.Forsyth */
44974a4d8c2SCharles.Forsyth void
sdaddconf(int i)45074a4d8c2SCharles.Forsyth sdaddconf(int i)
45174a4d8c2SCharles.Forsyth {
45274a4d8c2SCharles.Forsyth SDunit *unit;
45374a4d8c2SCharles.Forsyth SDpart *pp;
45474a4d8c2SCharles.Forsyth
45574a4d8c2SCharles.Forsyth unit = sdindex2unit(i);
45674a4d8c2SCharles.Forsyth
45774a4d8c2SCharles.Forsyth /*
45874a4d8c2SCharles.Forsyth * If there were no partitions (just data and partition), don't bother.
45974a4d8c2SCharles.Forsyth */
46074a4d8c2SCharles.Forsyth if(unit->npart<= 1 || (unit->npart==2 && strcmp(unit->part[1].name, "partition")==0))
46174a4d8c2SCharles.Forsyth return;
46274a4d8c2SCharles.Forsyth
46374a4d8c2SCharles.Forsyth addconf("%spart=", unit->name);
46474a4d8c2SCharles.Forsyth for(i=1, pp=&unit->part[i]; i<unit->npart; i++, pp++) /* skip 0, which is "data" */
465*8a8c2d74SCharles.Forsyth addconf("%s%s %lld %lld", i==1 ? "" : "/", pp->name,
46674a4d8c2SCharles.Forsyth pp->start, pp->end);
46774a4d8c2SCharles.Forsyth addconf("\n");
46874a4d8c2SCharles.Forsyth }
46974a4d8c2SCharles.Forsyth
47074a4d8c2SCharles.Forsyth int
sdboot(int dev,char * pname,Boot * b)47174a4d8c2SCharles.Forsyth sdboot(int dev, char *pname, Boot *b)
47274a4d8c2SCharles.Forsyth {
47374a4d8c2SCharles.Forsyth char *file;
47474a4d8c2SCharles.Forsyth Fs *fs;
47574a4d8c2SCharles.Forsyth
47674a4d8c2SCharles.Forsyth if((file = strchr(pname, '!')) == nil) {
47774a4d8c2SCharles.Forsyth print("syntax is sdC0!partition!file\n");
47874a4d8c2SCharles.Forsyth return -1;
47974a4d8c2SCharles.Forsyth }
48074a4d8c2SCharles.Forsyth *file++ = '\0';
48174a4d8c2SCharles.Forsyth
48274a4d8c2SCharles.Forsyth fs = sdgetfspart(dev, pname, 1);
48374a4d8c2SCharles.Forsyth if(fs == nil)
48474a4d8c2SCharles.Forsyth return -1;
48574a4d8c2SCharles.Forsyth
48674a4d8c2SCharles.Forsyth return fsboot(fs, file, b);
48774a4d8c2SCharles.Forsyth }
48874a4d8c2SCharles.Forsyth
48974a4d8c2SCharles.Forsyth long
sdbio(SDunit * unit,SDpart * pp,void * va,long len,vlong off)49074a4d8c2SCharles.Forsyth sdbio(SDunit *unit, SDpart *pp, void* va, long len, vlong off)
49174a4d8c2SCharles.Forsyth {
49274a4d8c2SCharles.Forsyth long l;
49374a4d8c2SCharles.Forsyth ulong bno, max, nb, offset;
49474a4d8c2SCharles.Forsyth static uchar *b;
49574a4d8c2SCharles.Forsyth char *a;
49674a4d8c2SCharles.Forsyth static ulong bsz;
49774a4d8c2SCharles.Forsyth
49874a4d8c2SCharles.Forsyth a = va;
49974a4d8c2SCharles.Forsyth memset(a, 0xDA, len);
50074a4d8c2SCharles.Forsyth qlock(&unit->ctl);
50174a4d8c2SCharles.Forsyth if(unit->changed){
50274a4d8c2SCharles.Forsyth qunlock(&unit->ctl);
50374a4d8c2SCharles.Forsyth return 0;
50474a4d8c2SCharles.Forsyth }
50574a4d8c2SCharles.Forsyth
50674a4d8c2SCharles.Forsyth /*
50774a4d8c2SCharles.Forsyth * Check the request is within bounds.
50874a4d8c2SCharles.Forsyth * Removeable drives are locked throughout the I/O
50974a4d8c2SCharles.Forsyth * in case the media changes unexpectedly.
51074a4d8c2SCharles.Forsyth * Non-removeable drives are not locked during the I/O
51174a4d8c2SCharles.Forsyth * to allow the hardware to optimise if it can; this is
51274a4d8c2SCharles.Forsyth * a little fast and loose.
51374a4d8c2SCharles.Forsyth * It's assumed that non-removable media parameters
51474a4d8c2SCharles.Forsyth * (sectors, secsize) can't change once the drive has
51574a4d8c2SCharles.Forsyth * been brought online.
51674a4d8c2SCharles.Forsyth */
51774a4d8c2SCharles.Forsyth bno = (off/unit->secsize) + pp->start;
51874a4d8c2SCharles.Forsyth nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
51974a4d8c2SCharles.Forsyth max = SDmaxio/unit->secsize;
52074a4d8c2SCharles.Forsyth if(nb > max)
52174a4d8c2SCharles.Forsyth nb = max;
52274a4d8c2SCharles.Forsyth if(bno+nb > pp->end)
52374a4d8c2SCharles.Forsyth nb = pp->end - bno;
52474a4d8c2SCharles.Forsyth if(bno >= pp->end || nb == 0){
52574a4d8c2SCharles.Forsyth qunlock(&unit->ctl);
52674a4d8c2SCharles.Forsyth return 0;
52774a4d8c2SCharles.Forsyth }
52874a4d8c2SCharles.Forsyth if(!(unit->inquiry[1] & 0x80))
52974a4d8c2SCharles.Forsyth qunlock(&unit->ctl);
53074a4d8c2SCharles.Forsyth
53174a4d8c2SCharles.Forsyth if(bsz < nb*unit->secsize){
53274a4d8c2SCharles.Forsyth b = malloc(nb*unit->secsize);
53374a4d8c2SCharles.Forsyth bsz = nb*unit->secsize;
53474a4d8c2SCharles.Forsyth }
53574a4d8c2SCharles.Forsyth // b = sdmalloc(nb*unit->secsize);
53674a4d8c2SCharles.Forsyth // if(b == nil)
53774a4d8c2SCharles.Forsyth // return 0;
53874a4d8c2SCharles.Forsyth
53974a4d8c2SCharles.Forsyth offset = off%unit->secsize;
54074a4d8c2SCharles.Forsyth if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0) {
54174a4d8c2SCharles.Forsyth // sdfree(b);
54274a4d8c2SCharles.Forsyth return 0;
54374a4d8c2SCharles.Forsyth }
54474a4d8c2SCharles.Forsyth
54574a4d8c2SCharles.Forsyth if(l < offset)
54674a4d8c2SCharles.Forsyth len = 0;
54774a4d8c2SCharles.Forsyth else if(len > l - offset)
54874a4d8c2SCharles.Forsyth len = l - offset;
54974a4d8c2SCharles.Forsyth if(len)
55074a4d8c2SCharles.Forsyth memmove(a, b+offset, len);
55174a4d8c2SCharles.Forsyth // sdfree(b);
55274a4d8c2SCharles.Forsyth
55374a4d8c2SCharles.Forsyth if(unit->inquiry[1] & 0x80)
55474a4d8c2SCharles.Forsyth qunlock(&unit->ctl);
55574a4d8c2SCharles.Forsyth
55674a4d8c2SCharles.Forsyth return len;
55774a4d8c2SCharles.Forsyth }
55874a4d8c2SCharles.Forsyth
55974a4d8c2SCharles.Forsyth #ifdef DMA
56074a4d8c2SCharles.Forsyth long
sdrio(SDreq * r,void * a,long n)56174a4d8c2SCharles.Forsyth sdrio(SDreq *r, void* a, long n)
56274a4d8c2SCharles.Forsyth {
56374a4d8c2SCharles.Forsyth if(n >= SDmaxio || n < 0)
56474a4d8c2SCharles.Forsyth return 0;
56574a4d8c2SCharles.Forsyth
56674a4d8c2SCharles.Forsyth r->data = nil;
56774a4d8c2SCharles.Forsyth if(n){
56874a4d8c2SCharles.Forsyth if((r->data = malloc(n)) == nil)
56974a4d8c2SCharles.Forsyth return 0;
57074a4d8c2SCharles.Forsyth if(r->write)
57174a4d8c2SCharles.Forsyth memmove(r->data, a, n);
57274a4d8c2SCharles.Forsyth }
57374a4d8c2SCharles.Forsyth r->dlen = n;
57474a4d8c2SCharles.Forsyth
57574a4d8c2SCharles.Forsyth if(r->unit->dev->ifc->rio(r) != SDok){
57674a4d8c2SCharles.Forsyth // cgascreenputs("1", 1);
57774a4d8c2SCharles.Forsyth if(r->data != nil){
57874a4d8c2SCharles.Forsyth sdfree(r->data);
57974a4d8c2SCharles.Forsyth r->data = nil;
58074a4d8c2SCharles.Forsyth }
58174a4d8c2SCharles.Forsyth return 0;
58274a4d8c2SCharles.Forsyth }
58374a4d8c2SCharles.Forsyth // cgascreenputs("2", 1);
58474a4d8c2SCharles.Forsyth
58574a4d8c2SCharles.Forsyth if(!r->write && r->rlen > 0)
58674a4d8c2SCharles.Forsyth memmove(a, r->data, r->rlen);
58774a4d8c2SCharles.Forsyth // cgascreenputs("3", 1);
58874a4d8c2SCharles.Forsyth if(r->data != nil){
58974a4d8c2SCharles.Forsyth sdfree(r->data);
59074a4d8c2SCharles.Forsyth r->data = nil;
59174a4d8c2SCharles.Forsyth }
59274a4d8c2SCharles.Forsyth
59374a4d8c2SCharles.Forsyth // cgascreenputs("4", 1);
59474a4d8c2SCharles.Forsyth return r->rlen;
59574a4d8c2SCharles.Forsyth }
59674a4d8c2SCharles.Forsyth #endif /* DMA */
59774a4d8c2SCharles.Forsyth
59874a4d8c2SCharles.Forsyth void
sleep(void *,int (* fn)(void *),void * v)59974a4d8c2SCharles.Forsyth sleep(void*, int (*fn)(void*), void *v)
60074a4d8c2SCharles.Forsyth {
60174a4d8c2SCharles.Forsyth int x;
60274a4d8c2SCharles.Forsyth x = spllo();
60374a4d8c2SCharles.Forsyth while(!fn(v))
60474a4d8c2SCharles.Forsyth ;
60574a4d8c2SCharles.Forsyth splx(x);
60674a4d8c2SCharles.Forsyth return;
60774a4d8c2SCharles.Forsyth }
60874a4d8c2SCharles.Forsyth
60974a4d8c2SCharles.Forsyth void
tsleep(void *,int (* fn)(void *),void * v,int msec)61074a4d8c2SCharles.Forsyth tsleep(void*, int (*fn)(void*), void *v, int msec)
61174a4d8c2SCharles.Forsyth {
61274a4d8c2SCharles.Forsyth int x;
61374a4d8c2SCharles.Forsyth ulong start;
61474a4d8c2SCharles.Forsyth
61574a4d8c2SCharles.Forsyth x = spllo();
61674a4d8c2SCharles.Forsyth for(start = m->ticks; TK2MS(m->ticks - start) < msec
61774a4d8c2SCharles.Forsyth && !fn(v); )
61874a4d8c2SCharles.Forsyth ;
61974a4d8c2SCharles.Forsyth splx(x);
62074a4d8c2SCharles.Forsyth return;
62174a4d8c2SCharles.Forsyth }
62274a4d8c2SCharles.Forsyth
62374a4d8c2SCharles.Forsyth void*
sdmalloc(void * p,ulong sz)62474a4d8c2SCharles.Forsyth sdmalloc(void *p, ulong sz)
62574a4d8c2SCharles.Forsyth {
62674a4d8c2SCharles.Forsyth if(p != nil) {
62774a4d8c2SCharles.Forsyth memset(p, 0, sz);
62874a4d8c2SCharles.Forsyth return p;
62974a4d8c2SCharles.Forsyth }
63074a4d8c2SCharles.Forsyth return malloc(sz);
63174a4d8c2SCharles.Forsyth }
632