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