git: 9front

Download patch

ref: f79a97198558c19f004519c8523ea59fbcd8d78a
parent: f3e24e40bd024de6c8e4766b5d80089b3232ef1a
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Tue Dec 6 09:49:40 EST 2011

fix cdrom media change

--- a/sys/src/9/pc/sdiahci.c
+++ b/sys/src/9/pc/sdiahci.c
@@ -1473,24 +1473,22 @@
 
 	c = unit->dev->ctlr;
 	d = c->drive[unit->subno];
-	r = 0;
-
-	if(d->portm.feat & Datapi && d->drivechange){
-		r = scsionline(unit);
-		if(r > 0)
-			d->drivechange = 0;
-		return r;
-	}
-
 	ilock(d);
+	if(d->portm.feat & Datapi){
+		d->drivechange = 0;
+		iunlock(d);
+		return scsionline(unit);
+	}
+	r = 0;
 	if(d->drivechange){
-		r = 2;
 		d->drivechange = 0;
-		/* devsd resets this after online is called; why? */
-		unit->sectors = d->sectors;
-		unit->secsize = d->secsize;
+		r = 2;
 	}else if(d->state == Dready)
 		r = 1;
+	if(r){
+		unit->sectors = d->sectors;
+		unit->secsize = d->secsize;
+	}
 	iunlock(d);
 	return r;
 }
@@ -1707,7 +1705,6 @@
 		case SDretry:
 			continue;
 		}
-//		print("%.2ux :: %.2ux :: %.4ux\n", r->cmd[0], r->status, d->port->task);
 		r->rlen = d->portm.list->len;
 		return SDok;
 	}
--- a/sys/src/9/pc/sdide.c
+++ b/sys/src/9/pc/sdide.c
@@ -1188,7 +1188,7 @@
 	cmdport = ctlr->cmdport;
 	ctlport = ctlr->ctlport;
 
-	as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, Drdy, 107*1000);
+	as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 107*1000);
 	/* used to test as&Chk as failure too, but some CD readers use that for media change */
 	if(as < 0)
 		return SDnostatus;
@@ -1242,12 +1242,12 @@
 	iunlock(ctlr);
 
 	if(drive->status & Chk){
+		rv = SDcheck;
 		if(drive->pktdma){
 			print("atapktio: disabling dma\n");
 			drive->dmactl = 0;
 			rv = SDretry;
-		} else
-			rv = SDcheck;
+		}
 	}
 	return rv;
 }
@@ -1545,7 +1545,7 @@
 	ctlr = d->ctlr;
 	cmdport = ctlr->cmdport;
 	ctlport = ctlr->ctlport;
-	if(ataready(cmdport, ctlport, d->dev, Bsy|Drq, d->pkt? 0: Drdy, 101*1000) < 0)
+	if(ataready(cmdport, ctlport, d->dev, Bsy|Drq, d->pkt ? 0 : Drdy, 101*1000) < 0)
 		return -1;
 
 	ilock(ctlr);
@@ -1902,7 +1902,6 @@
 			print("Inil%2.2uX+", ctlr->command);
 		return;
 	}
-
 	if(status & Err)
 		drive->error = inb(cmdport+Error);
 	else switch(drive->command){
@@ -1999,8 +1998,8 @@
 	switch(p->did<<16 | p->did){
 	case 0x439c<<16 | 0x1002:
 	case 0x438c<<16 | 0x1002:
-print("hi, anothy\n");
-print("%T: allowing bad ccru %.2ux for suspected ide controller\n", p->tbdf, p->ccru);
+		print("%T: allowing bad ccru %.2ux for suspected ide controller\n",
+			p->tbdf, p->ccru);
 		return 1;
 	default:
 		return 0;
@@ -2411,9 +2410,8 @@
 	if((drive->flags & Online) == 0){
 		drive->flags |= Online;
 		atadrive(unit, drive, ctlr->cmdport, ctlr->ctlport, drive->dev);
+		ret = 2;
 	}
-	unit->sectors = drive->sectors;
-	unit->secsize = drive->secsize;
 	if(drive->feat & Datapi){
 		ulong dma;
 
@@ -2421,6 +2419,9 @@
 		drive->dmactl = 0;
 		ret = scsionline(unit);
 		drive->dmactl = dma;
+	} else {
+		unit->sectors = drive->sectors;
+		unit->secsize = drive->secsize;
 	}
 	return ret;
 }
--- a/sys/src/9/port/sdscsi.c
+++ b/sys/src/9/port/sdscsi.c
@@ -214,7 +214,6 @@
 	ulong ss;
 	uvlong s;
 
-	*secsize = 0;
 	u = r->data;
 	if(r->clen == 16){
 		s = (uvlong)belong(u)<<32 | belong(u + 4);
@@ -223,24 +222,8 @@
 		s = belong(u);
 		ss = belong(u + 4);
 	}
-	/*
-	 * Some ATAPI CD readers lie about the block size.
-	 * Since we don't read audio via this interface
-	 * it's okay to always fudge this.
-	 */
-	if(ss == 2352)
-		ss = 2048;
-	/*
-	 * Devices with removable media may return 0 sectors
-	 * when they have empty media (e.g. sata dvd writers);
-	 * if so, keep the count zero.
-	 *
-	 * Read-capacity returns the LBA of the last sector,
-	 * therefore the number of sectors must be incremented.
-	 */
-	if(s != 0)
-		s++;
-	*secsize = ss;
+	if(secsize)
+		*secsize = ss;
 	return s;
 }
 
@@ -249,6 +232,8 @@
 {
 	SDreq *r;
 	uchar *p;
+	ulong ss;
+	uvlong s;
 	int ok, retries;
 	void (*cap)(SDreq*);
 
@@ -276,20 +261,51 @@
 		memset(r->cmd, 0, sizeof r->cmd);
 		cap(r);
 
-		r->status = ~0;
 		switch(scsirio(r)){
 		default:
+			/*
+			 * ATAPI returns error and no sense information
+			 * on media change / no media present.
+			 * count as retries.
+			 */
+			if(retries < 4)
+				continue;
 			break;
 		case 0:
-			unit->sectors = capreply(r, &unit->secsize);
-			if(unit->sectors == 0xffffffff && cap == cap10){
+			s = capreply(r, &ss);
+			if(s == 0xffffffff && cap == cap10){
 				cap = cap16;
 				continue;
 			}
-			ok = 1;
+			if(s == 0xffffffffffffffffLL)
+				s = 0;
+
+			/*
+			 * Some ATAPI CD readers lie about the block size.
+			 * Since we don't read audio via this interface
+			 * it's okay to always fudge this.
+			 */
+			if(ss == 2352)
+				ss = 2048;
+
+			/*
+			 * Devices with removable media may return 0 sectors
+			 * when they have empty media (e.g. sata dvd writers);
+			 * if so, keep the count zero.
+			 *	
+			 * Read-capacity returns the LBA of the last sector,
+			 * therefore the number of sectors must be incremented.
+			 */
+			if(s != 0)
+				s++;
+
+			ok = (unit->sectors != s) ? 2 : 1;
+			unit->sectors = s;
+			unit->secsize = ss;
 			break;
 		case 1:
-			ok = 1;
+			ok = (unit->sectors != 0) ? 2 : 1;
+			unit->sectors = 0;
 			break;
 		case 2:
 			continue;
@@ -298,6 +314,11 @@
 	}
 	free(p);
 	free(r);
+
+	/*
+	print("scsionline: %s: ok=%d retries=%d sectors=%llud secsize=%lud\n",
+		unit->name, ok, retries, unit->sectors, unit->secsize);
+	*/
 
 	if(ok)
 		return ok+retries;
--