root / tests / fdc-test.c @ e4b42e6e
History | View | Annotate | Download (12.6 kB)
1 | 93e9eb68 | Kevin Wolf | /*
|
---|---|---|---|
2 | 93e9eb68 | Kevin Wolf | * Floppy test cases.
|
3 | 93e9eb68 | Kevin Wolf | *
|
4 | 93e9eb68 | Kevin Wolf | * Copyright (c) 2012 Kevin Wolf <kwolf@redhat.com>
|
5 | 93e9eb68 | Kevin Wolf | *
|
6 | 93e9eb68 | Kevin Wolf | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 93e9eb68 | Kevin Wolf | * of this software and associated documentation files (the "Software"), to deal
|
8 | 93e9eb68 | Kevin Wolf | * in the Software without restriction, including without limitation the rights
|
9 | 93e9eb68 | Kevin Wolf | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 93e9eb68 | Kevin Wolf | * copies of the Software, and to permit persons to whom the Software is
|
11 | 93e9eb68 | Kevin Wolf | * furnished to do so, subject to the following conditions:
|
12 | 93e9eb68 | Kevin Wolf | *
|
13 | 93e9eb68 | Kevin Wolf | * The above copyright notice and this permission notice shall be included in
|
14 | 93e9eb68 | Kevin Wolf | * all copies or substantial portions of the Software.
|
15 | 93e9eb68 | Kevin Wolf | *
|
16 | 93e9eb68 | Kevin Wolf | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 93e9eb68 | Kevin Wolf | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 93e9eb68 | Kevin Wolf | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 93e9eb68 | Kevin Wolf | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 93e9eb68 | Kevin Wolf | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 93e9eb68 | Kevin Wolf | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 93e9eb68 | Kevin Wolf | * THE SOFTWARE.
|
23 | 93e9eb68 | Kevin Wolf | */
|
24 | 93e9eb68 | Kevin Wolf | |
25 | 93e9eb68 | Kevin Wolf | #include <stdint.h> |
26 | 93e9eb68 | Kevin Wolf | #include <string.h> |
27 | 93e9eb68 | Kevin Wolf | #include <stdio.h> |
28 | 93e9eb68 | Kevin Wolf | |
29 | 93e9eb68 | Kevin Wolf | #include <glib.h> |
30 | 93e9eb68 | Kevin Wolf | |
31 | 93e9eb68 | Kevin Wolf | #include "libqtest.h" |
32 | 93e9eb68 | Kevin Wolf | #include "qemu-common.h" |
33 | 93e9eb68 | Kevin Wolf | |
34 | 93e9eb68 | Kevin Wolf | #define TEST_IMAGE_SIZE 1440 * 1024 |
35 | 93e9eb68 | Kevin Wolf | |
36 | 93e9eb68 | Kevin Wolf | #define FLOPPY_BASE 0x3f0 |
37 | 93e9eb68 | Kevin Wolf | #define FLOPPY_IRQ 6 |
38 | 93e9eb68 | Kevin Wolf | |
39 | 93e9eb68 | Kevin Wolf | enum {
|
40 | 93e9eb68 | Kevin Wolf | reg_sra = 0x0,
|
41 | 93e9eb68 | Kevin Wolf | reg_srb = 0x1,
|
42 | 93e9eb68 | Kevin Wolf | reg_dor = 0x2,
|
43 | 93e9eb68 | Kevin Wolf | reg_msr = 0x4,
|
44 | 93e9eb68 | Kevin Wolf | reg_dsr = 0x4,
|
45 | 93e9eb68 | Kevin Wolf | reg_fifo = 0x5,
|
46 | 93e9eb68 | Kevin Wolf | reg_dir = 0x7,
|
47 | 93e9eb68 | Kevin Wolf | }; |
48 | 93e9eb68 | Kevin Wolf | |
49 | 93e9eb68 | Kevin Wolf | enum {
|
50 | 98272dbb | Pavel Hrdina | CMD_SENSE_INT = 0x08,
|
51 | 67f194bd | Kevin Wolf | CMD_READ_ID = 0x0a,
|
52 | 98272dbb | Pavel Hrdina | CMD_SEEK = 0x0f,
|
53 | 6f442fe8 | Hervé Poussineau | CMD_VERIFY = 0x16,
|
54 | 98272dbb | Pavel Hrdina | CMD_READ = 0xe6,
|
55 | 98272dbb | Pavel Hrdina | CMD_RELATIVE_SEEK_OUT = 0x8f,
|
56 | 98272dbb | Pavel Hrdina | CMD_RELATIVE_SEEK_IN = 0xcf,
|
57 | 93e9eb68 | Kevin Wolf | }; |
58 | 93e9eb68 | Kevin Wolf | |
59 | 93e9eb68 | Kevin Wolf | enum {
|
60 | 5f8ae8e2 | Hervé Poussineau | BUSY = 0x10,
|
61 | 5f8ae8e2 | Hervé Poussineau | NONDMA = 0x20,
|
62 | 93e9eb68 | Kevin Wolf | RQM = 0x80,
|
63 | 93e9eb68 | Kevin Wolf | DIO = 0x40,
|
64 | 93e9eb68 | Kevin Wolf | |
65 | 93e9eb68 | Kevin Wolf | DSKCHG = 0x80,
|
66 | 93e9eb68 | Kevin Wolf | }; |
67 | 93e9eb68 | Kevin Wolf | |
68 | 93e9eb68 | Kevin Wolf | char test_image[] = "/tmp/qtest.XXXXXX"; |
69 | 93e9eb68 | Kevin Wolf | |
70 | 93e9eb68 | Kevin Wolf | #define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, (mask))
|
71 | 93e9eb68 | Kevin Wolf | #define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0) |
72 | 93e9eb68 | Kevin Wolf | |
73 | 7cd33161 | Pavel Hrdina | static uint8_t base = 0x70; |
74 | 7cd33161 | Pavel Hrdina | |
75 | 7cd33161 | Pavel Hrdina | enum {
|
76 | 7cd33161 | Pavel Hrdina | CMOS_FLOPPY = 0x10,
|
77 | 7cd33161 | Pavel Hrdina | }; |
78 | 7cd33161 | Pavel Hrdina | |
79 | 93e9eb68 | Kevin Wolf | static void floppy_send(uint8_t byte) |
80 | 93e9eb68 | Kevin Wolf | { |
81 | 93e9eb68 | Kevin Wolf | uint8_t msr; |
82 | 93e9eb68 | Kevin Wolf | |
83 | 93e9eb68 | Kevin Wolf | msr = inb(FLOPPY_BASE + reg_msr); |
84 | 93e9eb68 | Kevin Wolf | assert_bit_set(msr, RQM); |
85 | 93e9eb68 | Kevin Wolf | assert_bit_clear(msr, DIO); |
86 | 93e9eb68 | Kevin Wolf | |
87 | 93e9eb68 | Kevin Wolf | outb(FLOPPY_BASE + reg_fifo, byte); |
88 | 93e9eb68 | Kevin Wolf | } |
89 | 93e9eb68 | Kevin Wolf | |
90 | 93e9eb68 | Kevin Wolf | static uint8_t floppy_recv(void) |
91 | 93e9eb68 | Kevin Wolf | { |
92 | 93e9eb68 | Kevin Wolf | uint8_t msr; |
93 | 93e9eb68 | Kevin Wolf | |
94 | 93e9eb68 | Kevin Wolf | msr = inb(FLOPPY_BASE + reg_msr); |
95 | 93e9eb68 | Kevin Wolf | assert_bit_set(msr, RQM | DIO); |
96 | 93e9eb68 | Kevin Wolf | |
97 | 93e9eb68 | Kevin Wolf | return inb(FLOPPY_BASE + reg_fifo);
|
98 | 93e9eb68 | Kevin Wolf | } |
99 | 93e9eb68 | Kevin Wolf | |
100 | c3cdc1b0 | Kevin Wolf | /* pcn: Present Cylinder Number */
|
101 | c3cdc1b0 | Kevin Wolf | static void ack_irq(uint8_t *pcn) |
102 | 93e9eb68 | Kevin Wolf | { |
103 | 98272dbb | Pavel Hrdina | uint8_t ret; |
104 | 98272dbb | Pavel Hrdina | |
105 | 93e9eb68 | Kevin Wolf | g_assert(get_irq(FLOPPY_IRQ)); |
106 | 93e9eb68 | Kevin Wolf | floppy_send(CMD_SENSE_INT); |
107 | 93e9eb68 | Kevin Wolf | floppy_recv(); |
108 | c3cdc1b0 | Kevin Wolf | |
109 | 98272dbb | Pavel Hrdina | ret = floppy_recv(); |
110 | c3cdc1b0 | Kevin Wolf | if (pcn != NULL) { |
111 | c3cdc1b0 | Kevin Wolf | *pcn = ret; |
112 | c3cdc1b0 | Kevin Wolf | } |
113 | 98272dbb | Pavel Hrdina | |
114 | c3cdc1b0 | Kevin Wolf | g_assert(!get_irq(FLOPPY_IRQ)); |
115 | 93e9eb68 | Kevin Wolf | } |
116 | 93e9eb68 | Kevin Wolf | |
117 | 6f442fe8 | Hervé Poussineau | static uint8_t send_read_command(uint8_t cmd)
|
118 | 8b9ef60d | Pavel Hrdina | { |
119 | 8b9ef60d | Pavel Hrdina | uint8_t drive = 0;
|
120 | 8b9ef60d | Pavel Hrdina | uint8_t head = 0;
|
121 | 8b9ef60d | Pavel Hrdina | uint8_t cyl = 0;
|
122 | 8b9ef60d | Pavel Hrdina | uint8_t sect_addr = 1;
|
123 | 8b9ef60d | Pavel Hrdina | uint8_t sect_size = 2;
|
124 | 8b9ef60d | Pavel Hrdina | uint8_t eot = 1;
|
125 | 8b9ef60d | Pavel Hrdina | uint8_t gap = 0x1b;
|
126 | 8b9ef60d | Pavel Hrdina | uint8_t gpl = 0xff;
|
127 | 8b9ef60d | Pavel Hrdina | |
128 | 8b9ef60d | Pavel Hrdina | uint8_t msr = 0;
|
129 | 8b9ef60d | Pavel Hrdina | uint8_t st0; |
130 | 8b9ef60d | Pavel Hrdina | |
131 | 8b9ef60d | Pavel Hrdina | uint8_t ret = 0;
|
132 | 8b9ef60d | Pavel Hrdina | |
133 | 6f442fe8 | Hervé Poussineau | floppy_send(cmd); |
134 | 8b9ef60d | Pavel Hrdina | floppy_send(head << 2 | drive);
|
135 | 8b9ef60d | Pavel Hrdina | g_assert(!get_irq(FLOPPY_IRQ)); |
136 | 8b9ef60d | Pavel Hrdina | floppy_send(cyl); |
137 | 8b9ef60d | Pavel Hrdina | floppy_send(head); |
138 | 8b9ef60d | Pavel Hrdina | floppy_send(sect_addr); |
139 | 8b9ef60d | Pavel Hrdina | floppy_send(sect_size); |
140 | 8b9ef60d | Pavel Hrdina | floppy_send(eot); |
141 | 8b9ef60d | Pavel Hrdina | floppy_send(gap); |
142 | 8b9ef60d | Pavel Hrdina | floppy_send(gpl); |
143 | 8b9ef60d | Pavel Hrdina | |
144 | 8b9ef60d | Pavel Hrdina | uint8_t i = 0;
|
145 | 8b9ef60d | Pavel Hrdina | uint8_t n = 2;
|
146 | 8b9ef60d | Pavel Hrdina | for (; i < n; i++) {
|
147 | 8b9ef60d | Pavel Hrdina | msr = inb(FLOPPY_BASE + reg_msr); |
148 | 8b9ef60d | Pavel Hrdina | if (msr == 0xd0) { |
149 | 8b9ef60d | Pavel Hrdina | break;
|
150 | 8b9ef60d | Pavel Hrdina | } |
151 | 8b9ef60d | Pavel Hrdina | sleep(1);
|
152 | 8b9ef60d | Pavel Hrdina | } |
153 | 8b9ef60d | Pavel Hrdina | |
154 | 8b9ef60d | Pavel Hrdina | if (i >= n) {
|
155 | 8b9ef60d | Pavel Hrdina | return 1; |
156 | 8b9ef60d | Pavel Hrdina | } |
157 | 8b9ef60d | Pavel Hrdina | |
158 | 8b9ef60d | Pavel Hrdina | st0 = floppy_recv(); |
159 | 075f5532 | Hervé Poussineau | if (st0 != 0x40) { |
160 | 8b9ef60d | Pavel Hrdina | ret = 1;
|
161 | 8b9ef60d | Pavel Hrdina | } |
162 | 8b9ef60d | Pavel Hrdina | |
163 | 8b9ef60d | Pavel Hrdina | floppy_recv(); |
164 | 8b9ef60d | Pavel Hrdina | floppy_recv(); |
165 | 8b9ef60d | Pavel Hrdina | floppy_recv(); |
166 | 8b9ef60d | Pavel Hrdina | floppy_recv(); |
167 | 8b9ef60d | Pavel Hrdina | floppy_recv(); |
168 | 8b9ef60d | Pavel Hrdina | floppy_recv(); |
169 | 8b9ef60d | Pavel Hrdina | |
170 | 8b9ef60d | Pavel Hrdina | return ret;
|
171 | 8b9ef60d | Pavel Hrdina | } |
172 | 8b9ef60d | Pavel Hrdina | |
173 | 5f8ae8e2 | Hervé Poussineau | static uint8_t send_read_no_dma_command(int nb_sect, uint8_t expected_st0) |
174 | 5f8ae8e2 | Hervé Poussineau | { |
175 | 5f8ae8e2 | Hervé Poussineau | uint8_t drive = 0;
|
176 | 5f8ae8e2 | Hervé Poussineau | uint8_t head = 0;
|
177 | 5f8ae8e2 | Hervé Poussineau | uint8_t cyl = 0;
|
178 | 5f8ae8e2 | Hervé Poussineau | uint8_t sect_addr = 1;
|
179 | 5f8ae8e2 | Hervé Poussineau | uint8_t sect_size = 2;
|
180 | 5f8ae8e2 | Hervé Poussineau | uint8_t eot = nb_sect; |
181 | 5f8ae8e2 | Hervé Poussineau | uint8_t gap = 0x1b;
|
182 | 5f8ae8e2 | Hervé Poussineau | uint8_t gpl = 0xff;
|
183 | 5f8ae8e2 | Hervé Poussineau | |
184 | 5f8ae8e2 | Hervé Poussineau | uint8_t msr = 0;
|
185 | 5f8ae8e2 | Hervé Poussineau | uint8_t st0; |
186 | 5f8ae8e2 | Hervé Poussineau | |
187 | 5f8ae8e2 | Hervé Poussineau | uint8_t ret = 0;
|
188 | 5f8ae8e2 | Hervé Poussineau | |
189 | 5f8ae8e2 | Hervé Poussineau | floppy_send(CMD_READ); |
190 | 5f8ae8e2 | Hervé Poussineau | floppy_send(head << 2 | drive);
|
191 | 5f8ae8e2 | Hervé Poussineau | g_assert(!get_irq(FLOPPY_IRQ)); |
192 | 5f8ae8e2 | Hervé Poussineau | floppy_send(cyl); |
193 | 5f8ae8e2 | Hervé Poussineau | floppy_send(head); |
194 | 5f8ae8e2 | Hervé Poussineau | floppy_send(sect_addr); |
195 | 5f8ae8e2 | Hervé Poussineau | floppy_send(sect_size); |
196 | 5f8ae8e2 | Hervé Poussineau | floppy_send(eot); |
197 | 5f8ae8e2 | Hervé Poussineau | floppy_send(gap); |
198 | 5f8ae8e2 | Hervé Poussineau | floppy_send(gpl); |
199 | 5f8ae8e2 | Hervé Poussineau | |
200 | 5f8ae8e2 | Hervé Poussineau | uint16_t i = 0;
|
201 | 5f8ae8e2 | Hervé Poussineau | uint8_t n = 2;
|
202 | 5f8ae8e2 | Hervé Poussineau | for (; i < n; i++) {
|
203 | 5f8ae8e2 | Hervé Poussineau | msr = inb(FLOPPY_BASE + reg_msr); |
204 | 5f8ae8e2 | Hervé Poussineau | if (msr == (BUSY | NONDMA | DIO | RQM)) {
|
205 | 5f8ae8e2 | Hervé Poussineau | break;
|
206 | 5f8ae8e2 | Hervé Poussineau | } |
207 | 5f8ae8e2 | Hervé Poussineau | sleep(1);
|
208 | 5f8ae8e2 | Hervé Poussineau | } |
209 | 5f8ae8e2 | Hervé Poussineau | |
210 | 5f8ae8e2 | Hervé Poussineau | if (i >= n) {
|
211 | 5f8ae8e2 | Hervé Poussineau | return 1; |
212 | 5f8ae8e2 | Hervé Poussineau | } |
213 | 5f8ae8e2 | Hervé Poussineau | |
214 | 5f8ae8e2 | Hervé Poussineau | /* Non-DMA mode */
|
215 | 5f8ae8e2 | Hervé Poussineau | for (i = 0; i < 512 * 2 * nb_sect; i++) { |
216 | 5f8ae8e2 | Hervé Poussineau | msr = inb(FLOPPY_BASE + reg_msr); |
217 | 5f8ae8e2 | Hervé Poussineau | assert_bit_set(msr, BUSY | RQM | DIO); |
218 | 5f8ae8e2 | Hervé Poussineau | inb(FLOPPY_BASE + reg_fifo); |
219 | 5f8ae8e2 | Hervé Poussineau | } |
220 | 5f8ae8e2 | Hervé Poussineau | |
221 | 5f8ae8e2 | Hervé Poussineau | st0 = floppy_recv(); |
222 | 5f8ae8e2 | Hervé Poussineau | if (st0 != expected_st0) {
|
223 | 5f8ae8e2 | Hervé Poussineau | ret = 1;
|
224 | 5f8ae8e2 | Hervé Poussineau | } |
225 | 5f8ae8e2 | Hervé Poussineau | |
226 | 5f8ae8e2 | Hervé Poussineau | floppy_recv(); |
227 | 5f8ae8e2 | Hervé Poussineau | floppy_recv(); |
228 | 5f8ae8e2 | Hervé Poussineau | floppy_recv(); |
229 | 5f8ae8e2 | Hervé Poussineau | floppy_recv(); |
230 | 5f8ae8e2 | Hervé Poussineau | floppy_recv(); |
231 | 5f8ae8e2 | Hervé Poussineau | floppy_recv(); |
232 | 5f8ae8e2 | Hervé Poussineau | |
233 | 5f8ae8e2 | Hervé Poussineau | return ret;
|
234 | 5f8ae8e2 | Hervé Poussineau | } |
235 | 5f8ae8e2 | Hervé Poussineau | |
236 | c3cdc1b0 | Kevin Wolf | static void send_seek(int cyl) |
237 | 93e9eb68 | Kevin Wolf | { |
238 | 93e9eb68 | Kevin Wolf | int drive = 0; |
239 | 93e9eb68 | Kevin Wolf | int head = 0; |
240 | 93e9eb68 | Kevin Wolf | |
241 | 93e9eb68 | Kevin Wolf | floppy_send(CMD_SEEK); |
242 | 93e9eb68 | Kevin Wolf | floppy_send(head << 2 | drive);
|
243 | 93e9eb68 | Kevin Wolf | g_assert(!get_irq(FLOPPY_IRQ)); |
244 | 93e9eb68 | Kevin Wolf | floppy_send(cyl); |
245 | c3cdc1b0 | Kevin Wolf | ack_irq(NULL);
|
246 | 93e9eb68 | Kevin Wolf | } |
247 | 93e9eb68 | Kevin Wolf | |
248 | 7cd33161 | Pavel Hrdina | static uint8_t cmos_read(uint8_t reg)
|
249 | 93e9eb68 | Kevin Wolf | { |
250 | 7cd33161 | Pavel Hrdina | outb(base + 0, reg);
|
251 | 7cd33161 | Pavel Hrdina | return inb(base + 1); |
252 | 7cd33161 | Pavel Hrdina | } |
253 | 93e9eb68 | Kevin Wolf | |
254 | 7cd33161 | Pavel Hrdina | static void test_cmos(void) |
255 | 7cd33161 | Pavel Hrdina | { |
256 | 7cd33161 | Pavel Hrdina | uint8_t cmos; |
257 | 93e9eb68 | Kevin Wolf | |
258 | 7cd33161 | Pavel Hrdina | cmos = cmos_read(CMOS_FLOPPY); |
259 | 7cd33161 | Pavel Hrdina | g_assert(cmos == 0x40);
|
260 | 7cd33161 | Pavel Hrdina | } |
261 | 93e9eb68 | Kevin Wolf | |
262 | 7cd33161 | Pavel Hrdina | static void test_no_media_on_start(void) |
263 | 7cd33161 | Pavel Hrdina | { |
264 | 7cd33161 | Pavel Hrdina | uint8_t dir; |
265 | 7cd33161 | Pavel Hrdina | |
266 | 7cd33161 | Pavel Hrdina | /* Media changed bit must be set all time after start if there is
|
267 | 7cd33161 | Pavel Hrdina | * no media in drive. */
|
268 | 93e9eb68 | Kevin Wolf | dir = inb(FLOPPY_BASE + reg_dir); |
269 | 93e9eb68 | Kevin Wolf | assert_bit_set(dir, DSKCHG); |
270 | 93e9eb68 | Kevin Wolf | dir = inb(FLOPPY_BASE + reg_dir); |
271 | 93e9eb68 | Kevin Wolf | assert_bit_set(dir, DSKCHG); |
272 | c3cdc1b0 | Kevin Wolf | send_seek(1);
|
273 | 93e9eb68 | Kevin Wolf | dir = inb(FLOPPY_BASE + reg_dir); |
274 | 93e9eb68 | Kevin Wolf | assert_bit_set(dir, DSKCHG); |
275 | 93e9eb68 | Kevin Wolf | dir = inb(FLOPPY_BASE + reg_dir); |
276 | 93e9eb68 | Kevin Wolf | assert_bit_set(dir, DSKCHG); |
277 | 7cd33161 | Pavel Hrdina | } |
278 | 7cd33161 | Pavel Hrdina | |
279 | 8b9ef60d | Pavel Hrdina | static void test_read_without_media(void) |
280 | 8b9ef60d | Pavel Hrdina | { |
281 | 8b9ef60d | Pavel Hrdina | uint8_t ret; |
282 | 8b9ef60d | Pavel Hrdina | |
283 | 6f442fe8 | Hervé Poussineau | ret = send_read_command(CMD_READ); |
284 | 8b9ef60d | Pavel Hrdina | g_assert(ret == 0);
|
285 | 8b9ef60d | Pavel Hrdina | } |
286 | 8b9ef60d | Pavel Hrdina | |
287 | 1f507913 | Hervé Poussineau | static void test_media_insert(void) |
288 | 7cd33161 | Pavel Hrdina | { |
289 | 7cd33161 | Pavel Hrdina | uint8_t dir; |
290 | 93e9eb68 | Kevin Wolf | |
291 | 7cd33161 | Pavel Hrdina | /* Insert media in drive. DSKCHK should not be reset until a step pulse
|
292 | 93e9eb68 | Kevin Wolf | * is sent. */
|
293 | 93e9eb68 | Kevin Wolf | qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', "
|
294 | 93e9eb68 | Kevin Wolf | "'target': '%s' }}", test_image);
|
295 | 93e9eb68 | Kevin Wolf | qmp(""); /* ignore event (FIXME open -> open transition?!) */ |
296 | 93e9eb68 | Kevin Wolf | qmp(""); /* ignore event */ |
297 | 93e9eb68 | Kevin Wolf | |
298 | 93e9eb68 | Kevin Wolf | dir = inb(FLOPPY_BASE + reg_dir); |
299 | 93e9eb68 | Kevin Wolf | assert_bit_set(dir, DSKCHG); |
300 | 93e9eb68 | Kevin Wolf | dir = inb(FLOPPY_BASE + reg_dir); |
301 | 93e9eb68 | Kevin Wolf | assert_bit_set(dir, DSKCHG); |
302 | 93e9eb68 | Kevin Wolf | |
303 | c3cdc1b0 | Kevin Wolf | send_seek(0);
|
304 | 59240c34 | Pavel Hrdina | dir = inb(FLOPPY_BASE + reg_dir); |
305 | 59240c34 | Pavel Hrdina | assert_bit_set(dir, DSKCHG); |
306 | 59240c34 | Pavel Hrdina | dir = inb(FLOPPY_BASE + reg_dir); |
307 | 59240c34 | Pavel Hrdina | assert_bit_set(dir, DSKCHG); |
308 | 59240c34 | Pavel Hrdina | |
309 | 59240c34 | Pavel Hrdina | /* Step to next track should clear DSKCHG bit. */
|
310 | c3cdc1b0 | Kevin Wolf | send_seek(1);
|
311 | 93e9eb68 | Kevin Wolf | dir = inb(FLOPPY_BASE + reg_dir); |
312 | 93e9eb68 | Kevin Wolf | assert_bit_clear(dir, DSKCHG); |
313 | 93e9eb68 | Kevin Wolf | dir = inb(FLOPPY_BASE + reg_dir); |
314 | 93e9eb68 | Kevin Wolf | assert_bit_clear(dir, DSKCHG); |
315 | 1f507913 | Hervé Poussineau | } |
316 | 1f507913 | Hervé Poussineau | |
317 | 1f507913 | Hervé Poussineau | static void test_media_change(void) |
318 | 1f507913 | Hervé Poussineau | { |
319 | 1f507913 | Hervé Poussineau | uint8_t dir; |
320 | 1f507913 | Hervé Poussineau | |
321 | 1f507913 | Hervé Poussineau | test_media_insert(); |
322 | 7cd33161 | Pavel Hrdina | |
323 | 7cd33161 | Pavel Hrdina | /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
|
324 | 7cd33161 | Pavel Hrdina | * reset the bit. */
|
325 | 7cd33161 | Pavel Hrdina | qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}");
|
326 | 7cd33161 | Pavel Hrdina | qmp(""); /* ignore event */ |
327 | 7cd33161 | Pavel Hrdina | |
328 | 7cd33161 | Pavel Hrdina | dir = inb(FLOPPY_BASE + reg_dir); |
329 | 7cd33161 | Pavel Hrdina | assert_bit_set(dir, DSKCHG); |
330 | 7cd33161 | Pavel Hrdina | dir = inb(FLOPPY_BASE + reg_dir); |
331 | 7cd33161 | Pavel Hrdina | assert_bit_set(dir, DSKCHG); |
332 | 7cd33161 | Pavel Hrdina | |
333 | c3cdc1b0 | Kevin Wolf | send_seek(0);
|
334 | 59240c34 | Pavel Hrdina | dir = inb(FLOPPY_BASE + reg_dir); |
335 | 59240c34 | Pavel Hrdina | assert_bit_set(dir, DSKCHG); |
336 | 59240c34 | Pavel Hrdina | dir = inb(FLOPPY_BASE + reg_dir); |
337 | 59240c34 | Pavel Hrdina | assert_bit_set(dir, DSKCHG); |
338 | 59240c34 | Pavel Hrdina | |
339 | c3cdc1b0 | Kevin Wolf | send_seek(1);
|
340 | 7cd33161 | Pavel Hrdina | dir = inb(FLOPPY_BASE + reg_dir); |
341 | 7cd33161 | Pavel Hrdina | assert_bit_set(dir, DSKCHG); |
342 | 7cd33161 | Pavel Hrdina | dir = inb(FLOPPY_BASE + reg_dir); |
343 | 7cd33161 | Pavel Hrdina | assert_bit_set(dir, DSKCHG); |
344 | 93e9eb68 | Kevin Wolf | } |
345 | 93e9eb68 | Kevin Wolf | |
346 | b3ce604e | Pavel Hrdina | static void test_sense_interrupt(void) |
347 | b3ce604e | Pavel Hrdina | { |
348 | b3ce604e | Pavel Hrdina | int drive = 0; |
349 | b3ce604e | Pavel Hrdina | int head = 0; |
350 | b3ce604e | Pavel Hrdina | int cyl = 0; |
351 | b3ce604e | Pavel Hrdina | int ret = 0; |
352 | b3ce604e | Pavel Hrdina | |
353 | b3ce604e | Pavel Hrdina | floppy_send(CMD_SENSE_INT); |
354 | b3ce604e | Pavel Hrdina | ret = floppy_recv(); |
355 | b3ce604e | Pavel Hrdina | g_assert(ret == 0x80);
|
356 | b3ce604e | Pavel Hrdina | |
357 | b3ce604e | Pavel Hrdina | floppy_send(CMD_SEEK); |
358 | b3ce604e | Pavel Hrdina | floppy_send(head << 2 | drive);
|
359 | b3ce604e | Pavel Hrdina | g_assert(!get_irq(FLOPPY_IRQ)); |
360 | b3ce604e | Pavel Hrdina | floppy_send(cyl); |
361 | b3ce604e | Pavel Hrdina | |
362 | b3ce604e | Pavel Hrdina | floppy_send(CMD_SENSE_INT); |
363 | b3ce604e | Pavel Hrdina | ret = floppy_recv(); |
364 | b3ce604e | Pavel Hrdina | g_assert(ret == 0x20);
|
365 | b3ce604e | Pavel Hrdina | floppy_recv(); |
366 | b3ce604e | Pavel Hrdina | } |
367 | b3ce604e | Pavel Hrdina | |
368 | 98272dbb | Pavel Hrdina | static void test_relative_seek(void) |
369 | 98272dbb | Pavel Hrdina | { |
370 | 98272dbb | Pavel Hrdina | uint8_t drive = 0;
|
371 | 98272dbb | Pavel Hrdina | uint8_t head = 0;
|
372 | 98272dbb | Pavel Hrdina | uint8_t cyl = 1;
|
373 | c3cdc1b0 | Kevin Wolf | uint8_t pcn; |
374 | 98272dbb | Pavel Hrdina | |
375 | 98272dbb | Pavel Hrdina | /* Send seek to track 0 */
|
376 | c3cdc1b0 | Kevin Wolf | send_seek(0);
|
377 | 98272dbb | Pavel Hrdina | |
378 | 98272dbb | Pavel Hrdina | /* Send relative seek to increase track by 1 */
|
379 | 98272dbb | Pavel Hrdina | floppy_send(CMD_RELATIVE_SEEK_IN); |
380 | 98272dbb | Pavel Hrdina | floppy_send(head << 2 | drive);
|
381 | 98272dbb | Pavel Hrdina | g_assert(!get_irq(FLOPPY_IRQ)); |
382 | 98272dbb | Pavel Hrdina | floppy_send(cyl); |
383 | 98272dbb | Pavel Hrdina | |
384 | c3cdc1b0 | Kevin Wolf | ack_irq(&pcn); |
385 | c3cdc1b0 | Kevin Wolf | g_assert(pcn == 1);
|
386 | 98272dbb | Pavel Hrdina | |
387 | 98272dbb | Pavel Hrdina | /* Send relative seek to decrease track by 1 */
|
388 | 98272dbb | Pavel Hrdina | floppy_send(CMD_RELATIVE_SEEK_OUT); |
389 | 98272dbb | Pavel Hrdina | floppy_send(head << 2 | drive);
|
390 | 98272dbb | Pavel Hrdina | g_assert(!get_irq(FLOPPY_IRQ)); |
391 | 98272dbb | Pavel Hrdina | floppy_send(cyl); |
392 | 98272dbb | Pavel Hrdina | |
393 | c3cdc1b0 | Kevin Wolf | ack_irq(&pcn); |
394 | c3cdc1b0 | Kevin Wolf | g_assert(pcn == 0);
|
395 | 98272dbb | Pavel Hrdina | } |
396 | 98272dbb | Pavel Hrdina | |
397 | 67f194bd | Kevin Wolf | static void test_read_id(void) |
398 | 67f194bd | Kevin Wolf | { |
399 | 67f194bd | Kevin Wolf | uint8_t drive = 0;
|
400 | 67f194bd | Kevin Wolf | uint8_t head = 0;
|
401 | 67f194bd | Kevin Wolf | uint8_t cyl; |
402 | 67f194bd | Kevin Wolf | uint8_t st0; |
403 | 67f194bd | Kevin Wolf | |
404 | 67f194bd | Kevin Wolf | /* Seek to track 0 and check with READ ID */
|
405 | 67f194bd | Kevin Wolf | send_seek(0);
|
406 | 67f194bd | Kevin Wolf | |
407 | 67f194bd | Kevin Wolf | floppy_send(CMD_READ_ID); |
408 | 67f194bd | Kevin Wolf | g_assert(!get_irq(FLOPPY_IRQ)); |
409 | 67f194bd | Kevin Wolf | floppy_send(head << 2 | drive);
|
410 | 67f194bd | Kevin Wolf | |
411 | 67f194bd | Kevin Wolf | while (!get_irq(FLOPPY_IRQ)) {
|
412 | 67f194bd | Kevin Wolf | /* qemu involves a timer with READ ID... */
|
413 | 67f194bd | Kevin Wolf | clock_step(1000000000LL / 50); |
414 | 67f194bd | Kevin Wolf | } |
415 | 67f194bd | Kevin Wolf | |
416 | 67f194bd | Kevin Wolf | st0 = floppy_recv(); |
417 | 67f194bd | Kevin Wolf | floppy_recv(); |
418 | 67f194bd | Kevin Wolf | floppy_recv(); |
419 | 67f194bd | Kevin Wolf | cyl = floppy_recv(); |
420 | 67f194bd | Kevin Wolf | head = floppy_recv(); |
421 | 67f194bd | Kevin Wolf | floppy_recv(); |
422 | 67f194bd | Kevin Wolf | floppy_recv(); |
423 | 67f194bd | Kevin Wolf | |
424 | 67f194bd | Kevin Wolf | g_assert_cmpint(cyl, ==, 0);
|
425 | 67f194bd | Kevin Wolf | g_assert_cmpint(head, ==, 0);
|
426 | 67f194bd | Kevin Wolf | g_assert_cmpint(st0, ==, head << 2);
|
427 | 67f194bd | Kevin Wolf | |
428 | 67f194bd | Kevin Wolf | /* Seek to track 8 on head 1 and check with READ ID */
|
429 | 67f194bd | Kevin Wolf | head = 1;
|
430 | 67f194bd | Kevin Wolf | cyl = 8;
|
431 | 67f194bd | Kevin Wolf | |
432 | 67f194bd | Kevin Wolf | floppy_send(CMD_SEEK); |
433 | 67f194bd | Kevin Wolf | floppy_send(head << 2 | drive);
|
434 | 67f194bd | Kevin Wolf | g_assert(!get_irq(FLOPPY_IRQ)); |
435 | 67f194bd | Kevin Wolf | floppy_send(cyl); |
436 | 67f194bd | Kevin Wolf | g_assert(get_irq(FLOPPY_IRQ)); |
437 | 67f194bd | Kevin Wolf | ack_irq(NULL);
|
438 | 67f194bd | Kevin Wolf | |
439 | 67f194bd | Kevin Wolf | floppy_send(CMD_READ_ID); |
440 | 67f194bd | Kevin Wolf | g_assert(!get_irq(FLOPPY_IRQ)); |
441 | 67f194bd | Kevin Wolf | floppy_send(head << 2 | drive);
|
442 | 67f194bd | Kevin Wolf | |
443 | 67f194bd | Kevin Wolf | while (!get_irq(FLOPPY_IRQ)) {
|
444 | 67f194bd | Kevin Wolf | /* qemu involves a timer with READ ID... */
|
445 | 67f194bd | Kevin Wolf | clock_step(1000000000LL / 50); |
446 | 67f194bd | Kevin Wolf | } |
447 | 67f194bd | Kevin Wolf | |
448 | 67f194bd | Kevin Wolf | st0 = floppy_recv(); |
449 | 67f194bd | Kevin Wolf | floppy_recv(); |
450 | 67f194bd | Kevin Wolf | floppy_recv(); |
451 | 67f194bd | Kevin Wolf | cyl = floppy_recv(); |
452 | 67f194bd | Kevin Wolf | head = floppy_recv(); |
453 | 67f194bd | Kevin Wolf | floppy_recv(); |
454 | 67f194bd | Kevin Wolf | floppy_recv(); |
455 | 67f194bd | Kevin Wolf | |
456 | 67f194bd | Kevin Wolf | g_assert_cmpint(cyl, ==, 8);
|
457 | 67f194bd | Kevin Wolf | g_assert_cmpint(head, ==, 1);
|
458 | 67f194bd | Kevin Wolf | g_assert_cmpint(st0, ==, head << 2);
|
459 | 67f194bd | Kevin Wolf | } |
460 | 67f194bd | Kevin Wolf | |
461 | 5f8ae8e2 | Hervé Poussineau | static void test_read_no_dma_1(void) |
462 | 5f8ae8e2 | Hervé Poussineau | { |
463 | 5f8ae8e2 | Hervé Poussineau | uint8_t ret; |
464 | 5f8ae8e2 | Hervé Poussineau | |
465 | 5f8ae8e2 | Hervé Poussineau | outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
|
466 | 5f8ae8e2 | Hervé Poussineau | send_seek(0);
|
467 | 075f5532 | Hervé Poussineau | ret = send_read_no_dma_command(1, 0x04); |
468 | 5f8ae8e2 | Hervé Poussineau | g_assert(ret == 0);
|
469 | 5f8ae8e2 | Hervé Poussineau | } |
470 | 5f8ae8e2 | Hervé Poussineau | |
471 | 5f8ae8e2 | Hervé Poussineau | static void test_read_no_dma_18(void) |
472 | 5f8ae8e2 | Hervé Poussineau | { |
473 | 5f8ae8e2 | Hervé Poussineau | uint8_t ret; |
474 | 5f8ae8e2 | Hervé Poussineau | |
475 | 5f8ae8e2 | Hervé Poussineau | outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
|
476 | 5f8ae8e2 | Hervé Poussineau | send_seek(0);
|
477 | 075f5532 | Hervé Poussineau | ret = send_read_no_dma_command(18, 0x04); |
478 | 5f8ae8e2 | Hervé Poussineau | g_assert(ret == 0);
|
479 | 5f8ae8e2 | Hervé Poussineau | } |
480 | 5f8ae8e2 | Hervé Poussineau | |
481 | 5f8ae8e2 | Hervé Poussineau | static void test_read_no_dma_19(void) |
482 | 5f8ae8e2 | Hervé Poussineau | { |
483 | 5f8ae8e2 | Hervé Poussineau | uint8_t ret; |
484 | 5f8ae8e2 | Hervé Poussineau | |
485 | 5f8ae8e2 | Hervé Poussineau | outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
|
486 | 5f8ae8e2 | Hervé Poussineau | send_seek(0);
|
487 | 5f8ae8e2 | Hervé Poussineau | ret = send_read_no_dma_command(19, 0x20); |
488 | 5f8ae8e2 | Hervé Poussineau | g_assert(ret == 0);
|
489 | 5f8ae8e2 | Hervé Poussineau | } |
490 | 5f8ae8e2 | Hervé Poussineau | |
491 | 6f442fe8 | Hervé Poussineau | static void test_verify(void) |
492 | 6f442fe8 | Hervé Poussineau | { |
493 | 6f442fe8 | Hervé Poussineau | uint8_t ret; |
494 | 6f442fe8 | Hervé Poussineau | |
495 | 6f442fe8 | Hervé Poussineau | ret = send_read_command(CMD_VERIFY); |
496 | 6f442fe8 | Hervé Poussineau | g_assert(ret == 0);
|
497 | 6f442fe8 | Hervé Poussineau | } |
498 | 6f442fe8 | Hervé Poussineau | |
499 | 3359847e | Blue Swirl | /* success if no crash or abort */
|
500 | 3359847e | Blue Swirl | static void fuzz_registers(void) |
501 | 3359847e | Blue Swirl | { |
502 | 3359847e | Blue Swirl | unsigned int i; |
503 | 3359847e | Blue Swirl | |
504 | 3359847e | Blue Swirl | for (i = 0; i < 1000; i++) { |
505 | 3359847e | Blue Swirl | uint8_t reg, val; |
506 | 3359847e | Blue Swirl | |
507 | 3359847e | Blue Swirl | reg = (uint8_t)g_test_rand_int_range(0, 8); |
508 | 3359847e | Blue Swirl | val = (uint8_t)g_test_rand_int_range(0, 256); |
509 | 3359847e | Blue Swirl | |
510 | 3359847e | Blue Swirl | outb(FLOPPY_BASE + reg, val); |
511 | 3359847e | Blue Swirl | inb(FLOPPY_BASE + reg); |
512 | 3359847e | Blue Swirl | } |
513 | 3359847e | Blue Swirl | } |
514 | 3359847e | Blue Swirl | |
515 | 93e9eb68 | Kevin Wolf | int main(int argc, char **argv) |
516 | 93e9eb68 | Kevin Wolf | { |
517 | 93e9eb68 | Kevin Wolf | const char *arch = qtest_get_arch(); |
518 | 93e9eb68 | Kevin Wolf | char *cmdline;
|
519 | 93e9eb68 | Kevin Wolf | int fd;
|
520 | 93e9eb68 | Kevin Wolf | int ret;
|
521 | 93e9eb68 | Kevin Wolf | |
522 | 93e9eb68 | Kevin Wolf | /* Check architecture */
|
523 | 93e9eb68 | Kevin Wolf | if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) { |
524 | 93e9eb68 | Kevin Wolf | g_test_message("Skipping test for non-x86\n");
|
525 | 93e9eb68 | Kevin Wolf | return 0; |
526 | 93e9eb68 | Kevin Wolf | } |
527 | 93e9eb68 | Kevin Wolf | |
528 | 93e9eb68 | Kevin Wolf | /* Create a temporary raw image */
|
529 | 93e9eb68 | Kevin Wolf | fd = mkstemp(test_image); |
530 | 93e9eb68 | Kevin Wolf | g_assert(fd >= 0);
|
531 | 93e9eb68 | Kevin Wolf | ret = ftruncate(fd, TEST_IMAGE_SIZE); |
532 | 93e9eb68 | Kevin Wolf | g_assert(ret == 0);
|
533 | 93e9eb68 | Kevin Wolf | close(fd); |
534 | 93e9eb68 | Kevin Wolf | |
535 | 93e9eb68 | Kevin Wolf | /* Run the tests */
|
536 | 93e9eb68 | Kevin Wolf | g_test_init(&argc, &argv, NULL);
|
537 | 93e9eb68 | Kevin Wolf | |
538 | 7cd33161 | Pavel Hrdina | cmdline = g_strdup_printf("-vnc none ");
|
539 | 93e9eb68 | Kevin Wolf | |
540 | 93e9eb68 | Kevin Wolf | qtest_start(cmdline); |
541 | 93e9eb68 | Kevin Wolf | qtest_irq_intercept_in(global_qtest, "ioapic");
|
542 | 7cd33161 | Pavel Hrdina | qtest_add_func("/fdc/cmos", test_cmos);
|
543 | 7cd33161 | Pavel Hrdina | qtest_add_func("/fdc/no_media_on_start", test_no_media_on_start);
|
544 | 8b9ef60d | Pavel Hrdina | qtest_add_func("/fdc/read_without_media", test_read_without_media);
|
545 | 93e9eb68 | Kevin Wolf | qtest_add_func("/fdc/media_change", test_media_change);
|
546 | b3ce604e | Pavel Hrdina | qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
|
547 | 98272dbb | Pavel Hrdina | qtest_add_func("/fdc/relative_seek", test_relative_seek);
|
548 | 67f194bd | Kevin Wolf | qtest_add_func("/fdc/read_id", test_read_id);
|
549 | 6f442fe8 | Hervé Poussineau | qtest_add_func("/fdc/verify", test_verify);
|
550 | 44212dcc | Hervé Poussineau | qtest_add_func("/fdc/media_insert", test_media_insert);
|
551 | 5f8ae8e2 | Hervé Poussineau | qtest_add_func("/fdc/read_no_dma_1", test_read_no_dma_1);
|
552 | 5f8ae8e2 | Hervé Poussineau | qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18);
|
553 | 5f8ae8e2 | Hervé Poussineau | qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19);
|
554 | 3359847e | Blue Swirl | qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
|
555 | 93e9eb68 | Kevin Wolf | |
556 | 93e9eb68 | Kevin Wolf | ret = g_test_run(); |
557 | 93e9eb68 | Kevin Wolf | |
558 | 93e9eb68 | Kevin Wolf | /* Cleanup */
|
559 | 93e9eb68 | Kevin Wolf | qtest_quit(global_qtest); |
560 | 93e9eb68 | Kevin Wolf | unlink(test_image); |
561 | 93e9eb68 | Kevin Wolf | |
562 | 93e9eb68 | Kevin Wolf | return ret;
|
563 | 93e9eb68 | Kevin Wolf | } |