Deleted Added
sdiff udiff text old ( 39724 ) new ( 39896 )
full compact
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.7 1998/09/28 20:07:39 peter 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
45#include <bootstrap.h>
46#include <btxv86.h>
47#include "libi386.h"
48
49#define BIOSDISK_SECSIZE 512
50#define BUFSIZE (1 * BIOSDISK_SECSIZE)
51#define MAXBDDEV MAXDEV
52
53#ifdef DISK_DEBUG
54# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __FUNCTION__ , ## args)
55#else
56# define DEBUG(fmt, args...)
57#endif
58
59
60struct open_disk {

--- 4 unchanged lines hidden (view full) ---

65 int od_sec;
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
88struct devsw biosdisk = {
89 "disk",
90 DEVT_DISK,
91 bd_init,
92 bd_strategy,
93 bd_open,
94 bd_close,
95 noioctl
96};
97
98/*
99 * List of BIOS devices, translation from disk unit number to
100 * BIOS unit number.
101 */
102static struct
103{
104 int bd_unit; /* BIOS unit number */
105 int bd_flags;
106} bdinfo [MAXBDDEV];
107static int nbdinfo = 0;
108
109/*
110 * Quiz the BIOS for disk devices, save a little info about them.
111 *
112 * XXX should we be consulting the BIOS equipment list, specifically
113 * the value at 0x475?
114 */
115static int
116bd_init(void)
117{
118 int base, unit;
119
120 /* sequence 0, 0x80 */
121 for (base = 0; base <= 0x80; base += 0x80) {
122 for (unit = base; (nbdinfo < MAXBDDEV); unit++) {
123 bdinfo[nbdinfo].bd_unit = -1;
124 bdinfo[nbdinfo].bd_flags = (unit < 0x80) ? BD_FLOPPY : 0;
125
126 if (bd_edd3probe(unit)) {
127 bdinfo[nbdinfo].bd_flags |= BD_MODEEDD3;
128 } else if (bd_edd1probe(unit)) {
129 bdinfo[nbdinfo].bd_flags |= BD_MODEEDD1;
130 } else if (bd_int13probe(unit)) {
131 bdinfo[nbdinfo].bd_flags |= BD_MODEINT13;
132 } else {
133 break;
134 }
135 /* XXX we need "disk aliases" to make this simpler */
136 printf("BIOS drive %c: is disk%d\n",
137 (unit < 0x80) ? ('A' + unit) : ('C' + unit - 0x80), nbdinfo);
138 bdinfo[nbdinfo].bd_unit = unit;
139 nbdinfo++;
140 }
141 }
142 return(0);
143}
144
145/*
146 * Try to detect a device supported by an Enhanced Disk Drive 3.0-compliant BIOS
147 */
148static int
149bd_edd3probe(int unit)
150{
151 return(0); /* XXX not implemented yet */
152}
153
154/*
155 * Try to detect a device supported by an Enhanced Disk Drive 1.1-compliant BIOS
156 */
157static int
158bd_edd1probe(int unit)
159{
160 return(0); /* XXX not implemented yet */
161}
162
163/*
164 * Try to detect a device supported by the legacy int13 BIOS
165 */
166
167static int
168bd_int13probe(int unit)
169{
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);
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.
188 * (eg. given no slice or partition value, with a disk that is
189 * sliced - are they after the first BSD slice, or the DOS
190 * slice before it?)
191 */
192static int
193bd_open(struct open_file *f, void *vdev)
194{
195 struct i386_devdesc *dev = (struct i386_devdesc *)vdev;
196 struct dos_partition *dptr;
197 struct open_disk *od;
198 struct disklabel *lp;
199 int sector, slice, i;
200 int error;
201
202 if (dev->d_kind.biosdisk.unit >= nbdinfo) {
203 DEBUG("attempt to open nonexistent disk");
204 return(ENXIO);
205 }
206
207 od = (struct open_disk *)malloc(sizeof(struct open_disk));
208 if (!od) {

--- 22 unchanged lines hidden (view full) ---

231 * Following calculations attempt to determine the correct value
232 * for d->od_boff by looking for the slice and partition specified,
233 * or searching for reasonable defaults.
234 */
235
236 /*
237 * Find the slice in the DOS slice table.
238 */
239 if (bd_read(od, 0, 1, od->od_buf)) {
240 DEBUG("error reading MBR");
241 error = EIO;
242 goto out;
243 }
244
245 /*
246 * Check the slice table magic.
247 */
248 if ((od->od_buf[0x1fe] != 0x55) || (od->od_buf[0x1ff] != 0xaa)) {
249 /* If a slice number was explicitly supplied, this is an error */
250 if (dev->d_kind.biosdisk.slice > 0) {
251 DEBUG("no slice table/MBR (no magic)");
252 error = ENOENT;
253 goto out;
254 }
255 sector = 0;
256 goto unsliced; /* may be a floppy */
257 }
258 dptr = (struct dos_partition *) & od->od_buf[DOSPARTOFF];
259
260 /*
261 * XXX No support here for 'extended' slices
262 */
263 if (dev->d_kind.biosdisk.slice <= 0) {
264 /*
265 * Search for the first FreeBSD slice; this also works on "unsliced"
266 * disks, as they contain a "historically bogus" MBR.

--- 27 unchanged lines hidden (view full) ---

294 *
295 * XXX we might want to check the label checksum.
296 */
297 if (dev->d_kind.biosdisk.partition < 0) {
298 od->od_boff = sector; /* no partition, must be after the slice */
299 DEBUG("opening raw slice");
300 } else {
301
302 if (bd_read(od, sector + LABELSECTOR, 1, od->od_buf)) {
303 DEBUG("error reading disklabel");
304 error = EIO;
305 goto out;
306 }
307 lp = (struct disklabel *) (od->od_buf + LABELOFFSET);
308
309 if (lp->d_magic != DISKMAGIC) {
310 DEBUG("no disklabel");
311 error = ENOENT;
312 goto out;
313 }
314 if (dev->d_kind.biosdisk.partition >= lp->d_npartitions) {
315 DEBUG("partition '%c' exceeds partitions in table (a-'%c')",

--- 5 unchanged lines hidden (view full) ---

321
322 /* Complain if the partition type is wrong */
323 if ((lp->d_partitions[dev->d_kind.biosdisk.partition].p_fstype == FS_UNUSED) &&
324 !(od->od_flags & BD_FLOPPY)) /* Floppies often have bogus fstype */
325 DEBUG("warning, partition marked as unused");
326
327 od->od_boff = lp->d_partitions[dev->d_kind.biosdisk.partition].p_offset;
328 }
329 /*
330 * Save our context
331 */
332 ((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data = od;
333 DEBUG("open_disk %p, partition at 0x%x", od, od->od_boff);
334
335 out:
336 if (error)
337 free(od);
338 return(error);
339}
340
341static int
342bd_close(struct open_file *f)
343{
344 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data);
345
346 DEBUG("open_disk %p", od);
347#if 0
348 /* XXX is this required? (especially if disk already open...) */
349 if (od->od_flags & BD_FLOPPY)
350 delay(3000000);
351#endif
352 free(od);
353 return(0);
354}
355
356static int
357bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize)
358{
359 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data);
360 int blks;
361#ifdef BD_SUPPORT_FRAGS

--- 154 unchanged lines hidden (view full) ---

516 /* convert max head # -> # of heads */
517 od->od_hds = ((v86.edx & 0xff00) >> 8) + 1;
518 od->od_sec = v86.ecx & 0x3f;
519
520
521 DEBUG("unit 0x%x geometry %d/%d/%d", od->od_unit, od->od_cyl, od->od_hds, od->od_sec);
522 return(0);
523}