biosdisk.c (38466) | biosdisk.c (39441) |
---|---|
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$ | 26 * $Id: biosdisk.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $ |
27 */ 28 29/* 30 * BIOS disk device handling. 31 * 32 * Ideas and algorithms from: 33 * 34 * - NetBSD libi386/biosdisk.c 35 * - FreeBSD biosboot/disk.c 36 * 37 * XXX Todo: add bad144 support. 38 */ 39 40#include <stand.h> 41 42#include <sys/disklabel.h> 43#include <sys/diskslice.h> 44 | 27 */ 28 29/* 30 * BIOS disk device handling. 31 * 32 * Ideas and algorithms from: 33 * 34 * - NetBSD libi386/biosdisk.c 35 * - FreeBSD biosboot/disk.c 36 * 37 * XXX Todo: add bad144 support. 38 */ 39 40#include <stand.h> 41 42#include <sys/disklabel.h> 43#include <sys/diskslice.h> 44 |
45#include "bootstrap.h" | 45#include <bootstrap.h> 46#include <btxv86.h> |
46#include "libi386.h" 47#include "crt/biosdisk_ll.h" 48 49#define BUFSIZE (1 * BIOSDISK_SECSIZE) 50#define MAXBDDEV MAXDEV 51 52#ifdef DISK_DEBUG 53# define D(x) x 54#else 55# define D(x) 56#endif 57 | 47#include "libi386.h" 48#include "crt/biosdisk_ll.h" 49 50#define BUFSIZE (1 * BIOSDISK_SECSIZE) 51#define MAXBDDEV MAXDEV 52 53#ifdef DISK_DEBUG 54# define D(x) x 55#else 56# define D(x) 57#endif 58 |
58/* biosdisk_support.S */ 59extern u_long bd_int13fn8(int unit); | |
60 | 59 |
61static int bd_edd3probe(int unit); 62static int bd_edd1probe(int unit); 63static int bd_int13probe(int unit); 64 65static int bd_init(void); 66static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize); 67static int bd_open(struct open_file *f, void *vdev); 68static int bd_close(struct open_file *f); 69 | |
70struct open_disk { | 60struct open_disk { |
71 struct biosdisk_ll od_ll; /* contains bios unit, geometry (XXX absorb) */ 72 int od_unit; /* our unit number */ | 61 int od_dkunit; /* disk unit number */ 62 int od_unit; /* BIOS unit number */ 63 int od_cyl; /* BIOS geometry */ 64 int od_hds; 65 int od_sec; |
73 int od_boff; /* block offset from beginning of BIOS disk */ 74 int od_flags; 75#define BD_MODEMASK 0x3 76#define BD_MODEINT13 0x0 77#define BD_MODEEDD1 0x1 78#define BD_MODEEDD3 0x2 79#define BD_FLOPPY (1<<2) 80 u_char od_buf[BUFSIZE]; /* transfer buffer (do we want/need this?) */ 81}; 82 | 66 int od_boff; /* block offset from beginning of BIOS disk */ 67 int od_flags; 68#define BD_MODEMASK 0x3 69#define BD_MODEINT13 0x0 70#define BD_MODEEDD1 0x1 71#define BD_MODEEDD3 0x2 72#define BD_FLOPPY (1<<2) 73 u_char od_buf[BUFSIZE]; /* transfer buffer (do we want/need this?) */ 74}; 75 |
76static int bd_getgeom(struct open_disk *od); 77static int bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest); 78 79static int bd_edd3probe(int unit); 80static int bd_edd1probe(int unit); 81static int bd_int13probe(int unit); 82 83static int bd_init(void); 84static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize); 85static int bd_open(struct open_file *f, void *vdev); 86static int bd_close(struct open_file *f); 87 |
|
83struct devsw biosdisk = { 84 "disk", 85 DEVT_DISK, 86 bd_init, 87 bd_strategy, 88 bd_open, 89 bd_close, 90 noioctl --- 66 unchanged lines hidden (view full) --- 157 158/* 159 * Try to detect a device supported by the legacy int13 BIOS 160 */ 161 162static int 163bd_int13probe(int unit) 164{ | 88struct devsw biosdisk = { 89 "disk", 90 DEVT_DISK, 91 bd_init, 92 bd_strategy, 93 bd_open, 94 bd_close, 95 noioctl --- 66 unchanged lines hidden (view full) --- 162 163/* 164 * Try to detect a device supported by the legacy int13 BIOS 165 */ 166 167static int 168bd_int13probe(int unit) 169{ |
165 u_long geom; 166 167 /* try int 0x13, function 8 */ 168 geom = bd_int13fn8(unit); 169 170 return(geom != 0); | 170 v86.ctl = V86_FLAGS; 171 v86.addr = 0x13; 172 v86.eax = 0x800; 173 v86.edx = unit; 174 v86int(); 175 176 if (!(v86.efl & 0x1) && /* carry clear */ 177 ((v86.edx & 0xff) > unit & 0x7f)) /* unit # OK */ 178 return(1); 179 return(0); |
171} 172 173/* 174 * Attempt to open the disk described by (dev) for use by (f). 175 * 176 * Note that the philosophy here is "give them exactly what 177 * they ask for". This is necessary because being too "smart" 178 * about what the user might want leads to complications. --- 18 unchanged lines hidden (view full) --- 197 198 od = (struct open_disk *)malloc(sizeof(struct open_disk)); 199 if (!od) { 200 D(printf("bd_open: no memory\n")); 201 return (ENOMEM); 202 } 203 204 /* Look up BIOS unit number, intialise open_disk structure */ | 180} 181 182/* 183 * Attempt to open the disk described by (dev) for use by (f). 184 * 185 * Note that the philosophy here is "give them exactly what 186 * they ask for". This is necessary because being too "smart" 187 * about what the user might want leads to complications. --- 18 unchanged lines hidden (view full) --- 206 207 od = (struct open_disk *)malloc(sizeof(struct open_disk)); 208 if (!od) { 209 D(printf("bd_open: no memory\n")); 210 return (ENOMEM); 211 } 212 213 /* Look up BIOS unit number, intialise open_disk structure */ |
205 od->od_unit = dev->d_kind.biosdisk.unit; 206 od->od_ll.dev = bdinfo[od->od_unit].bd_unit; 207 od->od_flags = bdinfo[od->od_unit].bd_flags; | 214 od->od_dkunit = dev->d_kind.biosdisk.unit; 215 od->od_unit = bdinfo[od->od_dkunit].bd_unit; 216 od->od_flags = bdinfo[od->od_dkunit].bd_flags; |
208 od->od_boff = 0; 209 error = 0; 210#if 0 211 D(printf("bd_open: open '%s' - unit 0x%x slice %d partition %c\n", 212 i386_fmtdev(dev), dev->d_kind.biosdisk.unit, 213 dev->d_kind.biosdisk.slice, dev->d_kind.biosdisk.partition + 'a')); 214#endif 215 216 /* Get geometry for this open (removable device may have changed) */ | 217 od->od_boff = 0; 218 error = 0; 219#if 0 220 D(printf("bd_open: open '%s' - unit 0x%x slice %d partition %c\n", 221 i386_fmtdev(dev), dev->d_kind.biosdisk.unit, 222 dev->d_kind.biosdisk.slice, dev->d_kind.biosdisk.partition + 'a')); 223#endif 224 225 /* Get geometry for this open (removable device may have changed) */ |
217 if (set_geometry(&od->od_ll)) { | 226 if (bd_getgeom(od)) { |
218 D(printf("bd_open: can't get geometry\n")); 219 error = ENXIO; 220 goto out; 221 } 222 223 /* 224 * Following calculations attempt to determine the correct value 225 * for d->od_boff by looking for the slice and partition specified, 226 * or searching for reasonable defaults. 227 */ 228 229 /* 230 * Find the slice in the DOS slice table. 231 */ | 227 D(printf("bd_open: can't get geometry\n")); 228 error = ENXIO; 229 goto out; 230 } 231 232 /* 233 * Following calculations attempt to determine the correct value 234 * for d->od_boff by looking for the slice and partition specified, 235 * or searching for reasonable defaults. 236 */ 237 238 /* 239 * Find the slice in the DOS slice table. 240 */ |
232 if (readsects(&od->od_ll, 0, 1, od->od_buf, 0)) { | 241 if (bd_read(od, 0, 1, od->od_buf)) { |
233 D(printf("bd_open: error reading MBR\n")); 234 error = EIO; 235 goto out; 236 } 237 238 /* 239 * Check the slice table magic. 240 */ --- 46 unchanged lines hidden (view full) --- 287 * 288 * XXX we might want to check the label checksum. 289 */ 290 if (dev->d_kind.biosdisk.partition < 0) { 291 od->od_boff = sector; /* no partition, must be after the slice */ 292 D(printf("bd_open: opening raw slice\n")); 293 } else { 294 | 242 D(printf("bd_open: error reading MBR\n")); 243 error = EIO; 244 goto out; 245 } 246 247 /* 248 * Check the slice table magic. 249 */ --- 46 unchanged lines hidden (view full) --- 296 * 297 * XXX we might want to check the label checksum. 298 */ 299 if (dev->d_kind.biosdisk.partition < 0) { 300 od->od_boff = sector; /* no partition, must be after the slice */ 301 D(printf("bd_open: opening raw slice\n")); 302 } else { 303 |
295 if (readsects(&od->od_ll, sector + LABELSECTOR, 1, od->od_buf, 0)) { | 304 if (bd_read(od, sector + LABELSECTOR, 1, od->od_buf)) { |
296 D(printf("bd_open: error reading disklabel\n")); 297 error = EIO; 298 goto out; 299 } 300 lp = (struct disklabel *) (od->od_buf + LABELOFFSET); 301 if (lp->d_magic != DISKMAGIC) { 302 D(printf("bd_open: no disklabel\n")); 303 error = ENOENT; --- 39 unchanged lines hidden (view full) --- 343static int 344bd_close(struct open_file *f) 345{ 346 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data); 347 348#if 0 349 D(printf("bd_close: open_disk %p\n", od)); 350#endif | 305 D(printf("bd_open: error reading disklabel\n")); 306 error = EIO; 307 goto out; 308 } 309 lp = (struct disklabel *) (od->od_buf + LABELOFFSET); 310 if (lp->d_magic != DISKMAGIC) { 311 D(printf("bd_open: no disklabel\n")); 312 error = ENOENT; --- 39 unchanged lines hidden (view full) --- 352static int 353bd_close(struct open_file *f) 354{ 355 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data); 356 357#if 0 358 D(printf("bd_close: open_disk %p\n", od)); 359#endif |
351 | 360#if 0 |
352 /* XXX is this required? (especially if disk already open...) */ 353 if (od->od_flags & BD_FLOPPY) 354 delay(3000000); | 361 /* XXX is this required? (especially if disk already open...) */ 362 if (od->od_flags & BD_FLOPPY) 363 delay(3000000); |
355 | 364#endif |
356 free(od); 357 return(0); 358} 359 360static int 361bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize) 362{ 363 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data); --- 18 unchanged lines hidden (view full) --- 382 383 blks = size / BIOSDISK_SECSIZE; 384#if 0 385 D(printf("bd_strategy: read %d from %d+%d to %p\n", blks, od->od_boff, dblk, buf)); 386#endif 387 388 if (rsize) 389 *rsize = 0; | 365 free(od); 366 return(0); 367} 368 369static int 370bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize) 371{ 372 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data); --- 18 unchanged lines hidden (view full) --- 391 392 blks = size / BIOSDISK_SECSIZE; 393#if 0 394 D(printf("bd_strategy: read %d from %d+%d to %p\n", blks, od->od_boff, dblk, buf)); 395#endif 396 397 if (rsize) 398 *rsize = 0; |
390 if (blks && readsects(&od->od_ll, dblk + od->od_boff, blks, buf, 0)) { | 399 if (blks && bd_read(od, dblk + od->od_boff, blks, buf)) { |
391 D(printf("read error\n")); 392 return (EIO); 393 } 394#ifdef BD_SUPPORT_FRAGS 395#if 0 396 D(printf("bd_strategy: frag read %d from %d+%d+d to %p\n", 397#endif 398 fragsize, od->od_boff, dblk, blks, buf + (blks * BIOSDISK_SECSIZE))); | 400 D(printf("read error\n")); 401 return (EIO); 402 } 403#ifdef BD_SUPPORT_FRAGS 404#if 0 405 D(printf("bd_strategy: frag read %d from %d+%d+d to %p\n", 406#endif 407 fragsize, od->od_boff, dblk, blks, buf + (blks * BIOSDISK_SECSIZE))); |
399 if (fragsize && readsects(&od->od_ll, dblk + od->od_boff + blks, 1, fragsize, 0)) { | 408 if (fragsize && bd_read(od, dblk + od->od_boff + blks, 1, fragsize)) { |
400 D(printf("frag read error\n")); 401 return(EIO); 402 } 403 bcopy(fragbuf, buf + (blks * BIOSDISK_SECSIZE), fragsize); 404#endif 405 if (rsize) 406 *rsize = size; 407 return (0); 408} | 409 D(printf("frag read error\n")); 410 return(EIO); 411 } 412 bcopy(fragbuf, buf + (blks * BIOSDISK_SECSIZE), fragsize); 413#endif 414 if (rsize) 415 *rsize = size; 416 return (0); 417} |
418 419static int 420bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest) 421{ 422 int x, bpc, cyl, hd, sec; 423 424 bpc = (od->od_sec * od->od_hds); /* blocks per cylinder */ 425 v86.ctl = V86_FLAGS; 426 v86.addr = 0x13; 427 428 while (blks != 0) { 429 x = dblk; 430 cyl = x / bpc; /* block # / blocks per cylinder */ 431 x %= bpc; /* block offset into cylinder */ 432 hd = x / od->od_sec; /* offset / blocks per track */ 433 sec = x % od->od_sec; /* offset into track */ 434 435 /* play it safe and don't cross track boundaries */ 436 x = min (od->od_sec - sec, blks); 437 438 /* correct sector number for 1-based BIOS numbering */ 439 sec++; 440 441 /* build request XXX support EDD requests too */ 442 v86.eax = 0x200 | x; 443 v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec; 444 v86.edx = (hd << 8) | od->od_unit; 445 v86.es = V86SEG(dest); 446 v86.ebx = V86OFS(dest); 447 v86int(); 448 if (v86.efl & 0x1) 449 return(-1); 450 451 dest + (x * BIOSDISK_SECSIZE); 452 dblk += x; 453 blks -= x; 454 } 455 return(0); 456} 457 458static int 459bd_getgeom(struct open_disk *od) 460{ 461 462 v86.ctl = V86_FLAGS; 463 v86.addr = 0x13; 464 v86.eax = 0x800; 465 v86.edx = od->od_unit; 466 v86int(); 467 468 if ((v86.efl & 0x1) || /* carry set */ 469 ((v86.edx & 0xff) <= (od->od_unit & 0x7f))) /* unit # bad */ 470 return(1); 471 472 /* convert max cyl # -> # of cylinders */ 473 od->od_cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1; 474 /* convert max head # -> # of heads */ 475 od->od_hds = ((v86.edx & 0xff00) >> 8) + 1; 476 od->od_sec = v86.ecx & 0x3f; 477 return(0); 478} |
|