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.
This commit is contained in:
parent
5de383f454
commit
1f68cc819a
|
@ -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
|
* Copyright (c) 2001 Marcus Comstedt
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
#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/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
@ -118,10 +118,12 @@ struct gd_toc {
|
||||||
#define GDROM_COND GDROM(0x9c)
|
#define GDROM_COND GDROM(0x9c)
|
||||||
|
|
||||||
int gdrom_getstat(void);
|
int gdrom_getstat(void);
|
||||||
int gdrom_do_command(struct gdrom_softc *, void *, void *, unsigned int);
|
int gdrom_do_command(struct gdrom_softc *, void *, void *, unsigned int,
|
||||||
int gdrom_command_sense(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_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_mount_disk(struct gdrom_softc *);
|
||||||
int gdrom_intr(void *);
|
int gdrom_intr(void *);
|
||||||
|
|
||||||
|
@ -202,7 +204,7 @@ gdrom_intr(void *arg)
|
||||||
|
|
||||||
|
|
||||||
int gdrom_do_command(struct gdrom_softc *sc, void *req, void *buf,
|
int gdrom_do_command(struct gdrom_softc *sc, void *req, void *buf,
|
||||||
unsigned int nbyt)
|
unsigned int nbyt, int *resid)
|
||||||
{
|
{
|
||||||
int i, s;
|
int i, s;
|
||||||
short *ptr = req;
|
short *ptr = req;
|
||||||
|
@ -239,12 +241,15 @@ int gdrom_do_command(struct gdrom_softc *sc, void *req, void *buf,
|
||||||
|
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
|
if (resid != NULL)
|
||||||
|
*resid = sc->cmd_result_size;
|
||||||
|
|
||||||
return sc->cmd_cond;
|
return sc->cmd_cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int gdrom_command_sense(struct gdrom_softc *sc, void *req, void *buf,
|
int gdrom_command_sense(struct gdrom_softc *sc, void *req, void *buf,
|
||||||
unsigned int nbyt)
|
unsigned int nbyt, int *resid)
|
||||||
{
|
{
|
||||||
/* 76543210 76543210
|
/* 76543210 76543210
|
||||||
0 0x13 -
|
0 0x13 -
|
||||||
|
@ -257,7 +262,7 @@ int gdrom_command_sense(struct gdrom_softc *sc, void *req, void *buf,
|
||||||
unsigned char cmd[12];
|
unsigned char cmd[12];
|
||||||
int sense_key, sense_specific;
|
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) {
|
if (cond < 0) {
|
||||||
#ifdef GDROMDEBUG
|
#ifdef GDROMDEBUG
|
||||||
|
@ -278,7 +283,7 @@ int gdrom_command_sense(struct gdrom_softc *sc, void *req, void *buf,
|
||||||
cmd[0] = 0x13;
|
cmd[0] = 0x13;
|
||||||
cmd[4] = sizeof(sense_data);
|
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_key = sense_data[1] & 0xf;
|
||||||
sense_specific = sense_data[4];
|
sense_specific = sense_data[4];
|
||||||
|
@ -314,10 +319,11 @@ int gdrom_read_toc(struct gdrom_softc *sc, struct gd_toc *toc)
|
||||||
cmd[3] = sizeof(struct gd_toc) >> 8;
|
cmd[3] = sizeof(struct gd_toc) >> 8;
|
||||||
cmd[4] = sizeof(struct gd_toc) & 0xff;
|
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
|
/* 76543210 76543210
|
||||||
0 0x30 datafmt
|
0 0x30 datafmt
|
||||||
|
@ -339,7 +345,7 @@ int gdrom_read_sectors(struct gdrom_softc *sc, void *buf, int sector, int cnt)
|
||||||
cmd[9] = cnt>>8;
|
cmd[9] = cnt>>8;
|
||||||
cmd[10] = cnt;
|
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)
|
int gdrom_mount_disk(struct gdrom_softc *sc)
|
||||||
|
@ -358,7 +364,7 @@ int gdrom_mount_disk(struct gdrom_softc *sc)
|
||||||
cmd[0] = 0x70;
|
cmd[0] = 0x70;
|
||||||
cmd[1] = 0x1f;
|
cmd[1] = 0x1f;
|
||||||
|
|
||||||
return gdrom_command_sense(sc, cmd, NULL, 0);
|
return gdrom_command_sense(sc, cmd, NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -468,7 +474,7 @@ void
|
||||||
gdromstrategy(struct buf *bp)
|
gdromstrategy(struct buf *bp)
|
||||||
{
|
{
|
||||||
struct gdrom_softc *sc;
|
struct gdrom_softc *sc;
|
||||||
int s, unit, error;
|
int s, unit, error, resid;
|
||||||
#ifdef GDROMDEBUG
|
#ifdef GDROMDEBUG
|
||||||
printf("GDROM: strategy\n");
|
printf("GDROM: strategy\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -493,11 +499,14 @@ gdromstrategy(struct buf *bp)
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
if ((error = gdrom_read_sectors(sc, bp->b_data, bp->b_rawblkno,
|
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;
|
bp->b_error = error;
|
||||||
|
|
||||||
sc->is_busy = 0;
|
sc->is_busy = 0;
|
||||||
wakeup(&sc->is_busy);
|
wakeup(&sc->is_busy);
|
||||||
|
bp->b_resid = resid;
|
||||||
|
biodone(bp);
|
||||||
|
return;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
bp->b_resid = bp->b_bcount;
|
bp->b_resid = bp->b_bcount;
|
||||||
|
|
Loading…
Reference in New Issue