Module Name:    src
Committed By:   tsutsui
Date:           Tue Aug 31 12:12:48 UTC 2010

Modified Files:
        src/sys/arch/dreamcast/dev: gdrom.c

Log Message:
Set bp->b_resid properly after data transfer is complete.
Fixes unexpected "Bad address" errors on file read ops since January 2006.

The problem is reported and tracked by Yasushi Oshima.


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/arch/dreamcast/dev/gdrom.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/dreamcast/dev/gdrom.c
diff -u src/sys/arch/dreamcast/dev/gdrom.c:1.26 src/sys/arch/dreamcast/dev/gdrom.c:1.27
--- src/sys/arch/dreamcast/dev/gdrom.c:1.26	Fri Aug  1 20:19:49 2008
+++ src/sys/arch/dreamcast/dev/gdrom.c	Tue Aug 31 12:12:48 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: gdrom.c,v 1.26 2008/08/01 20:19:49 marcus Exp $	*/
+/*	$NetBSD: gdrom.c,v 1.27 2010/08/31 12:12:48 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 2001 Marcus Comstedt
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: gdrom.c,v 1.26 2008/08/01 20:19:49 marcus Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gdrom.c,v 1.27 2010/08/31 12:12:48 tsutsui Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -118,10 +118,12 @@
 #define GDROM_COND	GDROM(0x9c)
 
 int	gdrom_getstat(void);
-int	gdrom_do_command(struct gdrom_softc *, void *, void *, unsigned int);
-int	gdrom_command_sense(struct gdrom_softc *, void *, void *, unsigned int);
+int	gdrom_do_command(struct gdrom_softc *, void *, void *, unsigned int,
+	    int *);
+int	gdrom_command_sense(struct gdrom_softc *, void *, void *, unsigned int,
+	    int *);
 int	gdrom_read_toc(struct gdrom_softc *, struct gd_toc *);
-int	gdrom_read_sectors(struct gdrom_softc *, void *, int, int);
+int	gdrom_read_sectors(struct gdrom_softc *, void *, int, int, int *);
 int	gdrom_mount_disk(struct gdrom_softc *);
 int	gdrom_intr(void *);
 
@@ -202,7 +204,7 @@
 
 
 int gdrom_do_command(struct gdrom_softc *sc, void *req, void *buf,
-    unsigned int nbyt)
+    unsigned int nbyt, int *resid)
 {
 	int i, s;
 	short *ptr = req;
@@ -239,12 +241,15 @@
 
 	splx(s);
 
+	if (resid != NULL)
+		*resid = sc->cmd_result_size;
+
 	return sc->cmd_cond;
 }
 
 
 int gdrom_command_sense(struct gdrom_softc *sc, void *req, void *buf,
-    unsigned int nbyt)
+    unsigned int nbyt, int *resid)
 {
 	/* 76543210 76543210
 	   0   0x13      -
@@ -257,7 +262,7 @@
 	unsigned char cmd[12];
 	int sense_key, sense_specific;
 
-	int cond = gdrom_do_command(sc, req, buf, nbyt);
+	int cond = gdrom_do_command(sc, req, buf, nbyt, resid);
 
 	if (cond < 0) {
 #ifdef GDROMDEBUG
@@ -278,7 +283,7 @@
 	cmd[0] = 0x13;
 	cmd[4] = sizeof(sense_data);
 	
-	gdrom_do_command(sc, cmd, sense_data, sizeof(sense_data));
+	gdrom_do_command(sc, cmd, sense_data, sizeof(sense_data), NULL);
 	
 	sense_key = sense_data[1] & 0xf;
 	sense_specific = sense_data[4];
@@ -314,10 +319,11 @@
 	cmd[3] = sizeof(struct gd_toc) >> 8;
 	cmd[4] = sizeof(struct gd_toc) & 0xff;
 	
-	return gdrom_command_sense(sc, cmd, toc, sizeof(struct gd_toc));
+	return gdrom_command_sense(sc, cmd, toc, sizeof(struct gd_toc), NULL);
 }
 
-int gdrom_read_sectors(struct gdrom_softc *sc, void *buf, int sector, int cnt)
+int gdrom_read_sectors(struct gdrom_softc *sc, void *buf, int sector, int cnt,
+    int *resid)
 {
 	/* 76543210 76543210
 	   0   0x30    datafmt
@@ -339,7 +345,7 @@
 	cmd[9] = cnt>>8;
 	cmd[10] = cnt;
 
-	return gdrom_command_sense(sc, cmd, buf, cnt << 11);
+	return gdrom_command_sense(sc, cmd, buf, cnt << 11, resid);
 }
 
 int gdrom_mount_disk(struct gdrom_softc *sc)
@@ -358,7 +364,7 @@
 	cmd[0] = 0x70;
 	cmd[1] = 0x1f;
 	
-	return gdrom_command_sense(sc, cmd, NULL, 0);
+	return gdrom_command_sense(sc, cmd, NULL, 0, NULL);
 }
 
 int
@@ -468,7 +474,7 @@
 gdromstrategy(struct buf *bp)
 {
 	struct gdrom_softc *sc;
-	int s, unit, error;
+	int s, unit, error, resid;
 #ifdef GDROMDEBUG
 	printf("GDROM: strategy\n");
 #endif
@@ -493,11 +499,14 @@
 	splx(s);
 
 	if ((error = gdrom_read_sectors(sc, bp->b_data, bp->b_rawblkno,
-	    bp->b_bcount >> 11)))
+	    bp->b_bcount >> 11, &resid)))
 		bp->b_error = error;
 
 	sc->is_busy = 0;
 	wakeup(&sc->is_busy);
+	bp->b_resid = resid;
+	biodone(bp);
+	return;
 
  done:
 	bp->b_resid = bp->b_bcount;

Reply via email to