Deleted Added
full compact
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}