瀏覽代碼

Plan 9 from Bell Labs 2011-10-26

David du Colombier 12 年之前
父節點
當前提交
8ba513e2c7
共有 1 個文件被更改,包括 70 次插入45 次删除
  1. 70 45
      sys/src/9/pc/sdiahci.c

+ 70 - 45
sys/src/9/pc/sdiahci.c

@@ -21,7 +21,7 @@
 #define Intel(x)	((x)->pci->vid == Vintel)
 
 enum {
-	NCtlr	= 8,
+	NCtlr	= 16,
 	NCtlrdrv= 32,
 	NDrive	= NCtlr*NCtlrdrv,
 
@@ -145,7 +145,9 @@ struct Drive {
 	char	firmware[8+1];
 	char	model[40+1];
 
-	ushort	info[0x200];
+	int	infosz;
+	ushort	*info;
+	ushort	tinyinfo[2];	/* used iff malloc fails */
 
 	int	driveno;	/* ctlr*NCtlrdrv + unit */
 	/* controller port # != driveno when not all ports are enabled */
@@ -171,8 +173,8 @@ struct Ctlr {
 	/* phyical register address */
 	uchar	*physio;
 
-	Drive	rawdrive[NCtlrdrv];
-	Drive*	drive[NCtlrdrv];
+	Drive	*rawdrive;
+	Drive	*drive[NCtlrdrv];
 	int	ndrive;
 	int	mport;		/* highest drive # (0-origin) on ich9 at least */
 
@@ -938,6 +940,14 @@ identify(Drive *d)
 	uchar oserial[21];
 	SDunit *u;
 
+	if(d->info == nil) {
+		d->infosz = 512 * sizeof(ushort);
+		d->info = malloc(d->infosz);
+	}
+	if(d->info == nil) {
+		d->info = d->tinyinfo;
+		d->infosz = sizeof d->tinyinfo;
+	}
 	id = d->info;
 	s = ahciidentify(&d->portc, id);
 	if(s == -1){
@@ -1362,7 +1372,8 @@ satakproc(void*)
 	for(;;){
 		tsleep(&up->sleep, return0, 0, Nms);
 		for(i = 0; i < niadrive; i++)
-			checkdrive(iadrive[i], i);
+			if(iadrive[i] != nil)
+				checkdrive(iadrive[i], i);
 	}
 }
 
@@ -1711,7 +1722,7 @@ iariopkt(SDreq *r, Drive *d)
 	aprint("ahci: iariopkt: %02ux %02ux %c %d %p\n",
 		cmd[0], cmd[2], "rw"[r->write], r->dlen, r->data);
 	if(cmd[0] == 0x5a && (cmd[2] & 0x3f) == 0x3f)
-		return sdmodesense(r, cmd, d->info, sizeof d->info);
+		return sdmodesense(r, cmd, d->info, d->infosz);
 	r->rlen = 0;
 	count = r->dlen;
 	max = 65536;
@@ -1812,7 +1823,7 @@ iario(SDreq *r)
 		return sdsetsense(r, SDcheck, 3, 0xc, 2);
 	}
 
-	if((i = sdfakescsi(r, d->info, sizeof d->info)) != SDnostatus){
+	if((i = sdfakescsi(r, d->info, d->infosz)) != SDnostatus){
 		r->status = i;
 		return i;
 	}
@@ -1967,13 +1978,60 @@ didtype(Pcidev *p)
 	return -1;
 }
 
+static int
+newctlr(Ctlr *ctlr, SDev *sdev, int nunit)
+{
+	int i, n;
+	Drive *drive;
+
+	ctlr->ndrive = sdev->nunit = nunit;
+	ctlr->mport = ctlr->hba->cap & ((1<<5)-1);
+
+	i = (ctlr->hba->cap >> 20) & ((1<<4)-1);		/* iss */
+	print("#S/sd%c: %s: %#p %s, %d ports, irq %d\n", sdev->idno,
+		Tname(ctlr), ctlr->physio, descmode[i], nunit, ctlr->pci->intl);
+	/* map the drives -- they don't all need to be enabled. */
+	n = 0;
+	ctlr->rawdrive = malloc(NCtlrdrv * sizeof(Drive));
+	if(ctlr->rawdrive == nil) {
+		print("ahci: out of memory\n");
+		return -1;
+	}
+	for(i = 0; i < NCtlrdrv; i++) {
+		drive = ctlr->rawdrive + i;
+		drive->portno = i;
+		drive->driveno = -1;
+		drive->sectors = 0;
+		drive->serial[0] = ' ';
+		drive->ctlr = ctlr;
+		if((ctlr->hba->pi & (1<<i)) == 0)
+			continue;
+		drive->port = (Aport*)(ctlr->mmio + 0x80*i + 0x100);
+		drive->portc.p = drive->port;
+		drive->portc.m = &drive->portm;
+		drive->driveno = n++;
+		ctlr->drive[drive->driveno] = drive;
+		iadrive[niadrive + drive->driveno] = drive;
+	}
+	for(i = 0; i < n; i++)
+		if(ahciidle(ctlr->drive[i]->port) == -1){
+			dprint("ahci: %s: port %d wedged; abort\n",
+				Tname(ctlr), i);
+			return -1;
+		}
+	for(i = 0; i < n; i++){
+		ctlr->drive[i]->mode = DMsatai;
+		configdrive(ctlr->drive[i]);
+	}
+	return n;
+}
+
 static SDev*
 iapnp(void)
 {
-	int i, n, nunit, type;
+	int n, nunit, type;
 	ulong io;
 	Ctlr *c;
-	Drive *d;
 	Pcidev *p;
 	SDev *head, *tail, *s;
 	static int done;
@@ -2025,42 +2083,9 @@ loop:
 			vunmap(c->mmio, p->mem[Abar].size);
 			continue;
 		}
-		c->ndrive = s->nunit = nunit;
-		c->mport = c->hba->cap & ((1<<5)-1);
-
-		i = (c->hba->cap >> 20) & ((1<<4)-1);		/* iss */
-		print("#S/sd%c: %s: %#p %s, %d ports, irq %d\n", s->idno,
-			Tname(c), c->physio, descmode[i], nunit, c->pci->intl);
-		/* map the drives -- they don't all need to be enabled. */
-		memset(c->rawdrive, 0, sizeof c->rawdrive);
-		n = 0;
-		for(i = 0; i < NCtlrdrv; i++) {
-			d = c->rawdrive + i;
-			d->portno = i;
-			d->driveno = -1;
-			d->sectors = 0;
-			d->serial[0] = ' ';
-			d->ctlr = c;
-			if((c->hba->pi & (1<<i)) == 0)
-				continue;
-			d->port = (Aport*)(c->mmio + 0x80*i + 0x100);
-			d->portc.p = d->port;
-			d->portc.m = &d->portm;
-			d->driveno = n++;
-			c->drive[d->driveno] = d;
-			iadrive[niadrive + d->driveno] = d;
-		}
-		for(i = 0; i < n; i++)
-			if(ahciidle(c->drive[i]->port) == -1){
-				dprint("ahci: %s: port %d wedged; abort\n",
-					Tname(c), i);
-				goto loop;
-			}
-		for(i = 0; i < n; i++){
-			c->drive[i]->mode = DMsatai;
-			configdrive(c->drive[i]);
-		}
-
+		n = newctlr(c, s, nunit);
+		if(n < 0)
+			goto loop;
 		niadrive += n;
 		niactlr++;
 		if(head)