biosdisk.c (39473) | biosdisk.c (39662) |
---|---|
1/*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $Id: biosdisk.c,v 1.4 1998/09/18 02:02:33 msmith Exp $ | 26 * $Id: biosdisk.c,v 1.5 1998/09/19 01:33:29 msmith Exp $ |
27 */ 28 29/* 30 * BIOS disk device handling. 31 * 32 * Ideas and algorithms from: 33 * 34 * - NetBSD libi386/biosdisk.c --- 357 unchanged lines hidden (view full) --- 392 } 393 bcopy(fragbuf, buf + (blks * BIOSDISK_SECSIZE), fragsize); 394#endif 395 if (rsize) 396 *rsize = size; 397 return (0); 398} 399 | 27 */ 28 29/* 30 * BIOS disk device handling. 31 * 32 * Ideas and algorithms from: 33 * 34 * - NetBSD libi386/biosdisk.c --- 357 unchanged lines hidden (view full) --- 392 } 393 bcopy(fragbuf, buf + (blks * BIOSDISK_SECSIZE), fragsize); 394#endif 395 if (rsize) 396 *rsize = size; 397 return (0); 398} 399 |
400/* Max number of sectors to bounce-buffer if the request crosses a 64k boundary */ 401#define FLOPPY_BOUNCEBUF 18 402 |
|
400static int 401bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest) 402{ | 403static int 404bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest) 405{ |
403 int x, bpc, cyl, hd, sec, result, resid, cnt; 404 caddr_t p; | 406 int x, bpc, cyl, hd, sec, result, resid, cnt, retry, maxfer; 407 caddr_t p, xp, bbuf, breg; |
405 406 bpc = (od->od_sec * od->od_hds); /* blocks per cylinder */ 407 resid = blks; 408 p = dest; 409 | 408 409 bpc = (od->od_sec * od->od_hds); /* blocks per cylinder */ 410 resid = blks; 411 p = dest; 412 |
413 /* Decide whether we have to bounce */ 414 if ((od->od_unit < 0x80) && 415 ((VTOP(dest) >> 16) != (VTOP(dest + blks * BIOSDISK_SECSIZE) >> 16))) { 416 417 /* 418 * There is a 64k physical boundary somewhere in the destination buffer, so we have 419 * to arrange a suitable bounce buffer. Allocate a buffer twice as large as we 420 * need to. Use the bottom half unless there is a break there, in which case we 421 * use the top half. 422 */ 423 x = min(FLOPPY_BOUNCEBUF, blks); 424 bbuf = malloc(x * 2 * BIOSDISK_SECSIZE); 425 if (((u_int32_t)VTOP(bbuf) & 0xffff0000) == ((u_int32_t)VTOP(dest + x * BIOSDISK_SECSIZE) & 0xffff0000)) { 426 breg = bbuf; 427 } else { 428 breg = bbuf + x * BIOSDISK_SECSIZE; 429 } 430 maxfer = x; /* limit transfers to bounce region size */ 431 } else { 432 bbuf = NULL; 433 maxfer = 0; 434 } 435 |
|
410 while (resid > 0) { 411 x = dblk; 412 cyl = x / bpc; /* block # / blocks per cylinder */ 413 x %= bpc; /* block offset into cylinder */ 414 hd = x / od->od_sec; /* offset / blocks per track */ 415 sec = x % od->od_sec; /* offset into track */ 416 | 436 while (resid > 0) { 437 x = dblk; 438 cyl = x / bpc; /* block # / blocks per cylinder */ 439 x %= bpc; /* block offset into cylinder */ 440 hd = x / od->od_sec; /* offset / blocks per track */ 441 sec = x % od->od_sec; /* offset into track */ 442 |
417 /* play it safe and don't cross track boundaries */ 418 x = min (od->od_sec - sec, resid); | 443 /* play it safe and don't cross track boundaries (XXX this is probably unnecessary) */ 444 x = min(od->od_sec - sec, resid); 445 if (maxfer > 0) 446 x = min(x, maxfer); /* fit bounce buffer */ |
419 | 447 |
448 /* where do we transfer to? */ 449 xp = bbuf == NULL ? p : breg; 450 |
|
420 /* correct sector number for 1-based BIOS numbering */ 421 sec++; 422 | 451 /* correct sector number for 1-based BIOS numbering */ 452 sec++; 453 |
423 /* build request XXX support EDD requests too */ 424 v86.ctl = V86_FLAGS; 425 v86.addr = 0x13; 426 v86.eax = 0x200 | x; 427 v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec; 428 v86.edx = (hd << 8) | od->od_unit; 429 v86.es = VTOPSEG(p); 430 v86.ebx = VTOPOFF(p); 431 v86int(); 432 result = (v86.efl & 0x1); 433 DEBUG("%d sectors from %d/%d/%d %s", x, cyl, hd, sec - 1, result ? "failed" : "ok"); 434 if (result) 435 return(-1); | 454 /* Loop retrying the operation a couple of times. The BIOS may also retry. */ 455 for (retry = 0; retry < 3; retry++) { 456 /* if retrying, reset the drive */ 457 if (retry > 0) { 458 v86.ctl = V86_FLAGS; 459 v86.addr = 0x13; 460 v86.eax = 0; 461 v86.edx = od->od_unit; 462 v86int(); 463 } 464 465 /* build request XXX support EDD requests too */ 466 v86.ctl = V86_FLAGS; 467 v86.addr = 0x13; 468 v86.eax = 0x200 | x; 469 v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec; 470 v86.edx = (hd << 8) | od->od_unit; 471 v86.es = VTOPSEG(xp); 472 v86.ebx = VTOPOFF(xp); 473 v86int(); 474 result = (v86.efl & 0x1); 475 if (result == 0) 476 break; 477 } |
436 | 478 |
479 DEBUG("%d sectors from %d/%d/%d to %p (0x%x) %s", x, cyl, hd, sec - 1, p, VTOP(p), result ? "failed" : "ok"); 480 DEBUG("ax = 0x%04x cx = 0x%04x dx = 0x%04x status 0x%x\n", 481 0x200 | x, ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec, (hd << 8) | od->od_unit, (v86.eax >> 8) & 0xff); 482 if (result) { 483 if (bbuf != NULL) 484 free(bbuf); 485 return(-1); 486 } 487 if (bbuf != NULL) 488 bcopy(breg, p, x * BIOSDISK_SECSIZE); |
|
437 p += (x * BIOSDISK_SECSIZE); 438 dblk += x; 439 resid -= x; 440 } 441 442/* hexdump(dest, (blks * BIOSDISK_SECSIZE)); */ | 489 p += (x * BIOSDISK_SECSIZE); 490 dblk += x; 491 resid -= x; 492 } 493 494/* hexdump(dest, (blks * BIOSDISK_SECSIZE)); */ |
495 if (bbuf != NULL) 496 free(bbuf); |
|
443 return(0); 444} 445 446static int 447bd_getgeom(struct open_disk *od) 448{ 449 450 v86.ctl = V86_FLAGS; --- 19 unchanged lines hidden --- | 497 return(0); 498} 499 500static int 501bd_getgeom(struct open_disk *od) 502{ 503 504 v86.ctl = V86_FLAGS; --- 19 unchanged lines hidden --- |