mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-20 11:11:24 +00:00
MFi386: r189749
Teach the BIOS CD driver to use bounce buffers when the destination address is > 1 MB.
This commit is contained in:
parent
15fb32c07d
commit
d0680af004
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=190146
@ -170,9 +170,9 @@ bc_add(int biosdev)
|
||||
static void
|
||||
bc_print(int verbose)
|
||||
{
|
||||
int i;
|
||||
char line[80];
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nbcinfo; i++) {
|
||||
sprintf(line, " cd%d: Device 0x%x\n", i,
|
||||
bcinfo[i].bc_sp.sp_devicespec);
|
||||
@ -232,7 +232,7 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
|
||||
if (dblk % (BIOSCD_SECSIZE / DEV_BSIZE) != 0)
|
||||
return (EINVAL);
|
||||
dblk /= (BIOSCD_SECSIZE / DEV_BSIZE);
|
||||
DEBUG("read %d from %d to %p", blks, dblk, buf);
|
||||
DEBUG("read %d from %lld to %p", blks, dblk, buf);
|
||||
|
||||
if (rsize)
|
||||
*rsize = 0;
|
||||
@ -241,9 +241,9 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
|
||||
return (EIO);
|
||||
}
|
||||
#ifdef BD_SUPPORT_FRAGS
|
||||
DEBUG("bc_strategy: frag read %d from %d+%d to %p",
|
||||
DEBUG("frag read %d from %lld+%d to %p",
|
||||
fragsize, dblk, blks, buf + (blks * BIOSCD_SECSIZE));
|
||||
if (fragsize && bc_read(unit, dblk + blks, 1, fragsize)) {
|
||||
if (fragsize && bc_read(unit, dblk + blks, 1, fragbuf)) {
|
||||
DEBUG("frag read error");
|
||||
return(EIO);
|
||||
}
|
||||
@ -254,11 +254,14 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Max number of sectors to bounce-buffer at a time. */
|
||||
#define CD_BOUNCEBUF 8
|
||||
|
||||
static int
|
||||
bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
|
||||
{
|
||||
u_int result, retry;
|
||||
static unsigned short packet[8];
|
||||
u_int maxfer, resid, result, retry, x;
|
||||
caddr_t bbuf, p, xp;
|
||||
int biosdev;
|
||||
#ifdef DISK_DEBUG
|
||||
int error;
|
||||
@ -272,40 +275,73 @@ bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
|
||||
if (blks == 0)
|
||||
return (0);
|
||||
|
||||
biosdev = bc_unit2bios(unit);
|
||||
/*
|
||||
* Loop retrying the operation a couple of times. The BIOS
|
||||
* may also retry.
|
||||
*/
|
||||
for (retry = 0; retry < 3; retry++) {
|
||||
/* If retrying, reset the drive */
|
||||
if (retry > 0) {
|
||||
v86.ctl = V86_FLAGS;
|
||||
v86.addr = 0x1b;
|
||||
v86.eax = 0x0300 | biosdev;
|
||||
v86int();
|
||||
}
|
||||
|
||||
v86.ctl = V86_FLAGS;
|
||||
v86.addr = 0x1b;
|
||||
v86.eax = 0x0600 | (biosdev & 0x7f);
|
||||
v86.ebx = blks * BIOSCD_SECSIZE;
|
||||
v86.ecx = dblk & 0xffff;
|
||||
v86.edx = (dblk >> 16) & 0xffff;
|
||||
v86.ebp = VTOPOFF(dest);
|
||||
v86.es = VTOPSEG(dest);
|
||||
v86int();
|
||||
result = (v86.efl & PSL_C);
|
||||
if (result == 0)
|
||||
break;
|
||||
/* Decide whether we have to bounce */
|
||||
if (VTOP(dest) >> 20 != 0) {
|
||||
/*
|
||||
* The destination buffer is above first 1MB of
|
||||
* physical memory so we have to arrange a suitable
|
||||
* bounce buffer.
|
||||
*/
|
||||
x = min(CD_BOUNCEBUF, (unsigned)blks);
|
||||
bbuf = alloca(x * BIOSCD_SECSIZE);
|
||||
maxfer = x;
|
||||
} else {
|
||||
bbuf = NULL;
|
||||
maxfer = 0;
|
||||
}
|
||||
|
||||
biosdev = bc_unit2bios(unit);
|
||||
resid = blks;
|
||||
p = dest;
|
||||
|
||||
while (resid > 0) {
|
||||
if (bbuf)
|
||||
xp = bbuf;
|
||||
else
|
||||
xp = p;
|
||||
x = resid;
|
||||
if (maxfer > 0)
|
||||
x = min(x, maxfer);
|
||||
|
||||
/*
|
||||
* Loop retrying the operation a couple of times. The BIOS
|
||||
* may also retry.
|
||||
*/
|
||||
for (retry = 0; retry < 3; retry++) {
|
||||
/* If retrying, reset the drive */
|
||||
if (retry > 0) {
|
||||
v86.ctl = V86_FLAGS;
|
||||
v86.addr = 0x1b;
|
||||
v86.eax = 0x0300 | biosdev;
|
||||
v86int();
|
||||
}
|
||||
|
||||
v86.ctl = V86_FLAGS;
|
||||
v86.addr = 0x1b;
|
||||
v86.eax = 0x0600 | (biosdev & 0x7f);
|
||||
v86.ebx = blks * BIOSCD_SECSIZE;
|
||||
v86.ecx = dblk & 0xffff;
|
||||
v86.edx = (dblk >> 16) & 0xffff;
|
||||
v86.ebp = VTOPOFF(dest);
|
||||
v86.es = VTOPSEG(dest);
|
||||
v86int();
|
||||
result = (v86.efl & PSL_C);
|
||||
if (result == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DISK_DEBUG
|
||||
error = (v86.eax >> 8) & 0xff;
|
||||
error = (v86.eax >> 8) & 0xff;
|
||||
#endif
|
||||
DEBUG("%d sectors from %ld to %p (0x%x) %s", blks, dblk, dest,
|
||||
VTOP(dest), result ? "failed" : "ok");
|
||||
DEBUG("unit %d status 0x%x", unit, error);
|
||||
DEBUG("%d sectors from %lld to %p (0x%x) %s", x, dblk, p,
|
||||
VTOP(p), result ? "failed" : "ok");
|
||||
DEBUG("unit %d status 0x%x", unit, error);
|
||||
if (bbuf != NULL)
|
||||
bcopy(bbuf, p, x * BIOSCD_SECSIZE);
|
||||
p += (x * BIOSCD_SECSIZE);
|
||||
dblk += x;
|
||||
resid -= x;
|
||||
}
|
||||
|
||||
/* hexdump(dest, (blks * BIOSCD_SECSIZE)); */
|
||||
return(0);
|
||||
|
Loading…
Reference in New Issue
Block a user