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/param.h>
18
19#include <btxv86.h>
20
21#include "stand.h"
22#include "rbx.h"
23#include "drv.h"
24#include "edd.h"
25
26static struct edd_params params;
27
28uint64_t
29drvsize(struct dsk *dskp)
30{
31
32	params.len = sizeof(struct edd_params);
33	v86.ctl = V86_FLAGS;
34	v86.addr = 0x13;
35	v86.eax = 0x4800;
36	v86.edx = dskp->drive;
37	v86.ds = VTOPSEG(&params);
38	v86.esi = VTOPOFF(&params);
39	v86int();
40	if (V86_CY(v86.efl)) {
41		printf("error %u\n", v86.eax >> 8 & 0xff);
42		return (0);
43	}
44	return (params.sectors);
45}
46
47static struct edd_packet packet;
48
49int
50drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
51{
52	static unsigned c = 0x2d5c7c2f;
53
54	if (!OPT_CHECK(RBX_QUIET))
55		printf("%c\b", c = c << 8 | c >> 24);
56	packet.len = sizeof(struct edd_packet);
57	packet.count = nblk;
58	packet.off = VTOPOFF(buf);
59	packet.seg = VTOPSEG(buf);
60	packet.lba = lba;
61	v86.ctl = V86_FLAGS;
62	v86.addr = 0x13;
63	v86.eax = 0x4200;
64	v86.edx = dskp->drive;
65	v86.ds = VTOPSEG(&packet);
66	v86.esi = VTOPOFF(&packet);
67	v86int();
68	if (V86_CY(v86.efl)) {
69		printf("%s: error %u lba %llu\n",
70		    BOOTPROG, v86.eax >> 8 & 0xff, lba);
71		return (-1);
72	}
73	return (0);
74}
75
76#if defined(GPT) || defined(ZFS)
77int
78drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
79{
80
81	packet.len = sizeof(struct edd_packet);
82	packet.count = nblk;
83	packet.off = VTOPOFF(buf);
84	packet.seg = VTOPSEG(buf);
85	packet.lba = lba;
86	v86.ctl = V86_FLAGS;
87	v86.addr = 0x13;
88	v86.eax = 0x4300;
89	v86.edx = dskp->drive;
90	v86.ds = VTOPSEG(&packet);
91	v86.esi = VTOPOFF(&packet);
92	v86int();
93	if (V86_CY(v86.efl)) {
94		printf("error %u lba %llu\n", v86.eax >> 8 & 0xff, lba);
95		return (-1);
96	}
97	return (0);
98}
99#endif	/* GPT || ZFS */
100