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