xref: /freebsd/stand/i386/common/drv.c (revision 7c43148a974877188a930e4078a164f83da8e652)
1ca987d46SWarner Losh /*-
2ca987d46SWarner Losh  * Copyright (c) 1998 Robert Nordier
3ca987d46SWarner Losh  * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
4ca987d46SWarner Losh  * All rights reserved.
5ca987d46SWarner Losh  *
6ca987d46SWarner Losh  * Redistribution and use in source and binary forms are freely
7ca987d46SWarner Losh  * permitted provided that the above copyright notice and this
8ca987d46SWarner Losh  * paragraph and the following disclaimer are duplicated in all
9ca987d46SWarner Losh  * such forms.
10ca987d46SWarner Losh  *
11ca987d46SWarner Losh  * This software is provided "AS IS" and without any express or
12ca987d46SWarner Losh  * implied warranties, including, without limitation, the implied
13ca987d46SWarner Losh  * warranties of merchantability and fitness for a particular
14ca987d46SWarner Losh  * purpose.
15ca987d46SWarner Losh  */
16ca987d46SWarner Losh 
17ca987d46SWarner Losh #include <sys/param.h>
18ca987d46SWarner Losh 
19ca987d46SWarner Losh #include <btxv86.h>
20ca987d46SWarner Losh 
21*65628439SWarner Losh #include "stand.h"
22ca987d46SWarner Losh #include "rbx.h"
23ca987d46SWarner Losh #include "drv.h"
24ca987d46SWarner Losh #include "edd.h"
25ca987d46SWarner Losh 
26ca987d46SWarner Losh static struct edd_params params;
27ca987d46SWarner Losh 
28ca987d46SWarner Losh uint64_t
drvsize(struct dsk * dskp)29ca987d46SWarner Losh drvsize(struct dsk *dskp)
30ca987d46SWarner Losh {
31ca987d46SWarner Losh 
32ca987d46SWarner Losh 	params.len = sizeof(struct edd_params);
33ca987d46SWarner Losh 	v86.ctl = V86_FLAGS;
34ca987d46SWarner Losh 	v86.addr = 0x13;
35ca987d46SWarner Losh 	v86.eax = 0x4800;
36ca987d46SWarner Losh 	v86.edx = dskp->drive;
37ca987d46SWarner Losh 	v86.ds = VTOPSEG(&params);
38ca987d46SWarner Losh 	v86.esi = VTOPOFF(&params);
39ca987d46SWarner Losh 	v86int();
40ca987d46SWarner Losh 	if (V86_CY(v86.efl)) {
41ca987d46SWarner Losh 		printf("error %u\n", v86.eax >> 8 & 0xff);
42ca987d46SWarner Losh 		return (0);
43ca987d46SWarner Losh 	}
44ca987d46SWarner Losh 	return (params.sectors);
45ca987d46SWarner Losh }
46ca987d46SWarner Losh 
47ca987d46SWarner Losh static struct edd_packet packet;
48ca987d46SWarner Losh 
49ca987d46SWarner Losh int
drvread(struct dsk * dskp,void * buf,daddr_t lba,unsigned nblk)50ca987d46SWarner Losh drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
51ca987d46SWarner Losh {
52ca987d46SWarner Losh 	static unsigned c = 0x2d5c7c2f;
53ca987d46SWarner Losh 
54ca987d46SWarner Losh 	if (!OPT_CHECK(RBX_QUIET))
55ca987d46SWarner Losh 		printf("%c\b", c = c << 8 | c >> 24);
56ca987d46SWarner Losh 	packet.len = sizeof(struct edd_packet);
57ca987d46SWarner Losh 	packet.count = nblk;
58ca987d46SWarner Losh 	packet.off = VTOPOFF(buf);
59ca987d46SWarner Losh 	packet.seg = VTOPSEG(buf);
60ca987d46SWarner Losh 	packet.lba = lba;
61ca987d46SWarner Losh 	v86.ctl = V86_FLAGS;
62ca987d46SWarner Losh 	v86.addr = 0x13;
63ca987d46SWarner Losh 	v86.eax = 0x4200;
64ca987d46SWarner Losh 	v86.edx = dskp->drive;
65ca987d46SWarner Losh 	v86.ds = VTOPSEG(&packet);
66ca987d46SWarner Losh 	v86.esi = VTOPOFF(&packet);
67ca987d46SWarner Losh 	v86int();
68ca987d46SWarner Losh 	if (V86_CY(v86.efl)) {
69*65628439SWarner Losh 		printf("%s: error %u lba %llu\n",
70ca987d46SWarner Losh 		    BOOTPROG, v86.eax >> 8 & 0xff, lba);
71ca987d46SWarner Losh 		return (-1);
72ca987d46SWarner Losh 	}
73ca987d46SWarner Losh 	return (0);
74ca987d46SWarner Losh }
75ca987d46SWarner Losh 
76ca987d46SWarner Losh #if defined(GPT) || defined(ZFS)
77ca987d46SWarner Losh int
drvwrite(struct dsk * dskp,void * buf,daddr_t lba,unsigned nblk)78ca987d46SWarner Losh drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
79ca987d46SWarner Losh {
80ca987d46SWarner Losh 
81ca987d46SWarner Losh 	packet.len = sizeof(struct edd_packet);
82ca987d46SWarner Losh 	packet.count = nblk;
83ca987d46SWarner Losh 	packet.off = VTOPOFF(buf);
84ca987d46SWarner Losh 	packet.seg = VTOPSEG(buf);
85ca987d46SWarner Losh 	packet.lba = lba;
86ca987d46SWarner Losh 	v86.ctl = V86_FLAGS;
87ca987d46SWarner Losh 	v86.addr = 0x13;
88ca987d46SWarner Losh 	v86.eax = 0x4300;
89ca987d46SWarner Losh 	v86.edx = dskp->drive;
90ca987d46SWarner Losh 	v86.ds = VTOPSEG(&packet);
91ca987d46SWarner Losh 	v86.esi = VTOPOFF(&packet);
92ca987d46SWarner Losh 	v86int();
93ca987d46SWarner Losh 	if (V86_CY(v86.efl)) {
94*65628439SWarner Losh 		printf("error %u lba %llu\n", v86.eax >> 8 & 0xff, lba);
95ca987d46SWarner Losh 		return (-1);
96ca987d46SWarner Losh 	}
97ca987d46SWarner Losh 	return (0);
98ca987d46SWarner Losh }
99ca987d46SWarner Losh #endif	/* GPT || ZFS */
100