vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

sdloop.c (5157B)


      1 #include "u.h"
      2 #include "lib.h"
      3 #include "mem.h"
      4 #include "dat.h"
      5 #include "fns.h"
      6 #include "io.h"
      7 #include "ureg.h"
      8 #include "error.h"
      9 
     10 #include "sd.h"
     11 
     12 void	loopdev(char*, int);
     13 
     14 typedef struct Ctlr Ctlr;
     15 struct Ctlr{
     16 	Ctlr	*next;
     17 	Ctlr	*prev;
     18 	
     19 	QLock	lk;
     20 	SDev	*sdev;
     21 
     22 	Chan	*c;
     23 	int		mode;
     24 	uvlong	qidpath;
     25 	char		fn[20];
     26 };
     27 
     28 static	Lock	ctlrlock;
     29 static	Ctlr	*ctlrhead;
     30 static	Ctlr	*ctlrtail;
     31 
     32 SDifc sdloopifc;
     33 
     34 static void
     35 loopopen(Ctlr *c)
     36 {
     37 	if(c->c == nil)
     38 		c->c = namec(c->fn, Aopen, c->mode, 0);
     39 }
     40 
     41 static SDev*
     42 looppnp(void)
     43 {
     44 	struct stat sbuf;
     45 	char c, c2;
     46 	char fn[20];
     47 
     48 	for(c = 'a'; c <= 'j'; ++c){
     49 		sprint(fn, "#Z/dev/sd%c", c);
     50 		if(stat(fn+2, &sbuf) == 0)
     51 			loopdev(fn, ORDWR);
     52 	}
     53 	for(c = '0'; c <= '9'; ++c){
     54 		sprintf(fn, "#Z/dev/sd%c",c);
     55 		if(stat(fn+2, &sbuf) == 0)
     56 			loopdev(fn, ORDWR);
     57 	}
     58 	for(c = 'a'; c <= 'j'; ++c){
     59 		sprint(fn, "#Z/dev/hd%c", c);
     60 		if(stat(fn+2, &sbuf) == 0)
     61 			loopdev(fn, ORDWR);
     62 	}
     63 	for(c = '0'; c <= '9'; ++c){
     64 		sprint(fn, "#Z/dev/wd%c", c);
     65 		if(stat(fn+2, &sbuf) == 0)
     66 			loopdev(fn, ORDWR);
     67 	}
     68 	for(c = '0'; c <= '8'; ++c){
     69 		for(c2 = '0'; c2 <= '8'; ++c2){
     70 			sprint(fn, "#Z/dev/cciss/c%cd%c", c, c2);
     71 			if(stat(fn+2, &sbuf) == 0)
     72 				loopdev(fn, ORDWR);
     73 		}
     74 	}
     75 	return nil;
     76 }
     77 
     78 /*
     79  * Cannot error.
     80  * Check that unit is available.
     81  * Return 1 if so, 0 if not.
     82  */
     83 static int
     84 loopverify(SDunit *u)
     85 {	
     86 	return 1;
     87 }
     88 
     89 /*
     90  * Cannot error.
     91  * Check that unit is online.
     92  * If media changed, return 2.
     93  * If ready, return 1.
     94  * If not ready, return 0.
     95  */
     96 static int
     97 looponline(SDunit *unit)
     98 {
     99 	uchar buf[sizeof(Dir)+100];
    100 	Chan *c;
    101 	SDev *sdev;
    102 	Ctlr *ctlr;
    103 	Dir dir;
    104 	long n;
    105 	
    106 	if(waserror())
    107 		return 0;
    108 
    109 	sdev = unit->dev;
    110 	ctlr = sdev->ctlr;
    111 	loopopen(ctlr);
    112 	c = ctlr->c;
    113 	n = devtab[c->type]->stat(c, buf, sizeof buf);
    114 	if(convM2D(buf, n, &dir, nil) == 0)
    115 		error("internal error: stat error in looponline");
    116 	if(ctlr->qidpath != dir.qid.path){
    117 		unit->sectors = dir.length/512;
    118 		unit->secsize = 512;
    119 		ctlr->qidpath = dir.qid.path;
    120 		poperror();
    121 		return 2;
    122 	}
    123 	poperror();
    124 	return 1;
    125 }
    126 
    127 static int
    128 looprio(SDreq *r)
    129 {
    130 	SDev *sdev;
    131 	SDunit *unit;
    132 	Ctlr *ctlr;
    133 	uchar *cmd;
    134 	uvlong lba;
    135 	long count, n;
    136 	Chan *c;
    137 	int status;
    138 
    139 	unit = r->unit;
    140 	sdev = unit->dev;
    141 	ctlr = sdev->ctlr;
    142 	loopopen(ctlr);
    143 	cmd = r->cmd;
    144 
    145 	if((status = sdfakescsi(r, nil, 0)) != SDnostatus){
    146 #warning "Need to check for SDcheck in sdloop.";
    147 		/* XXX check for SDcheck here */
    148 		r->status = status;
    149 		return status;
    150 	}
    151 
    152 	switch(cmd[0]){
    153 	case 0x28:	/* read */
    154 	case 0x2A:	/* write */
    155 		break;
    156 	default:
    157 		print("%s: bad cmd 0x%.2ux\n", unit->perm.name, cmd[0]);
    158 		r->status = SDcheck;
    159 		return SDcheck;
    160 	}
    161 
    162 	lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
    163 	count = (cmd[7]<<8)|cmd[8];
    164 	if(r->data == nil)
    165 		return SDok;
    166 	if(r->dlen < count*512)
    167 		count = r->dlen/512;
    168 
    169 	c = ctlr->c;
    170 	if(cmd[0] == 0x28)
    171 		n = devtab[c->type]->read(c, r->data, count*512, lba*512);
    172 	else
    173 		n = devtab[c->type]->write(c, r->data, count*512, lba*512);
    174 	r->rlen = n;
    175 	return SDok;
    176 }
    177 
    178 static int
    179 looprctl(SDunit *unit, char *p, int l)
    180 {
    181 	Ctlr *ctlr;
    182 	char *e, *op;
    183 	
    184 	ctlr = unit->dev->ctlr;
    185 	loopopen(ctlr);
    186 	e = p+l;
    187 	op = p;
    188 	
    189 	p = seprint(p, e, "loop %s %s\n", ctlr->mode == ORDWR ? "rw" : "ro", chanpath(ctlr->c));
    190 	p = seprint(p, e, "geometry %llud 512\n", unit->sectors*512);
    191 	return p - op;
    192 }
    193 
    194 static int
    195 loopwctl(SDunit *u, Cmdbuf *cmd)
    196 {
    197 	cmderror(cmd, Ebadarg);
    198 	return 0;
    199 }
    200 
    201 static void
    202 loopclear1(Ctlr *ctlr)
    203 {
    204 	lock(&ctlrlock);
    205 	if(ctlr->prev)
    206 		ctlr->prev->next = ctlr->next;
    207 	else
    208 		ctlrhead = ctlr;
    209 	if(ctlr->next)
    210 		ctlr->next->prev = ctlr->prev;
    211 	else
    212 		ctlrtail = ctlr->prev;
    213 	unlock(&ctlrlock);
    214 	
    215 	if(ctlr->c)
    216 		cclose(ctlr->c);
    217 	free(ctlr);
    218 }
    219 
    220 static void
    221 loopclear(SDev *sdev)
    222 {
    223 	loopclear1(sdev->ctlr);
    224 }
    225 
    226 static char*
    227 looprtopctl(SDev *s, char *p, char *e)
    228 {
    229 	Ctlr *c;
    230 	char *r;
    231 
    232 	c = s->ctlr;
    233 	loopopen(c);
    234 	r = "ro";
    235 	if(c->mode == ORDWR)
    236 		r = "rw";
    237 	return seprint(p, e, "%s loop %s %s\n", s->name, r, chanpath(c->c));
    238 }
    239 
    240 static int
    241 loopwtopctl(SDev *sdev, Cmdbuf *cb)
    242 {
    243 	int mode;
    244 
    245 	mode = 0;
    246 	if(cb->nf != 2)
    247 		cmderror(cb, Ebadarg);
    248 	if(strcmp(cb->f[0], "rw") == 0)
    249 		mode = ORDWR;
    250 	else if(strcmp(cb->f[0], "ro") == 0)
    251 		mode = OREAD;
    252 	else
    253 		cmderror(cb, Ebadarg);
    254 	
    255 	loopdev(cb->f[1], mode);
    256 	return 0;
    257 }
    258 
    259 void
    260 loopdev(char *name, int mode)
    261 {
    262 	Chan *c;
    263 	Ctlr *volatile ctlr;
    264 	SDev *volatile sdev;
    265 
    266 	ctlr = nil;
    267 	sdev = nil;
    268 /*
    269 	if(waserror()){
    270 		cclose(c);
    271 		if(ctlr)
    272 			free(ctlr);
    273 		if(sdev)
    274 			free(sdev);
    275 		nexterror();
    276 	}
    277 */
    278 
    279 	ctlr = smalloc(sizeof *ctlr);
    280 	sdev = smalloc(sizeof *sdev);
    281 	sdev->ifc = &sdloopifc;
    282 	sdev->ctlr = ctlr;
    283 	sdev->nunit = 1;
    284 	sdev->idno = '0';
    285 	ctlr->sdev = sdev;
    286 	strcpy(ctlr->fn, name);
    287 	ctlr->mode = mode;
    288 /*
    289 	poperror();
    290 */
    291 
    292 	lock(&ctlrlock);
    293 	ctlr->next = nil;
    294 	ctlr->prev = ctlrtail;
    295 	ctlrtail = ctlr;
    296 	if(ctlr->prev)
    297 		ctlr->prev->next = ctlr;
    298 	else
    299 		ctlrhead = ctlr;
    300 	unlock(&ctlrlock);
    301 	
    302 	sdadddevs(sdev);
    303 }
    304 
    305 
    306 SDifc sdloopifc = {
    307 	"loop",
    308 
    309 	looppnp,
    310 	nil,		/* legacy */
    311 	nil,		/* enable */
    312 	nil,		/* disable */
    313 
    314 	loopverify,
    315 	looponline,
    316 	looprio,
    317 	looprctl,
    318 	loopwctl,
    319 
    320 	scsibio,
    321 	nil,	/* probe */
    322 	loopclear,	/* clear */
    323 	looprtopctl,
    324 	loopwtopctl,
    325 };
    326 
    327 
    328