39
40 #include <sys/disk.h>
41 #include <sys/limits.h>
42 #include <stand.h>
43 #include <machine/bootinfo.h>
44 #include <stdarg.h>
45
46 #include <bootstrap.h>
47 #include <btxv86.h>
48 #include <edd.h>
49 #include "disk.h"
50 #include "libi386.h"
51
52 CTASSERT(sizeof(struct i386_devdesc) >= sizeof(struct disk_devdesc));
53
54 #define BIOS_NUMDRIVES 0x475
55 #define BIOSDISK_SECSIZE 512
56 #define BUFSIZE (1 * BIOSDISK_SECSIZE)
57
58 #define DT_ATAPI 0x10 /* disk type for ATAPI floppies */
59 #define WDMAJOR 0 /* major numbers for devices we frontend for */
60 #define WFDMAJOR 1
61 #define FDMAJOR 2
62 #define DAMAJOR 4
63
64 #ifdef DISK_DEBUG
65 # define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
66 #else
67 # define DEBUG(fmt, args...)
68 #endif
69
70 /*
71 * List of BIOS devices, translation from disk unit number to
72 * BIOS unit number.
73 */
74 static struct bdinfo
75 {
76 int bd_unit; /* BIOS unit number */
77 int bd_cyl; /* BIOS geometry */
78 int bd_hds;
79 int bd_sec;
80 int bd_flags;
81 #define BD_MODEINT13 0x0000
82 #define BD_MODEEDD1 0x0001
83 #define BD_MODEEDD3 0x0002
84 #define BD_MODEMASK 0x0003
85 #define BD_FLOPPY 0x0004
86 int bd_type; /* BIOS 'drive type' (floppy only) */
87 uint16_t bd_sectorsize; /* Sector size */
88 uint64_t bd_sectors; /* Disk size */
89 int bd_open; /* reference counter */
90 void *bd_bcache; /* buffer cache data */
91 } bdinfo [MAXBDDEV];
92 static int nbdinfo = 0;
93
94 #define BD(dev) (bdinfo[(dev)->d_unit])
95
96 static int bd_io(struct disk_devdesc *, daddr_t, int, caddr_t, int);
97 static int bd_int13probe(struct bdinfo *bd);
98
99 static int bd_init(void);
100 static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
101 char *buf, size_t *rsize);
102 static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size,
103 char *buf, size_t *rsize);
104 static int bd_open(struct open_file *f, ...);
105 static int bd_close(struct open_file *f);
106 static int bd_ioctl(struct open_file *f, u_long cmd, void *data);
107 static int bd_print(int verbose);
108
109 struct devsw biosdisk = {
110 "disk",
111 DEVT_DISK,
112 bd_init,
113 bd_strategy,
114 bd_open,
115 bd_close,
116 bd_ioctl,
117 bd_print,
118 NULL
119 };
120
121 /*
122 * Translate between BIOS device numbers and our private unit numbers.
123 */
124 int
125 bd_bios2unit(int biosdev)
126 {
127 int i;
128
129 DEBUG("looking for bios device 0x%x", biosdev);
130 for (i = 0; i < nbdinfo; i++) {
131 DEBUG("bd unit %d is BIOS device 0x%x", i, bdinfo[i].bd_unit);
132 if (bdinfo[i].bd_unit == biosdev)
133 return (i);
134 }
135 return (-1);
136 }
137
138 int
169 bdinfo[nbdinfo].bd_unit = unit;
170 bdinfo[nbdinfo].bd_flags = unit < 0x80 ? BD_FLOPPY: 0;
171 if (!bd_int13probe(&bdinfo[nbdinfo]))
172 break;
173
174 #ifndef BOOT2
175 /* XXX we need "disk aliases" to make this simpler */
176 printf("BIOS drive %c: is disk%d\n", (unit < 0x80) ?
177 ('A' + unit): ('C' + unit - 0x80), nbdinfo);
178 #endif
179 nbdinfo++;
180 if (base == 0x80)
181 nfd++;
182 }
183 }
184 bcache_add_dev(nbdinfo);
185 return(0);
186 }
187
188 /*
189 * Try to detect a device supported by the legacy int13 BIOS
190 */
191 static int
192 bd_int13probe(struct bdinfo *bd)
193 {
194 struct edd_params params;
195 int ret = 1; /* assume success */
196
197 v86.ctl = V86_FLAGS;
198 v86.addr = 0x13;
199 v86.eax = 0x800;
200 v86.edx = bd->bd_unit;
201 v86int();
202
203 /* Don't error out if we get bad sector number, try EDD as well */
204 if (V86_CY(v86.efl) || /* carry set */
205 (v86.edx & 0xff) <= (unsigned)(bd->bd_unit & 0x7f)) /* unit # bad */
206 return (0); /* skip device */
207
208 if ((v86.ecx & 0x3f) == 0) /* absurd sector number */
209 ret = 0; /* set error */
210
211 /* Convert max cyl # -> # of cylinders */
212 bd->bd_cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1;
213 /* Convert max head # -> # of heads */
214 bd->bd_hds = ((v86.edx & 0xff00) >> 8) + 1;
215 bd->bd_sec = v86.ecx & 0x3f;
216 bd->bd_type = v86.ebx & 0xff;
217 bd->bd_flags |= BD_MODEINT13;
218
219 /* Calculate sectors count from the geometry */
220 bd->bd_sectors = bd->bd_cyl * bd->bd_hds * bd->bd_sec;
221 bd->bd_sectorsize = BIOSDISK_SECSIZE;
222 DEBUG("unit 0x%x geometry %d/%d/%d", bd->bd_unit, bd->bd_cyl,
223 bd->bd_hds, bd->bd_sec);
224
225 /* Determine if we can use EDD with this device. */
226 v86.ctl = V86_FLAGS;
227 v86.addr = 0x13;
228 v86.eax = 0x4100;
229 v86.edx = bd->bd_unit;
230 v86.ebx = 0x55aa;
231 v86int();
232 if (V86_CY(v86.efl) || /* carry set */
233 (v86.ebx & 0xffff) != 0xaa55 || /* signature */
234 (v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0)
235 return (ret); /* return code from int13 AH=08 */
236
237 /* EDD supported */
238 bd->bd_flags |= BD_MODEEDD1;
239 if ((v86.eax & 0xff00) >= 0x3000)
240 bd->bd_flags |= BD_MODEEDD3;
241 /* Get disk params */
242 params.len = sizeof(struct edd_params);
243 v86.ctl = V86_FLAGS;
244 v86.addr = 0x13;
245 v86.eax = 0x4800;
246 v86.edx = bd->bd_unit;
247 v86.ds = VTOPSEG(¶ms);
248 v86.esi = VTOPOFF(¶ms);
249 v86int();
250 if (!V86_CY(v86.efl)) {
251 uint64_t total;
252
253 /*
254 * Sector size must be a multiple of 512 bytes.
255 * An alternate test would be to check power of 2,
256 * powerof2(params.sector_size).
257 */
258 if (params.sector_size % BIOSDISK_SECSIZE)
259 bd->bd_sectorsize = BIOSDISK_SECSIZE;
260 else
261 bd->bd_sectorsize = params.sector_size;
262
263 total = bd->bd_sectorsize * params.sectors;
264 if (params.sectors != 0) {
265 /* Only update if we did not overflow. */
266 if (total > params.sectors)
267 bd->bd_sectors = params.sectors;
268 }
269
270 total = (uint64_t)params.cylinders *
271 params.heads * params.sectors_per_track;
272 if (bd->bd_sectors < total)
273 bd->bd_sectors = total;
274
275 ret = 1;
276 }
277 DEBUG("unit 0x%x flags %x, sectors %llu, sectorsize %u",
278 bd->bd_unit, bd->bd_flags, bd->bd_sectors, bd->bd_sectorsize);
279 return (ret);
280 }
281
282 /*
283 * Print information about disks
284 */
285 static int
286 bd_print(int verbose)
287 {
288 static char line[80];
289 struct disk_devdesc dev;
290 int i, ret = 0;
291
292 if (nbdinfo == 0)
293 return (0);
294
295 printf("%s devices:", biosdisk.dv_name);
296 if ((ret = pager_output("\n")) != 0)
297 return (ret);
298
299 for (i = 0; i < nbdinfo; i++) {
300 snprintf(line, sizeof (line),
301 " disk%d: BIOS drive %c (%ju X %u):\n", i,
302 (bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit):
303 ('C' + bdinfo[i].bd_unit - 0x80),
304 (uintmax_t)bdinfo[i].bd_sectors,
305 bdinfo[i].bd_sectorsize);
306 ret = pager_output(line);
307 if (ret != 0)
308 return (ret);
309
310 dev.d_dev = &biosdisk;
311 dev.d_unit = i;
312 dev.d_slice = -1;
313 dev.d_partition = -1;
314 if (disk_open(&dev,
315 bdinfo[i].bd_sectorsize * bdinfo[i].bd_sectors,
316 bdinfo[i].bd_sectorsize) == 0) {
317 sprintf(line, " disk%d", i);
318 ret = disk_print(&dev, line, verbose);
319 disk_close(&dev);
320 if (ret != 0)
321 return (ret);
322 }
323 }
332 * about what the user might want leads to complications.
333 * (eg. given no slice or partition value, with a disk that is
334 * sliced - are they after the first BSD slice, or the DOS
335 * slice before it?)
336 */
337 static int
338 bd_open(struct open_file *f, ...)
339 {
340 struct disk_devdesc *dev;
341 struct disk_devdesc disk;
342 va_list ap;
343 uint64_t size;
344 int rc;
345
346 va_start(ap, f);
347 dev = va_arg(ap, struct disk_devdesc *);
348 va_end(ap);
349
350 if (dev->d_unit < 0 || dev->d_unit >= nbdinfo)
351 return (EIO);
352 BD(dev).bd_open++;
353 if (BD(dev).bd_bcache == NULL)
354 BD(dev).bd_bcache = bcache_allocate();
355
356 /*
357 * Read disk size from partition.
358 * This is needed to work around buggy BIOS systems returning
359 * wrong (truncated) disk media size.
360 * During bd_probe() we tested if the mulitplication of bd_sectors
361 * would overflow so it should be safe to perform here.
362 */
363 disk.d_dev = dev->d_dev;
364 disk.d_type = dev->d_type;
365 disk.d_unit = dev->d_unit;
366 disk.d_opendata = NULL;
367 disk.d_slice = -1;
368 disk.d_partition = -1;
369 disk.d_offset = 0;
370
371 if (disk_open(&disk, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
651 if (V86_CY(v86.efl))
652 return (v86.eax >> 8);
653 return (0);
654 }
655
656 static int
657 bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
658 int dowrite)
659 {
660 u_int result, retry;
661
662 /* Just in case some idiot actually tries to read/write -1 blocks... */
663 if (blks < 0)
664 return (-1);
665
666 /*
667 * Loop retrying the operation a couple of times. The BIOS
668 * may also retry.
669 */
670 for (retry = 0; retry < 3; retry++) {
671 /* if retrying, reset the drive */
672 if (retry > 0) {
673 v86.ctl = V86_FLAGS;
674 v86.addr = 0x13;
675 v86.eax = 0;
676 v86.edx = BD(dev).bd_unit;
677 v86int();
678 }
679
680 if (BD(dev).bd_flags & BD_MODEEDD1)
681 result = bd_edd_io(dev, dblk, blks, dest, dowrite);
682 else
683 result = bd_chs_io(dev, dblk, blks, dest, dowrite);
684
685 if (result == 0)
686 break;
687 }
688
689 /*
690 * 0x20 - Controller failure. This is common error when the
691 * media is not present.
692 */
693 if (result != 0 && result != 0x20) {
694 if (dowrite != 0) {
695 printf("%s%d: Write %d sector(s) from %p (0x%x) "
696 "to %lld: 0x%x", dev->d_dev->dv_name, dev->d_unit,
697 blks, dest, VTOP(dest), dblk, result);
698 } else {
699 printf("%s%d: Read %d sector(s) from %lld to %p "
700 "(0x%x): 0x%x", dev->d_dev->dv_name, dev->d_unit,
701 blks, dblk, dest, VTOP(dest), result);
702 }
703
704 if (result != 0)
705 return (result);
706 }
707
708 return(0);
709 }
710
711 /*
712 * Return the BIOS geometry of a given "fixed drive" in a format
713 * suitable for the legacy bootinfo structure. Since the kernel is
714 * expecting raw int 0x13/0x8 values for N_BIOS_GEOM drives, we
715 * prefer to get the information directly, rather than rely on being
716 * able to put it together from information already maintained for
717 * different purposes and for a probably different number of drives.
718 *
719 * For valid drives, the geometry is expected in the format (31..0)
720 * "000000cc cccccccc hhhhhhhh 00ssssss"; and invalid drives are
721 * indicated by returning the geometry of a "1.2M" PC-format floppy
722 * disk. And, incidentally, what is returned is not the geometry as
723 * such but the highest valid cylinder, head, and sector numbers.
724 */
725 u_int32_t
726 bd_getbigeom(int bunit)
727 {
728
|
39
40 #include <sys/disk.h>
41 #include <sys/limits.h>
42 #include <stand.h>
43 #include <machine/bootinfo.h>
44 #include <stdarg.h>
45
46 #include <bootstrap.h>
47 #include <btxv86.h>
48 #include <edd.h>
49 #include "disk.h"
50 #include "libi386.h"
51
52 CTASSERT(sizeof(struct i386_devdesc) >= sizeof(struct disk_devdesc));
53
54 #define BIOS_NUMDRIVES 0x475
55 #define BIOSDISK_SECSIZE 512
56 #define BUFSIZE (1 * BIOSDISK_SECSIZE)
57
58 #define DT_ATAPI 0x10 /* disk type for ATAPI floppies */
59
60 /* major numbers for devices we frontend for */
61 #define WDMAJOR 0
62 #define WFDMAJOR 1
63 #define FDMAJOR 2
64 #define DAMAJOR 4
65
66 #ifdef DISK_DEBUG
67 # define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
68 #else
69 # define DEBUG(fmt, args...)
70 #endif
71
72 /*
73 * List of BIOS devices, translation from disk unit number to
74 * BIOS unit number.
75 */
76 static struct bdinfo
77 {
78 int bd_unit; /* BIOS unit number */
79 int bd_cyl; /* BIOS geometry */
80 int bd_hds;
81 int bd_sec;
82 int bd_flags;
83 #define BD_MODEINT13 0x0000
84 #define BD_MODEEDD1 0x0001
85 #define BD_MODEEDD3 0x0002
86 #define BD_MODEEDD (BD_MODEEDD1 | BD_MODEEDD3)
87 #define BD_MODEMASK 0x0003
88 #define BD_FLOPPY 0x0004
89 #define BD_NO_MEDIA 0x0008
90 int bd_type; /* BIOS 'drive type' (floppy only) */
91 uint16_t bd_sectorsize; /* Sector size */
92 uint64_t bd_sectors; /* Disk size */
93 int bd_open; /* reference counter */
94 void *bd_bcache; /* buffer cache data */
95 } bdinfo [MAXBDDEV];
96 static int nbdinfo = 0;
97
98 #define BD(dev) (bdinfo[(dev)->d_unit])
99
100 static int bd_io(struct disk_devdesc *, daddr_t, int, caddr_t, int);
101 static int bd_int13probe(struct bdinfo *bd);
102
103 static int bd_init(void);
104 static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
105 char *buf, size_t *rsize);
106 static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size,
107 char *buf, size_t *rsize);
108 static int bd_open(struct open_file *f, ...);
109 static int bd_close(struct open_file *f);
110 static int bd_ioctl(struct open_file *f, u_long cmd, void *data);
111 static int bd_print(int verbose);
112
113 struct devsw biosfd = {
114 .dv_name = "fd",
115 .dv_type = DEVT_FD,
116 .dv_init = bd_init,
117 .dv_strategy = bd_strategy,
118 .dv_open = bd_open,
119 .dv_close = bd_close,
120 .dv_ioctl = bd_ioctl,
121 .dv_print = bd_print,
122 .dv_cleanup = NULL
123 };
124
125 #if 0
126 struct devsw bioscd = {
127 .dv_name = "cd",
128 .dv_type = DEVT_CD,
129 .dv_init = bd_init,
130 .dv_strategy = bd_strategy,
131 .dv_open = bd_open,
132 .dv_close = bd_close,
133 .dv_ioctl = bd_ioctl,
134 .dv_print = bd_print,
135 .dv_cleanup = NULL
136 };
137 #endif
138
139 struct devsw biosdisk = {
140 .dv_name = "disk",
141 .dv_type = DEVT_DISK,
142 .dv_init = bd_init,
143 .dv_strategy = bd_strategy,
144 .dv_open = bd_open,
145 .dv_close = bd_close,
146 .dv_ioctl = bd_ioctl,
147 .dv_print = bd_print,
148 .dv_cleanup = NULL
149 };
150
151 /*
152 * Translate between BIOS device numbers and our private unit numbers.
153 */
154 int
155 bd_bios2unit(int biosdev)
156 {
157 int i;
158
159 DEBUG("looking for bios device 0x%x", biosdev);
160 for (i = 0; i < nbdinfo; i++) {
161 DEBUG("bd unit %d is BIOS device 0x%x", i, bdinfo[i].bd_unit);
162 if (bdinfo[i].bd_unit == biosdev)
163 return (i);
164 }
165 return (-1);
166 }
167
168 int
199 bdinfo[nbdinfo].bd_unit = unit;
200 bdinfo[nbdinfo].bd_flags = unit < 0x80 ? BD_FLOPPY: 0;
201 if (!bd_int13probe(&bdinfo[nbdinfo]))
202 break;
203
204 #ifndef BOOT2
205 /* XXX we need "disk aliases" to make this simpler */
206 printf("BIOS drive %c: is disk%d\n", (unit < 0x80) ?
207 ('A' + unit): ('C' + unit - 0x80), nbdinfo);
208 #endif
209 nbdinfo++;
210 if (base == 0x80)
211 nfd++;
212 }
213 }
214 bcache_add_dev(nbdinfo);
215 return(0);
216 }
217
218 /*
219 * Return EDD version or 0 if EDD is not supported on this drive.
220 */
221 static int
222 bd_check_extensions(int unit)
223 {
224 /* Determine if we can use EDD with this device. */
225 v86.ctl = V86_FLAGS;
226 v86.addr = 0x13;
227 v86.eax = 0x4100;
228 v86.edx = unit;
229 v86.ebx = 0x55aa;
230 v86int();
231
232 if (V86_CY(v86.efl) || /* carry set */
233 (v86.ebx & 0xffff) != 0xaa55) /* signature */
234 return (0);
235
236 /* extended disk access functions (AH=42h-44h,47h,48h) supported */
237 if ((v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0)
238 return (0);
239
240 return ((v86.eax >> 8) & 0xff);
241 }
242
243 static void
244 bd_reset_disk(int unit)
245 {
246 /* reset disk */
247 v86.ctl = V86_FLAGS;
248 v86.addr = 0x13;
249 v86.eax = 0;
250 v86.edx = unit;
251 v86int();
252 }
253
254 /*
255 * Read CHS info. Return 0 on success, error otherwise.
256 */
257 static int
258 bd_get_diskinfo_std(struct bdinfo *bd)
259 {
260 bzero(&v86, sizeof (v86));
261 v86.ctl = V86_FLAGS;
262 v86.addr = 0x13;
263 v86.eax = 0x800;
264 v86.edx = bd->bd_unit;
265 v86int();
266
267 if (V86_CY(v86.efl) && ((v86.eax & 0xff00) != 0))
268 return ((v86.eax & 0xff00) >> 8);
269
270 /* return custom error on absurd sector number */
271 if ((v86.ecx & 0x3f) == 0)
272 return (0x60);
273
274 bd->bd_cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1;
275 /* Convert max head # -> # of heads */
276 bd->bd_hds = ((v86.edx & 0xff00) >> 8) + 1;
277 bd->bd_sec = v86.ecx & 0x3f;
278 bd->bd_type = v86.ebx;
279 bd->bd_sectors = (uint64_t)bd->bd_cyl * bd->bd_hds * bd->bd_sec;
280
281 return (0);
282 }
283
284 /*
285 * Read EDD info. Return 0 on success, error otherwise.
286 */
287 static int
288 bd_get_diskinfo_ext(struct bdinfo *bd)
289 {
290 struct edd_params params;
291 uint64_t total;
292
293 /* Get disk params */
294 bzero(¶ms, sizeof (params));
295 params.len = sizeof (params);
296 v86.ctl = V86_FLAGS;
297 v86.addr = 0x13;
298 v86.eax = 0x4800;
299 v86.edx = bd->bd_unit;
300 v86.ds = VTOPSEG(¶ms);
301 v86.esi = VTOPOFF(¶ms);
302 v86int();
303
304 if (V86_CY(v86.efl) && ((v86.eax & 0xff00) != 0))
305 return ((v86.eax & 0xff00) >> 8);
306
307 /*
308 * Sector size must be a multiple of 512 bytes.
309 * An alternate test would be to check power of 2,
310 * powerof2(params.sector_size).
311 */
312 if (params.sector_size % BIOSDISK_SECSIZE)
313 bd->bd_sectorsize = BIOSDISK_SECSIZE;
314 else
315 bd->bd_sectorsize = params.sector_size;
316
317 bd->bd_cyl = params.cylinders;
318 bd->bd_hds = params.heads;
319 bd->bd_sec = params.sectors_per_track;
320
321 if (params.sectors != 0) {
322 total = params.sectors;
323 } else {
324 total = (uint64_t)params.cylinders *
325 params.heads * params.sectors_per_track;
326 }
327 bd->bd_sectors = total;
328
329 return (0);
330 }
331
332 /*
333 * Try to detect a device supported by the legacy int13 BIOS
334 */
335 static int
336 bd_int13probe(struct bdinfo *bd)
337 {
338 int edd;
339 int ret;
340
341 bd->bd_flags &= ~BD_NO_MEDIA;
342
343 edd = bd_check_extensions(bd->bd_unit);
344 if (edd == 0)
345 bd->bd_flags |= BD_MODEINT13;
346 else if (edd < 0x30)
347 bd->bd_flags |= BD_MODEEDD1;
348 else
349 bd->bd_flags |= BD_MODEEDD3;
350
351 /* Default sector size */
352 bd->bd_sectorsize = BIOSDISK_SECSIZE;
353
354 if (bd->bd_unit < 0x80) {
355 /* reset disk */
356 bd_reset_disk(bd->bd_unit);
357
358 /* Get disk type */
359 v86.ctl = V86_FLAGS;
360 v86.addr = 0x13;
361 v86.eax = 0x1500;
362 v86.edx = bd->bd_unit;
363 v86int();
364 if (V86_CY(v86.efl) || (v86.eax & 0x300) == 0)
365 return (0);
366
367 /* Set defaults for 1.44 floppy */
368 bd->bd_cyl = 80;
369 bd->bd_hds = 2;
370 bd->bd_sec = 18;
371 bd->bd_type = 4;
372 bd->bd_sectors = 2880;
373 }
374
375 ret = 1;
376 if (edd != 0)
377 ret = bd_get_diskinfo_ext(bd);
378 if (ret != 0)
379 ret = bd_get_diskinfo_std(bd);
380
381 DEBUG("unit 0x%x geometry %d/%d/%d", bd->bd_unit, bd->bd_cyl,
382 bd->bd_hds, bd->bd_sec);
383
384 return (1);
385 }
386
387 /*
388 * Print information about disks
389 */
390 static int
391 bd_print(int verbose)
392 {
393 static char line[80];
394 struct disk_devdesc dev;
395 int i, ret = 0;
396
397 if (nbdinfo == 0)
398 return (0);
399
400 printf("%s devices:", biosdisk.dv_name);
401 if ((ret = pager_output("\n")) != 0)
402 return (ret);
403
404 for (i = 0; i < nbdinfo; i++) {
405 snprintf(line, sizeof (line),
406 " disk%d: BIOS drive %c (%s%ju X %u):\n", i,
407 (bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit):
408 ('C' + bdinfo[i].bd_unit - 0x80),
409 (bdinfo[i].bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA ?
410 "no media, " : "",
411 (uintmax_t)bdinfo[i].bd_sectors,
412 bdinfo[i].bd_sectorsize);
413 ret = pager_output(line);
414 if (ret != 0)
415 return (ret);
416
417 dev.d_dev = &biosdisk;
418 dev.d_unit = i;
419 dev.d_slice = -1;
420 dev.d_partition = -1;
421 if (disk_open(&dev,
422 bdinfo[i].bd_sectorsize * bdinfo[i].bd_sectors,
423 bdinfo[i].bd_sectorsize) == 0) {
424 sprintf(line, " disk%d", i);
425 ret = disk_print(&dev, line, verbose);
426 disk_close(&dev);
427 if (ret != 0)
428 return (ret);
429 }
430 }
439 * about what the user might want leads to complications.
440 * (eg. given no slice or partition value, with a disk that is
441 * sliced - are they after the first BSD slice, or the DOS
442 * slice before it?)
443 */
444 static int
445 bd_open(struct open_file *f, ...)
446 {
447 struct disk_devdesc *dev;
448 struct disk_devdesc disk;
449 va_list ap;
450 uint64_t size;
451 int rc;
452
453 va_start(ap, f);
454 dev = va_arg(ap, struct disk_devdesc *);
455 va_end(ap);
456
457 if (dev->d_unit < 0 || dev->d_unit >= nbdinfo)
458 return (EIO);
459
460 if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA) {
461 if (!bd_int13probe(&BD(dev)))
462 return (EIO);
463 }
464 BD(dev).bd_open++;
465 if (BD(dev).bd_bcache == NULL)
466 BD(dev).bd_bcache = bcache_allocate();
467
468 /*
469 * Read disk size from partition.
470 * This is needed to work around buggy BIOS systems returning
471 * wrong (truncated) disk media size.
472 * During bd_probe() we tested if the mulitplication of bd_sectors
473 * would overflow so it should be safe to perform here.
474 */
475 disk.d_dev = dev->d_dev;
476 disk.d_type = dev->d_type;
477 disk.d_unit = dev->d_unit;
478 disk.d_opendata = NULL;
479 disk.d_slice = -1;
480 disk.d_partition = -1;
481 disk.d_offset = 0;
482
483 if (disk_open(&disk, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
763 if (V86_CY(v86.efl))
764 return (v86.eax >> 8);
765 return (0);
766 }
767
768 static int
769 bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
770 int dowrite)
771 {
772 u_int result, retry;
773
774 /* Just in case some idiot actually tries to read/write -1 blocks... */
775 if (blks < 0)
776 return (-1);
777
778 /*
779 * Loop retrying the operation a couple of times. The BIOS
780 * may also retry.
781 */
782 for (retry = 0; retry < 3; retry++) {
783 if (BD(dev).bd_flags & BD_MODEEDD)
784 result = bd_edd_io(dev, dblk, blks, dest, dowrite);
785 else
786 result = bd_chs_io(dev, dblk, blks, dest, dowrite);
787
788 if (result == 0) {
789 if (BD(dev).bd_flags & BD_NO_MEDIA)
790 BD(dev).bd_flags &= ~BD_NO_MEDIA;
791 break;
792 }
793
794 bd_reset_disk(BD(dev).bd_unit);
795
796 /*
797 * Error codes:
798 * 20h controller failure
799 * 31h no media in drive (IBM/MS INT 13 extensions)
800 * There is no reason to repeat the IO with errors above.
801 */
802 if (result == 0x20 || result == 0x31 || result == 0x80) {
803 BD(dev).bd_flags |= BD_NO_MEDIA;
804 break;
805 }
806 }
807
808 if (result != 0 && (BD(dev).bd_flags & BD_NO_MEDIA) == 0) {
809 if (dowrite != 0) {
810 printf("%s%d: Write %d sector(s) from %p (0x%x) "
811 "to %lld: 0x%x\n", dev->d_dev->dv_name, dev->d_unit,
812 blks, dest, VTOP(dest), dblk, result);
813 } else {
814 printf("%s%d: Read %d sector(s) from %lld to %p "
815 "(0x%x): 0x%x\n", dev->d_dev->dv_name, dev->d_unit,
816 blks, dblk, dest, VTOP(dest), result);
817 }
818 }
819
820 return (result);
821 }
822
823 /*
824 * Return the BIOS geometry of a given "fixed drive" in a format
825 * suitable for the legacy bootinfo structure. Since the kernel is
826 * expecting raw int 0x13/0x8 values for N_BIOS_GEOM drives, we
827 * prefer to get the information directly, rather than rely on being
828 * able to put it together from information already maintained for
829 * different purposes and for a probably different number of drives.
830 *
831 * For valid drives, the geometry is expected in the format (31..0)
832 * "000000cc cccccccc hhhhhhhh 00ssssss"; and invalid drives are
833 * indicated by returning the geometry of a "1.2M" PC-format floppy
834 * disk. And, incidentally, what is returned is not the geometry as
835 * such but the highest valid cylinder, head, and sector numbers.
836 */
837 u_int32_t
838 bd_getbigeom(int bunit)
839 {
840
|