acpi: add function to extract oem_id and oem_table_id from the user's SLIC
[qemu/cris-port.git] / hw / block / fdc.c
blob818e8a4072eeeb511b67daa02be04ac5627fba73
1 /*
2 * QEMU Floppy disk emulator (Intel 82078)
4 * Copyright (c) 2003, 2007 Jocelyn Mayer
5 * Copyright (c) 2008 Hervé Poussineau
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
26 * The controller is used in Sun4m systems in a slightly different
27 * way. There are changes in DOR register and DMA is not available.
30 #include "qemu/osdep.h"
31 #include "hw/hw.h"
32 #include "hw/block/fdc.h"
33 #include "qemu/error-report.h"
34 #include "qemu/timer.h"
35 #include "hw/isa/isa.h"
36 #include "hw/sysbus.h"
37 #include "sysemu/block-backend.h"
38 #include "sysemu/blockdev.h"
39 #include "sysemu/sysemu.h"
40 #include "qemu/log.h"
42 /********************************************************/
43 /* debug Floppy devices */
44 //#define DEBUG_FLOPPY
46 #ifdef DEBUG_FLOPPY
47 #define FLOPPY_DPRINTF(fmt, ...) \
48 do { printf("FLOPPY: " fmt , ## __VA_ARGS__); } while (0)
49 #else
50 #define FLOPPY_DPRINTF(fmt, ...)
51 #endif
53 /********************************************************/
54 /* Floppy drive emulation */
56 typedef enum FDriveRate {
57 FDRIVE_RATE_500K = 0x00, /* 500 Kbps */
58 FDRIVE_RATE_300K = 0x01, /* 300 Kbps */
59 FDRIVE_RATE_250K = 0x02, /* 250 Kbps */
60 FDRIVE_RATE_1M = 0x03, /* 1 Mbps */
61 } FDriveRate;
63 typedef enum FDriveSize {
64 FDRIVE_SIZE_UNKNOWN,
65 FDRIVE_SIZE_350,
66 FDRIVE_SIZE_525,
67 } FDriveSize;
69 typedef struct FDFormat {
70 FloppyDriveType drive;
71 uint8_t last_sect;
72 uint8_t max_track;
73 uint8_t max_head;
74 FDriveRate rate;
75 } FDFormat;
77 /* In many cases, the total sector size of a format is enough to uniquely
78 * identify it. However, there are some total sector collisions between
79 * formats of different physical size, and these are noted below by
80 * highlighting the total sector size for entries with collisions. */
81 static const FDFormat fd_formats[] = {
82 /* First entry is default format */
83 /* 1.44 MB 3"1/2 floppy disks */
84 { FLOPPY_DRIVE_TYPE_144, 18, 80, 1, FDRIVE_RATE_500K, }, /* 3.5" 2880 */
85 { FLOPPY_DRIVE_TYPE_144, 20, 80, 1, FDRIVE_RATE_500K, }, /* 3.5" 3200 */
86 { FLOPPY_DRIVE_TYPE_144, 21, 80, 1, FDRIVE_RATE_500K, },
87 { FLOPPY_DRIVE_TYPE_144, 21, 82, 1, FDRIVE_RATE_500K, },
88 { FLOPPY_DRIVE_TYPE_144, 21, 83, 1, FDRIVE_RATE_500K, },
89 { FLOPPY_DRIVE_TYPE_144, 22, 80, 1, FDRIVE_RATE_500K, },
90 { FLOPPY_DRIVE_TYPE_144, 23, 80, 1, FDRIVE_RATE_500K, },
91 { FLOPPY_DRIVE_TYPE_144, 24, 80, 1, FDRIVE_RATE_500K, },
92 /* 2.88 MB 3"1/2 floppy disks */
93 { FLOPPY_DRIVE_TYPE_288, 36, 80, 1, FDRIVE_RATE_1M, },
94 { FLOPPY_DRIVE_TYPE_288, 39, 80, 1, FDRIVE_RATE_1M, },
95 { FLOPPY_DRIVE_TYPE_288, 40, 80, 1, FDRIVE_RATE_1M, },
96 { FLOPPY_DRIVE_TYPE_288, 44, 80, 1, FDRIVE_RATE_1M, },
97 { FLOPPY_DRIVE_TYPE_288, 48, 80, 1, FDRIVE_RATE_1M, },
98 /* 720 kB 3"1/2 floppy disks */
99 { FLOPPY_DRIVE_TYPE_144, 9, 80, 1, FDRIVE_RATE_250K, }, /* 3.5" 1440 */
100 { FLOPPY_DRIVE_TYPE_144, 10, 80, 1, FDRIVE_RATE_250K, },
101 { FLOPPY_DRIVE_TYPE_144, 10, 82, 1, FDRIVE_RATE_250K, },
102 { FLOPPY_DRIVE_TYPE_144, 10, 83, 1, FDRIVE_RATE_250K, },
103 { FLOPPY_DRIVE_TYPE_144, 13, 80, 1, FDRIVE_RATE_250K, },
104 { FLOPPY_DRIVE_TYPE_144, 14, 80, 1, FDRIVE_RATE_250K, },
105 /* 1.2 MB 5"1/4 floppy disks */
106 { FLOPPY_DRIVE_TYPE_120, 15, 80, 1, FDRIVE_RATE_500K, },
107 { FLOPPY_DRIVE_TYPE_120, 18, 80, 1, FDRIVE_RATE_500K, }, /* 5.25" 2880 */
108 { FLOPPY_DRIVE_TYPE_120, 18, 82, 1, FDRIVE_RATE_500K, },
109 { FLOPPY_DRIVE_TYPE_120, 18, 83, 1, FDRIVE_RATE_500K, },
110 { FLOPPY_DRIVE_TYPE_120, 20, 80, 1, FDRIVE_RATE_500K, }, /* 5.25" 3200 */
111 /* 720 kB 5"1/4 floppy disks */
112 { FLOPPY_DRIVE_TYPE_120, 9, 80, 1, FDRIVE_RATE_250K, }, /* 5.25" 1440 */
113 { FLOPPY_DRIVE_TYPE_120, 11, 80, 1, FDRIVE_RATE_250K, },
114 /* 360 kB 5"1/4 floppy disks */
115 { FLOPPY_DRIVE_TYPE_120, 9, 40, 1, FDRIVE_RATE_300K, }, /* 5.25" 720 */
116 { FLOPPY_DRIVE_TYPE_120, 9, 40, 0, FDRIVE_RATE_300K, },
117 { FLOPPY_DRIVE_TYPE_120, 10, 41, 1, FDRIVE_RATE_300K, },
118 { FLOPPY_DRIVE_TYPE_120, 10, 42, 1, FDRIVE_RATE_300K, },
119 /* 320 kB 5"1/4 floppy disks */
120 { FLOPPY_DRIVE_TYPE_120, 8, 40, 1, FDRIVE_RATE_250K, },
121 { FLOPPY_DRIVE_TYPE_120, 8, 40, 0, FDRIVE_RATE_250K, },
122 /* 360 kB must match 5"1/4 better than 3"1/2... */
123 { FLOPPY_DRIVE_TYPE_144, 9, 80, 0, FDRIVE_RATE_250K, }, /* 3.5" 720 */
124 /* end */
125 { FLOPPY_DRIVE_TYPE_NONE, -1, -1, 0, 0, },
128 static FDriveSize drive_size(FloppyDriveType drive)
130 switch (drive) {
131 case FLOPPY_DRIVE_TYPE_120:
132 return FDRIVE_SIZE_525;
133 case FLOPPY_DRIVE_TYPE_144:
134 case FLOPPY_DRIVE_TYPE_288:
135 return FDRIVE_SIZE_350;
136 default:
137 return FDRIVE_SIZE_UNKNOWN;
141 #define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
142 #define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
144 /* Will always be a fixed parameter for us */
145 #define FD_SECTOR_LEN 512
146 #define FD_SECTOR_SC 2 /* Sector size code */
147 #define FD_RESET_SENSEI_COUNT 4 /* Number of sense interrupts on RESET */
149 typedef struct FDCtrl FDCtrl;
151 /* Floppy disk drive emulation */
152 typedef enum FDiskFlags {
153 FDISK_DBL_SIDES = 0x01,
154 } FDiskFlags;
156 typedef struct FDrive {
157 FDCtrl *fdctrl;
158 BlockBackend *blk;
159 /* Drive status */
160 FloppyDriveType drive; /* CMOS drive type */
161 uint8_t perpendicular; /* 2.88 MB access mode */
162 /* Position */
163 uint8_t head;
164 uint8_t track;
165 uint8_t sect;
166 /* Media */
167 FloppyDriveType disk; /* Current disk type */
168 FDiskFlags flags;
169 uint8_t last_sect; /* Nb sector per track */
170 uint8_t max_track; /* Nb of tracks */
171 uint16_t bps; /* Bytes per sector */
172 uint8_t ro; /* Is read-only */
173 uint8_t media_changed; /* Is media changed */
174 uint8_t media_rate; /* Data rate of medium */
176 bool media_validated; /* Have we validated the media? */
177 } FDrive;
180 static FloppyDriveType get_fallback_drive_type(FDrive *drv);
182 static void fd_init(FDrive *drv)
184 /* Drive */
185 drv->perpendicular = 0;
186 /* Disk */
187 drv->disk = FLOPPY_DRIVE_TYPE_NONE;
188 drv->last_sect = 0;
189 drv->max_track = 0;
190 drv->ro = true;
191 drv->media_changed = 1;
194 #define NUM_SIDES(drv) ((drv)->flags & FDISK_DBL_SIDES ? 2 : 1)
196 static int fd_sector_calc(uint8_t head, uint8_t track, uint8_t sect,
197 uint8_t last_sect, uint8_t num_sides)
199 return (((track * num_sides) + head) * last_sect) + sect - 1;
202 /* Returns current position, in sectors, for given drive */
203 static int fd_sector(FDrive *drv)
205 return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect,
206 NUM_SIDES(drv));
209 /* Seek to a new position:
210 * returns 0 if already on right track
211 * returns 1 if track changed
212 * returns 2 if track is invalid
213 * returns 3 if sector is invalid
214 * returns 4 if seek is disabled
216 static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
217 int enable_seek)
219 uint32_t sector;
220 int ret;
222 if (track > drv->max_track ||
223 (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
224 FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
225 head, track, sect, 1,
226 (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
227 drv->max_track, drv->last_sect);
228 return 2;
230 if (sect > drv->last_sect) {
231 FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
232 head, track, sect, 1,
233 (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
234 drv->max_track, drv->last_sect);
235 return 3;
237 sector = fd_sector_calc(head, track, sect, drv->last_sect, NUM_SIDES(drv));
238 ret = 0;
239 if (sector != fd_sector(drv)) {
240 #if 0
241 if (!enable_seek) {
242 FLOPPY_DPRINTF("error: no implicit seek %d %02x %02x"
243 " (max=%d %02x %02x)\n",
244 head, track, sect, 1, drv->max_track,
245 drv->last_sect);
246 return 4;
248 #endif
249 drv->head = head;
250 if (drv->track != track) {
251 if (drv->blk != NULL && blk_is_inserted(drv->blk)) {
252 drv->media_changed = 0;
254 ret = 1;
256 drv->track = track;
257 drv->sect = sect;
260 if (drv->blk == NULL || !blk_is_inserted(drv->blk)) {
261 ret = 2;
264 return ret;
267 /* Set drive back to track 0 */
268 static void fd_recalibrate(FDrive *drv)
270 FLOPPY_DPRINTF("recalibrate\n");
271 fd_seek(drv, 0, 0, 1, 1);
275 * Determine geometry based on inserted diskette.
276 * Will not operate on an empty drive.
278 * @return: 0 on success, -1 if the drive is empty.
280 static int pick_geometry(FDrive *drv)
282 BlockBackend *blk = drv->blk;
283 const FDFormat *parse;
284 uint64_t nb_sectors, size;
285 int i;
286 int match, size_match, type_match;
287 bool magic = drv->drive == FLOPPY_DRIVE_TYPE_AUTO;
289 /* We can only pick a geometry if we have a diskette. */
290 if (!drv->blk || !blk_is_inserted(drv->blk) ||
291 drv->drive == FLOPPY_DRIVE_TYPE_NONE)
293 return -1;
296 /* We need to determine the likely geometry of the inserted medium.
297 * In order of preference, we look for:
298 * (1) The same drive type and number of sectors,
299 * (2) The same diskette size and number of sectors,
300 * (3) The same drive type.
302 * In all cases, matches that occur higher in the drive table will take
303 * precedence over matches that occur later in the table.
305 blk_get_geometry(blk, &nb_sectors);
306 match = size_match = type_match = -1;
307 for (i = 0; ; i++) {
308 parse = &fd_formats[i];
309 if (parse->drive == FLOPPY_DRIVE_TYPE_NONE) {
310 break;
312 size = (parse->max_head + 1) * parse->max_track * parse->last_sect;
313 if (nb_sectors == size) {
314 if (magic || parse->drive == drv->drive) {
315 /* (1) perfect match -- nb_sectors and drive type */
316 goto out;
317 } else if (drive_size(parse->drive) == drive_size(drv->drive)) {
318 /* (2) size match -- nb_sectors and physical medium size */
319 match = (match == -1) ? i : match;
320 } else {
321 /* This is suspicious -- Did the user misconfigure? */
322 size_match = (size_match == -1) ? i : size_match;
324 } else if (type_match == -1) {
325 if ((parse->drive == drv->drive) ||
326 (magic && (parse->drive == get_fallback_drive_type(drv)))) {
327 /* (3) type match -- nb_sectors mismatch, but matches the type
328 * specified explicitly by the user, or matches the fallback
329 * default type when using the drive autodetect mechanism */
330 type_match = i;
335 /* No exact match found */
336 if (match == -1) {
337 if (size_match != -1) {
338 parse = &fd_formats[size_match];
339 FLOPPY_DPRINTF("User requested floppy drive type '%s', "
340 "but inserted medium appears to be a "
341 "%d sector '%s' type\n",
342 FloppyDriveType_lookup[drv->drive],
343 nb_sectors,
344 FloppyDriveType_lookup[parse->drive]);
346 match = type_match;
349 /* No match of any kind found -- fd_format is misconfigured, abort. */
350 if (match == -1) {
351 error_setg(&error_abort, "No candidate geometries present in table "
352 " for floppy drive type '%s'",
353 FloppyDriveType_lookup[drv->drive]);
356 parse = &(fd_formats[match]);
358 out:
359 if (parse->max_head == 0) {
360 drv->flags &= ~FDISK_DBL_SIDES;
361 } else {
362 drv->flags |= FDISK_DBL_SIDES;
364 drv->max_track = parse->max_track;
365 drv->last_sect = parse->last_sect;
366 drv->disk = parse->drive;
367 drv->media_rate = parse->rate;
368 return 0;
371 static void pick_drive_type(FDrive *drv)
373 if (drv->drive != FLOPPY_DRIVE_TYPE_AUTO) {
374 return;
377 if (pick_geometry(drv) == 0) {
378 drv->drive = drv->disk;
379 } else {
380 drv->drive = get_fallback_drive_type(drv);
383 g_assert(drv->drive != FLOPPY_DRIVE_TYPE_AUTO);
386 /* Revalidate a disk drive after a disk change */
387 static void fd_revalidate(FDrive *drv)
389 int rc;
391 FLOPPY_DPRINTF("revalidate\n");
392 if (drv->blk != NULL) {
393 drv->ro = blk_is_read_only(drv->blk);
394 if (!blk_is_inserted(drv->blk)) {
395 FLOPPY_DPRINTF("No disk in drive\n");
396 drv->disk = FLOPPY_DRIVE_TYPE_NONE;
397 } else if (!drv->media_validated) {
398 rc = pick_geometry(drv);
399 if (rc) {
400 FLOPPY_DPRINTF("Could not validate floppy drive media");
401 } else {
402 drv->media_validated = true;
403 FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n",
404 (drv->flags & FDISK_DBL_SIDES) ? 2 : 1,
405 drv->max_track, drv->last_sect,
406 drv->ro ? "ro" : "rw");
409 } else {
410 FLOPPY_DPRINTF("No drive connected\n");
411 drv->last_sect = 0;
412 drv->max_track = 0;
413 drv->flags &= ~FDISK_DBL_SIDES;
414 drv->drive = FLOPPY_DRIVE_TYPE_NONE;
415 drv->disk = FLOPPY_DRIVE_TYPE_NONE;
419 /********************************************************/
420 /* Intel 82078 floppy disk controller emulation */
422 static void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
423 static void fdctrl_to_command_phase(FDCtrl *fdctrl);
424 static int fdctrl_transfer_handler (void *opaque, int nchan,
425 int dma_pos, int dma_len);
426 static void fdctrl_raise_irq(FDCtrl *fdctrl);
427 static FDrive *get_cur_drv(FDCtrl *fdctrl);
429 static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl);
430 static uint32_t fdctrl_read_statusB(FDCtrl *fdctrl);
431 static uint32_t fdctrl_read_dor(FDCtrl *fdctrl);
432 static void fdctrl_write_dor(FDCtrl *fdctrl, uint32_t value);
433 static uint32_t fdctrl_read_tape(FDCtrl *fdctrl);
434 static void fdctrl_write_tape(FDCtrl *fdctrl, uint32_t value);
435 static uint32_t fdctrl_read_main_status(FDCtrl *fdctrl);
436 static void fdctrl_write_rate(FDCtrl *fdctrl, uint32_t value);
437 static uint32_t fdctrl_read_data(FDCtrl *fdctrl);
438 static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value);
439 static uint32_t fdctrl_read_dir(FDCtrl *fdctrl);
440 static void fdctrl_write_ccr(FDCtrl *fdctrl, uint32_t value);
442 enum {
443 FD_DIR_WRITE = 0,
444 FD_DIR_READ = 1,
445 FD_DIR_SCANE = 2,
446 FD_DIR_SCANL = 3,
447 FD_DIR_SCANH = 4,
448 FD_DIR_VERIFY = 5,
451 enum {
452 FD_STATE_MULTI = 0x01, /* multi track flag */
453 FD_STATE_FORMAT = 0x02, /* format flag */
456 enum {
457 FD_REG_SRA = 0x00,
458 FD_REG_SRB = 0x01,
459 FD_REG_DOR = 0x02,
460 FD_REG_TDR = 0x03,
461 FD_REG_MSR = 0x04,
462 FD_REG_DSR = 0x04,
463 FD_REG_FIFO = 0x05,
464 FD_REG_DIR = 0x07,
465 FD_REG_CCR = 0x07,
468 enum {
469 FD_CMD_READ_TRACK = 0x02,
470 FD_CMD_SPECIFY = 0x03,
471 FD_CMD_SENSE_DRIVE_STATUS = 0x04,
472 FD_CMD_WRITE = 0x05,
473 FD_CMD_READ = 0x06,
474 FD_CMD_RECALIBRATE = 0x07,
475 FD_CMD_SENSE_INTERRUPT_STATUS = 0x08,
476 FD_CMD_WRITE_DELETED = 0x09,
477 FD_CMD_READ_ID = 0x0a,
478 FD_CMD_READ_DELETED = 0x0c,
479 FD_CMD_FORMAT_TRACK = 0x0d,
480 FD_CMD_DUMPREG = 0x0e,
481 FD_CMD_SEEK = 0x0f,
482 FD_CMD_VERSION = 0x10,
483 FD_CMD_SCAN_EQUAL = 0x11,
484 FD_CMD_PERPENDICULAR_MODE = 0x12,
485 FD_CMD_CONFIGURE = 0x13,
486 FD_CMD_LOCK = 0x14,
487 FD_CMD_VERIFY = 0x16,
488 FD_CMD_POWERDOWN_MODE = 0x17,
489 FD_CMD_PART_ID = 0x18,
490 FD_CMD_SCAN_LOW_OR_EQUAL = 0x19,
491 FD_CMD_SCAN_HIGH_OR_EQUAL = 0x1d,
492 FD_CMD_SAVE = 0x2e,
493 FD_CMD_OPTION = 0x33,
494 FD_CMD_RESTORE = 0x4e,
495 FD_CMD_DRIVE_SPECIFICATION_COMMAND = 0x8e,
496 FD_CMD_RELATIVE_SEEK_OUT = 0x8f,
497 FD_CMD_FORMAT_AND_WRITE = 0xcd,
498 FD_CMD_RELATIVE_SEEK_IN = 0xcf,
501 enum {
502 FD_CONFIG_PRETRK = 0xff, /* Pre-compensation set to track 0 */
503 FD_CONFIG_FIFOTHR = 0x0f, /* FIFO threshold set to 1 byte */
504 FD_CONFIG_POLL = 0x10, /* Poll enabled */
505 FD_CONFIG_EFIFO = 0x20, /* FIFO disabled */
506 FD_CONFIG_EIS = 0x40, /* No implied seeks */
509 enum {
510 FD_SR0_DS0 = 0x01,
511 FD_SR0_DS1 = 0x02,
512 FD_SR0_HEAD = 0x04,
513 FD_SR0_EQPMT = 0x10,
514 FD_SR0_SEEK = 0x20,
515 FD_SR0_ABNTERM = 0x40,
516 FD_SR0_INVCMD = 0x80,
517 FD_SR0_RDYCHG = 0xc0,
520 enum {
521 FD_SR1_MA = 0x01, /* Missing address mark */
522 FD_SR1_NW = 0x02, /* Not writable */
523 FD_SR1_EC = 0x80, /* End of cylinder */
526 enum {
527 FD_SR2_SNS = 0x04, /* Scan not satisfied */
528 FD_SR2_SEH = 0x08, /* Scan equal hit */
531 enum {
532 FD_SRA_DIR = 0x01,
533 FD_SRA_nWP = 0x02,
534 FD_SRA_nINDX = 0x04,
535 FD_SRA_HDSEL = 0x08,
536 FD_SRA_nTRK0 = 0x10,
537 FD_SRA_STEP = 0x20,
538 FD_SRA_nDRV2 = 0x40,
539 FD_SRA_INTPEND = 0x80,
542 enum {
543 FD_SRB_MTR0 = 0x01,
544 FD_SRB_MTR1 = 0x02,
545 FD_SRB_WGATE = 0x04,
546 FD_SRB_RDATA = 0x08,
547 FD_SRB_WDATA = 0x10,
548 FD_SRB_DR0 = 0x20,
551 enum {
552 #if MAX_FD == 4
553 FD_DOR_SELMASK = 0x03,
554 #else
555 FD_DOR_SELMASK = 0x01,
556 #endif
557 FD_DOR_nRESET = 0x04,
558 FD_DOR_DMAEN = 0x08,
559 FD_DOR_MOTEN0 = 0x10,
560 FD_DOR_MOTEN1 = 0x20,
561 FD_DOR_MOTEN2 = 0x40,
562 FD_DOR_MOTEN3 = 0x80,
565 enum {
566 #if MAX_FD == 4
567 FD_TDR_BOOTSEL = 0x0c,
568 #else
569 FD_TDR_BOOTSEL = 0x04,
570 #endif
573 enum {
574 FD_DSR_DRATEMASK= 0x03,
575 FD_DSR_PWRDOWN = 0x40,
576 FD_DSR_SWRESET = 0x80,
579 enum {
580 FD_MSR_DRV0BUSY = 0x01,
581 FD_MSR_DRV1BUSY = 0x02,
582 FD_MSR_DRV2BUSY = 0x04,
583 FD_MSR_DRV3BUSY = 0x08,
584 FD_MSR_CMDBUSY = 0x10,
585 FD_MSR_NONDMA = 0x20,
586 FD_MSR_DIO = 0x40,
587 FD_MSR_RQM = 0x80,
590 enum {
591 FD_DIR_DSKCHG = 0x80,
595 * See chapter 5.0 "Controller phases" of the spec:
597 * Command phase:
598 * The host writes a command and its parameters into the FIFO. The command
599 * phase is completed when all parameters for the command have been supplied,
600 * and execution phase is entered.
602 * Execution phase:
603 * Data transfers, either DMA or non-DMA. For non-DMA transfers, the FIFO
604 * contains the payload now, otherwise it's unused. When all bytes of the
605 * required data have been transferred, the state is switched to either result
606 * phase (if the command produces status bytes) or directly back into the
607 * command phase for the next command.
609 * Result phase:
610 * The host reads out the FIFO, which contains one or more result bytes now.
612 enum {
613 /* Only for migration: reconstruct phase from registers like qemu 2.3 */
614 FD_PHASE_RECONSTRUCT = 0,
616 FD_PHASE_COMMAND = 1,
617 FD_PHASE_EXECUTION = 2,
618 FD_PHASE_RESULT = 3,
621 #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
622 #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
624 struct FDCtrl {
625 MemoryRegion iomem;
626 qemu_irq irq;
627 /* Controller state */
628 QEMUTimer *result_timer;
629 int dma_chann;
630 uint8_t phase;
631 /* Controller's identification */
632 uint8_t version;
633 /* HW */
634 uint8_t sra;
635 uint8_t srb;
636 uint8_t dor;
637 uint8_t dor_vmstate; /* only used as temp during vmstate */
638 uint8_t tdr;
639 uint8_t dsr;
640 uint8_t msr;
641 uint8_t cur_drv;
642 uint8_t status0;
643 uint8_t status1;
644 uint8_t status2;
645 /* Command FIFO */
646 uint8_t *fifo;
647 int32_t fifo_size;
648 uint32_t data_pos;
649 uint32_t data_len;
650 uint8_t data_state;
651 uint8_t data_dir;
652 uint8_t eot; /* last wanted sector */
653 /* States kept only to be returned back */
654 /* precompensation */
655 uint8_t precomp_trk;
656 uint8_t config;
657 uint8_t lock;
658 /* Power down config (also with status regB access mode */
659 uint8_t pwrd;
660 /* Floppy drives */
661 uint8_t num_floppies;
662 FDrive drives[MAX_FD];
663 int reset_sensei;
664 uint32_t check_media_rate;
665 FloppyDriveType fallback; /* type=auto failure fallback */
666 /* Timers state */
667 uint8_t timer0;
668 uint8_t timer1;
671 static FloppyDriveType get_fallback_drive_type(FDrive *drv)
673 return drv->fdctrl->fallback;
676 #define TYPE_SYSBUS_FDC "base-sysbus-fdc"
677 #define SYSBUS_FDC(obj) OBJECT_CHECK(FDCtrlSysBus, (obj), TYPE_SYSBUS_FDC)
679 typedef struct FDCtrlSysBus {
680 /*< private >*/
681 SysBusDevice parent_obj;
682 /*< public >*/
684 struct FDCtrl state;
685 } FDCtrlSysBus;
687 #define ISA_FDC(obj) OBJECT_CHECK(FDCtrlISABus, (obj), TYPE_ISA_FDC)
689 typedef struct FDCtrlISABus {
690 ISADevice parent_obj;
692 uint32_t iobase;
693 uint32_t irq;
694 uint32_t dma;
695 struct FDCtrl state;
696 int32_t bootindexA;
697 int32_t bootindexB;
698 } FDCtrlISABus;
700 static uint32_t fdctrl_read (void *opaque, uint32_t reg)
702 FDCtrl *fdctrl = opaque;
703 uint32_t retval;
705 reg &= 7;
706 switch (reg) {
707 case FD_REG_SRA:
708 retval = fdctrl_read_statusA(fdctrl);
709 break;
710 case FD_REG_SRB:
711 retval = fdctrl_read_statusB(fdctrl);
712 break;
713 case FD_REG_DOR:
714 retval = fdctrl_read_dor(fdctrl);
715 break;
716 case FD_REG_TDR:
717 retval = fdctrl_read_tape(fdctrl);
718 break;
719 case FD_REG_MSR:
720 retval = fdctrl_read_main_status(fdctrl);
721 break;
722 case FD_REG_FIFO:
723 retval = fdctrl_read_data(fdctrl);
724 break;
725 case FD_REG_DIR:
726 retval = fdctrl_read_dir(fdctrl);
727 break;
728 default:
729 retval = (uint32_t)(-1);
730 break;
732 FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval);
734 return retval;
737 static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
739 FDCtrl *fdctrl = opaque;
741 FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);
743 reg &= 7;
744 switch (reg) {
745 case FD_REG_DOR:
746 fdctrl_write_dor(fdctrl, value);
747 break;
748 case FD_REG_TDR:
749 fdctrl_write_tape(fdctrl, value);
750 break;
751 case FD_REG_DSR:
752 fdctrl_write_rate(fdctrl, value);
753 break;
754 case FD_REG_FIFO:
755 fdctrl_write_data(fdctrl, value);
756 break;
757 case FD_REG_CCR:
758 fdctrl_write_ccr(fdctrl, value);
759 break;
760 default:
761 break;
765 static uint64_t fdctrl_read_mem (void *opaque, hwaddr reg,
766 unsigned ize)
768 return fdctrl_read(opaque, (uint32_t)reg);
771 static void fdctrl_write_mem (void *opaque, hwaddr reg,
772 uint64_t value, unsigned size)
774 fdctrl_write(opaque, (uint32_t)reg, value);
777 static const MemoryRegionOps fdctrl_mem_ops = {
778 .read = fdctrl_read_mem,
779 .write = fdctrl_write_mem,
780 .endianness = DEVICE_NATIVE_ENDIAN,
783 static const MemoryRegionOps fdctrl_mem_strict_ops = {
784 .read = fdctrl_read_mem,
785 .write = fdctrl_write_mem,
786 .endianness = DEVICE_NATIVE_ENDIAN,
787 .valid = {
788 .min_access_size = 1,
789 .max_access_size = 1,
793 static bool fdrive_media_changed_needed(void *opaque)
795 FDrive *drive = opaque;
797 return (drive->blk != NULL && drive->media_changed != 1);
800 static const VMStateDescription vmstate_fdrive_media_changed = {
801 .name = "fdrive/media_changed",
802 .version_id = 1,
803 .minimum_version_id = 1,
804 .needed = fdrive_media_changed_needed,
805 .fields = (VMStateField[]) {
806 VMSTATE_UINT8(media_changed, FDrive),
807 VMSTATE_END_OF_LIST()
811 static bool fdrive_media_rate_needed(void *opaque)
813 FDrive *drive = opaque;
815 return drive->fdctrl->check_media_rate;
818 static const VMStateDescription vmstate_fdrive_media_rate = {
819 .name = "fdrive/media_rate",
820 .version_id = 1,
821 .minimum_version_id = 1,
822 .needed = fdrive_media_rate_needed,
823 .fields = (VMStateField[]) {
824 VMSTATE_UINT8(media_rate, FDrive),
825 VMSTATE_END_OF_LIST()
829 static bool fdrive_perpendicular_needed(void *opaque)
831 FDrive *drive = opaque;
833 return drive->perpendicular != 0;
836 static const VMStateDescription vmstate_fdrive_perpendicular = {
837 .name = "fdrive/perpendicular",
838 .version_id = 1,
839 .minimum_version_id = 1,
840 .needed = fdrive_perpendicular_needed,
841 .fields = (VMStateField[]) {
842 VMSTATE_UINT8(perpendicular, FDrive),
843 VMSTATE_END_OF_LIST()
847 static int fdrive_post_load(void *opaque, int version_id)
849 fd_revalidate(opaque);
850 return 0;
853 static const VMStateDescription vmstate_fdrive = {
854 .name = "fdrive",
855 .version_id = 1,
856 .minimum_version_id = 1,
857 .post_load = fdrive_post_load,
858 .fields = (VMStateField[]) {
859 VMSTATE_UINT8(head, FDrive),
860 VMSTATE_UINT8(track, FDrive),
861 VMSTATE_UINT8(sect, FDrive),
862 VMSTATE_END_OF_LIST()
864 .subsections = (const VMStateDescription*[]) {
865 &vmstate_fdrive_media_changed,
866 &vmstate_fdrive_media_rate,
867 &vmstate_fdrive_perpendicular,
868 NULL
873 * Reconstructs the phase from register values according to the logic that was
874 * implemented in qemu 2.3. This is the default value that is used if the phase
875 * subsection is not present on migration.
877 * Don't change this function to reflect newer qemu versions, it is part of
878 * the migration ABI.
880 static int reconstruct_phase(FDCtrl *fdctrl)
882 if (fdctrl->msr & FD_MSR_NONDMA) {
883 return FD_PHASE_EXECUTION;
884 } else if ((fdctrl->msr & FD_MSR_RQM) == 0) {
885 /* qemu 2.3 disabled RQM only during DMA transfers */
886 return FD_PHASE_EXECUTION;
887 } else if (fdctrl->msr & FD_MSR_DIO) {
888 return FD_PHASE_RESULT;
889 } else {
890 return FD_PHASE_COMMAND;
894 static void fdc_pre_save(void *opaque)
896 FDCtrl *s = opaque;
898 s->dor_vmstate = s->dor | GET_CUR_DRV(s);
901 static int fdc_pre_load(void *opaque)
903 FDCtrl *s = opaque;
904 s->phase = FD_PHASE_RECONSTRUCT;
905 return 0;
908 static int fdc_post_load(void *opaque, int version_id)
910 FDCtrl *s = opaque;
912 SET_CUR_DRV(s, s->dor_vmstate & FD_DOR_SELMASK);
913 s->dor = s->dor_vmstate & ~FD_DOR_SELMASK;
915 if (s->phase == FD_PHASE_RECONSTRUCT) {
916 s->phase = reconstruct_phase(s);
919 return 0;
922 static bool fdc_reset_sensei_needed(void *opaque)
924 FDCtrl *s = opaque;
926 return s->reset_sensei != 0;
929 static const VMStateDescription vmstate_fdc_reset_sensei = {
930 .name = "fdc/reset_sensei",
931 .version_id = 1,
932 .minimum_version_id = 1,
933 .needed = fdc_reset_sensei_needed,
934 .fields = (VMStateField[]) {
935 VMSTATE_INT32(reset_sensei, FDCtrl),
936 VMSTATE_END_OF_LIST()
940 static bool fdc_result_timer_needed(void *opaque)
942 FDCtrl *s = opaque;
944 return timer_pending(s->result_timer);
947 static const VMStateDescription vmstate_fdc_result_timer = {
948 .name = "fdc/result_timer",
949 .version_id = 1,
950 .minimum_version_id = 1,
951 .needed = fdc_result_timer_needed,
952 .fields = (VMStateField[]) {
953 VMSTATE_TIMER_PTR(result_timer, FDCtrl),
954 VMSTATE_END_OF_LIST()
958 static bool fdc_phase_needed(void *opaque)
960 FDCtrl *fdctrl = opaque;
962 return reconstruct_phase(fdctrl) != fdctrl->phase;
965 static const VMStateDescription vmstate_fdc_phase = {
966 .name = "fdc/phase",
967 .version_id = 1,
968 .minimum_version_id = 1,
969 .needed = fdc_phase_needed,
970 .fields = (VMStateField[]) {
971 VMSTATE_UINT8(phase, FDCtrl),
972 VMSTATE_END_OF_LIST()
976 static const VMStateDescription vmstate_fdc = {
977 .name = "fdc",
978 .version_id = 2,
979 .minimum_version_id = 2,
980 .pre_save = fdc_pre_save,
981 .pre_load = fdc_pre_load,
982 .post_load = fdc_post_load,
983 .fields = (VMStateField[]) {
984 /* Controller State */
985 VMSTATE_UINT8(sra, FDCtrl),
986 VMSTATE_UINT8(srb, FDCtrl),
987 VMSTATE_UINT8(dor_vmstate, FDCtrl),
988 VMSTATE_UINT8(tdr, FDCtrl),
989 VMSTATE_UINT8(dsr, FDCtrl),
990 VMSTATE_UINT8(msr, FDCtrl),
991 VMSTATE_UINT8(status0, FDCtrl),
992 VMSTATE_UINT8(status1, FDCtrl),
993 VMSTATE_UINT8(status2, FDCtrl),
994 /* Command FIFO */
995 VMSTATE_VARRAY_INT32(fifo, FDCtrl, fifo_size, 0, vmstate_info_uint8,
996 uint8_t),
997 VMSTATE_UINT32(data_pos, FDCtrl),
998 VMSTATE_UINT32(data_len, FDCtrl),
999 VMSTATE_UINT8(data_state, FDCtrl),
1000 VMSTATE_UINT8(data_dir, FDCtrl),
1001 VMSTATE_UINT8(eot, FDCtrl),
1002 /* States kept only to be returned back */
1003 VMSTATE_UINT8(timer0, FDCtrl),
1004 VMSTATE_UINT8(timer1, FDCtrl),
1005 VMSTATE_UINT8(precomp_trk, FDCtrl),
1006 VMSTATE_UINT8(config, FDCtrl),
1007 VMSTATE_UINT8(lock, FDCtrl),
1008 VMSTATE_UINT8(pwrd, FDCtrl),
1009 VMSTATE_UINT8_EQUAL(num_floppies, FDCtrl),
1010 VMSTATE_STRUCT_ARRAY(drives, FDCtrl, MAX_FD, 1,
1011 vmstate_fdrive, FDrive),
1012 VMSTATE_END_OF_LIST()
1014 .subsections = (const VMStateDescription*[]) {
1015 &vmstate_fdc_reset_sensei,
1016 &vmstate_fdc_result_timer,
1017 &vmstate_fdc_phase,
1018 NULL
1022 static void fdctrl_external_reset_sysbus(DeviceState *d)
1024 FDCtrlSysBus *sys = SYSBUS_FDC(d);
1025 FDCtrl *s = &sys->state;
1027 fdctrl_reset(s, 0);
1030 static void fdctrl_external_reset_isa(DeviceState *d)
1032 FDCtrlISABus *isa = ISA_FDC(d);
1033 FDCtrl *s = &isa->state;
1035 fdctrl_reset(s, 0);
1038 static void fdctrl_handle_tc(void *opaque, int irq, int level)
1040 //FDCtrl *s = opaque;
1042 if (level) {
1043 // XXX
1044 FLOPPY_DPRINTF("TC pulsed\n");
1048 /* Change IRQ state */
1049 static void fdctrl_reset_irq(FDCtrl *fdctrl)
1051 fdctrl->status0 = 0;
1052 if (!(fdctrl->sra & FD_SRA_INTPEND))
1053 return;
1054 FLOPPY_DPRINTF("Reset interrupt\n");
1055 qemu_set_irq(fdctrl->irq, 0);
1056 fdctrl->sra &= ~FD_SRA_INTPEND;
1059 static void fdctrl_raise_irq(FDCtrl *fdctrl)
1061 if (!(fdctrl->sra & FD_SRA_INTPEND)) {
1062 qemu_set_irq(fdctrl->irq, 1);
1063 fdctrl->sra |= FD_SRA_INTPEND;
1066 fdctrl->reset_sensei = 0;
1067 FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0);
1070 /* Reset controller */
1071 static void fdctrl_reset(FDCtrl *fdctrl, int do_irq)
1073 int i;
1075 FLOPPY_DPRINTF("reset controller\n");
1076 fdctrl_reset_irq(fdctrl);
1077 /* Initialise controller */
1078 fdctrl->sra = 0;
1079 fdctrl->srb = 0xc0;
1080 if (!fdctrl->drives[1].blk) {
1081 fdctrl->sra |= FD_SRA_nDRV2;
1083 fdctrl->cur_drv = 0;
1084 fdctrl->dor = FD_DOR_nRESET;
1085 fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0;
1086 fdctrl->msr = FD_MSR_RQM;
1087 fdctrl->reset_sensei = 0;
1088 timer_del(fdctrl->result_timer);
1089 /* FIFO state */
1090 fdctrl->data_pos = 0;
1091 fdctrl->data_len = 0;
1092 fdctrl->data_state = 0;
1093 fdctrl->data_dir = FD_DIR_WRITE;
1094 for (i = 0; i < MAX_FD; i++)
1095 fd_recalibrate(&fdctrl->drives[i]);
1096 fdctrl_to_command_phase(fdctrl);
1097 if (do_irq) {
1098 fdctrl->status0 |= FD_SR0_RDYCHG;
1099 fdctrl_raise_irq(fdctrl);
1100 fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT;
1104 static inline FDrive *drv0(FDCtrl *fdctrl)
1106 return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL) >> 2];
1109 static inline FDrive *drv1(FDCtrl *fdctrl)
1111 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (1 << 2))
1112 return &fdctrl->drives[1];
1113 else
1114 return &fdctrl->drives[0];
1117 #if MAX_FD == 4
1118 static inline FDrive *drv2(FDCtrl *fdctrl)
1120 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2))
1121 return &fdctrl->drives[2];
1122 else
1123 return &fdctrl->drives[1];
1126 static inline FDrive *drv3(FDCtrl *fdctrl)
1128 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2))
1129 return &fdctrl->drives[3];
1130 else
1131 return &fdctrl->drives[2];
1133 #endif
1135 static FDrive *get_cur_drv(FDCtrl *fdctrl)
1137 switch (fdctrl->cur_drv) {
1138 case 0: return drv0(fdctrl);
1139 case 1: return drv1(fdctrl);
1140 #if MAX_FD == 4
1141 case 2: return drv2(fdctrl);
1142 case 3: return drv3(fdctrl);
1143 #endif
1144 default: return NULL;
1148 /* Status A register : 0x00 (read-only) */
1149 static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl)
1151 uint32_t retval = fdctrl->sra;
1153 FLOPPY_DPRINTF("status register A: 0x%02x\n", retval);
1155 return retval;
1158 /* Status B register : 0x01 (read-only) */
1159 static uint32_t fdctrl_read_statusB(FDCtrl *fdctrl)
1161 uint32_t retval = fdctrl->srb;
1163 FLOPPY_DPRINTF("status register B: 0x%02x\n", retval);
1165 return retval;
1168 /* Digital output register : 0x02 */
1169 static uint32_t fdctrl_read_dor(FDCtrl *fdctrl)
1171 uint32_t retval = fdctrl->dor;
1173 /* Selected drive */
1174 retval |= fdctrl->cur_drv;
1175 FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval);
1177 return retval;
1180 static void fdctrl_write_dor(FDCtrl *fdctrl, uint32_t value)
1182 FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
1184 /* Motors */
1185 if (value & FD_DOR_MOTEN0)
1186 fdctrl->srb |= FD_SRB_MTR0;
1187 else
1188 fdctrl->srb &= ~FD_SRB_MTR0;
1189 if (value & FD_DOR_MOTEN1)
1190 fdctrl->srb |= FD_SRB_MTR1;
1191 else
1192 fdctrl->srb &= ~FD_SRB_MTR1;
1194 /* Drive */
1195 if (value & 1)
1196 fdctrl->srb |= FD_SRB_DR0;
1197 else
1198 fdctrl->srb &= ~FD_SRB_DR0;
1200 /* Reset */
1201 if (!(value & FD_DOR_nRESET)) {
1202 if (fdctrl->dor & FD_DOR_nRESET) {
1203 FLOPPY_DPRINTF("controller enter RESET state\n");
1205 } else {
1206 if (!(fdctrl->dor & FD_DOR_nRESET)) {
1207 FLOPPY_DPRINTF("controller out of RESET state\n");
1208 fdctrl_reset(fdctrl, 1);
1209 fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1212 /* Selected drive */
1213 fdctrl->cur_drv = value & FD_DOR_SELMASK;
1215 fdctrl->dor = value;
1218 /* Tape drive register : 0x03 */
1219 static uint32_t fdctrl_read_tape(FDCtrl *fdctrl)
1221 uint32_t retval = fdctrl->tdr;
1223 FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval);
1225 return retval;
1228 static void fdctrl_write_tape(FDCtrl *fdctrl, uint32_t value)
1230 /* Reset mode */
1231 if (!(fdctrl->dor & FD_DOR_nRESET)) {
1232 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
1233 return;
1235 FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);
1236 /* Disk boot selection indicator */
1237 fdctrl->tdr = value & FD_TDR_BOOTSEL;
1238 /* Tape indicators: never allow */
1241 /* Main status register : 0x04 (read) */
1242 static uint32_t fdctrl_read_main_status(FDCtrl *fdctrl)
1244 uint32_t retval = fdctrl->msr;
1246 fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1247 fdctrl->dor |= FD_DOR_nRESET;
1249 FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);
1251 return retval;
1254 /* Data select rate register : 0x04 (write) */
1255 static void fdctrl_write_rate(FDCtrl *fdctrl, uint32_t value)
1257 /* Reset mode */
1258 if (!(fdctrl->dor & FD_DOR_nRESET)) {
1259 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
1260 return;
1262 FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
1263 /* Reset: autoclear */
1264 if (value & FD_DSR_SWRESET) {
1265 fdctrl->dor &= ~FD_DOR_nRESET;
1266 fdctrl_reset(fdctrl, 1);
1267 fdctrl->dor |= FD_DOR_nRESET;
1269 if (value & FD_DSR_PWRDOWN) {
1270 fdctrl_reset(fdctrl, 1);
1272 fdctrl->dsr = value;
1275 /* Configuration control register: 0x07 (write) */
1276 static void fdctrl_write_ccr(FDCtrl *fdctrl, uint32_t value)
1278 /* Reset mode */
1279 if (!(fdctrl->dor & FD_DOR_nRESET)) {
1280 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
1281 return;
1283 FLOPPY_DPRINTF("configuration control register set to 0x%02x\n", value);
1285 /* Only the rate selection bits used in AT mode, and we
1286 * store those in the DSR.
1288 fdctrl->dsr = (fdctrl->dsr & ~FD_DSR_DRATEMASK) |
1289 (value & FD_DSR_DRATEMASK);
1292 static int fdctrl_media_changed(FDrive *drv)
1294 return drv->media_changed;
1297 /* Digital input register : 0x07 (read-only) */
1298 static uint32_t fdctrl_read_dir(FDCtrl *fdctrl)
1300 uint32_t retval = 0;
1302 if (fdctrl_media_changed(get_cur_drv(fdctrl))) {
1303 retval |= FD_DIR_DSKCHG;
1305 if (retval != 0) {
1306 FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
1309 return retval;
1312 /* Clear the FIFO and update the state for receiving the next command */
1313 static void fdctrl_to_command_phase(FDCtrl *fdctrl)
1315 fdctrl->phase = FD_PHASE_COMMAND;
1316 fdctrl->data_dir = FD_DIR_WRITE;
1317 fdctrl->data_pos = 0;
1318 fdctrl->data_len = 1; /* Accept command byte, adjust for params later */
1319 fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO);
1320 fdctrl->msr |= FD_MSR_RQM;
1323 /* Update the state to allow the guest to read out the command status.
1324 * @fifo_len is the number of result bytes to be read out. */
1325 static void fdctrl_to_result_phase(FDCtrl *fdctrl, int fifo_len)
1327 fdctrl->phase = FD_PHASE_RESULT;
1328 fdctrl->data_dir = FD_DIR_READ;
1329 fdctrl->data_len = fifo_len;
1330 fdctrl->data_pos = 0;
1331 fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO;
1334 /* Set an error: unimplemented/unknown command */
1335 static void fdctrl_unimplemented(FDCtrl *fdctrl, int direction)
1337 qemu_log_mask(LOG_UNIMP, "fdc: unimplemented command 0x%02x\n",
1338 fdctrl->fifo[0]);
1339 fdctrl->fifo[0] = FD_SR0_INVCMD;
1340 fdctrl_to_result_phase(fdctrl, 1);
1343 /* Seek to next sector
1344 * returns 0 when end of track reached (for DBL_SIDES on head 1)
1345 * otherwise returns 1
1347 static int fdctrl_seek_to_next_sect(FDCtrl *fdctrl, FDrive *cur_drv)
1349 FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d)\n",
1350 cur_drv->head, cur_drv->track, cur_drv->sect,
1351 fd_sector(cur_drv));
1352 /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
1353 error in fact */
1354 uint8_t new_head = cur_drv->head;
1355 uint8_t new_track = cur_drv->track;
1356 uint8_t new_sect = cur_drv->sect;
1358 int ret = 1;
1360 if (new_sect >= cur_drv->last_sect ||
1361 new_sect == fdctrl->eot) {
1362 new_sect = 1;
1363 if (FD_MULTI_TRACK(fdctrl->data_state)) {
1364 if (new_head == 0 &&
1365 (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
1366 new_head = 1;
1367 } else {
1368 new_head = 0;
1369 new_track++;
1370 fdctrl->status0 |= FD_SR0_SEEK;
1371 if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) {
1372 ret = 0;
1375 } else {
1376 fdctrl->status0 |= FD_SR0_SEEK;
1377 new_track++;
1378 ret = 0;
1380 if (ret == 1) {
1381 FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
1382 new_head, new_track, new_sect, fd_sector(cur_drv));
1384 } else {
1385 new_sect++;
1387 fd_seek(cur_drv, new_head, new_track, new_sect, 1);
1388 return ret;
1391 /* Callback for transfer end (stop or abort) */
1392 static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
1393 uint8_t status1, uint8_t status2)
1395 FDrive *cur_drv;
1396 cur_drv = get_cur_drv(fdctrl);
1398 fdctrl->status0 &= ~(FD_SR0_DS0 | FD_SR0_DS1 | FD_SR0_HEAD);
1399 fdctrl->status0 |= GET_CUR_DRV(fdctrl);
1400 if (cur_drv->head) {
1401 fdctrl->status0 |= FD_SR0_HEAD;
1403 fdctrl->status0 |= status0;
1405 FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
1406 status0, status1, status2, fdctrl->status0);
1407 fdctrl->fifo[0] = fdctrl->status0;
1408 fdctrl->fifo[1] = status1;
1409 fdctrl->fifo[2] = status2;
1410 fdctrl->fifo[3] = cur_drv->track;
1411 fdctrl->fifo[4] = cur_drv->head;
1412 fdctrl->fifo[5] = cur_drv->sect;
1413 fdctrl->fifo[6] = FD_SECTOR_SC;
1414 fdctrl->data_dir = FD_DIR_READ;
1415 if (!(fdctrl->msr & FD_MSR_NONDMA)) {
1416 DMA_release_DREQ(fdctrl->dma_chann);
1418 fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
1419 fdctrl->msr &= ~FD_MSR_NONDMA;
1421 fdctrl_to_result_phase(fdctrl, 7);
1422 fdctrl_raise_irq(fdctrl);
1425 /* Prepare a data transfer (either DMA or FIFO) */
1426 static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
1428 FDrive *cur_drv;
1429 uint8_t kh, kt, ks;
1431 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1432 cur_drv = get_cur_drv(fdctrl);
1433 kt = fdctrl->fifo[2];
1434 kh = fdctrl->fifo[3];
1435 ks = fdctrl->fifo[4];
1436 FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",
1437 GET_CUR_DRV(fdctrl), kh, kt, ks,
1438 fd_sector_calc(kh, kt, ks, cur_drv->last_sect,
1439 NUM_SIDES(cur_drv)));
1440 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
1441 case 2:
1442 /* sect too big */
1443 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1444 fdctrl->fifo[3] = kt;
1445 fdctrl->fifo[4] = kh;
1446 fdctrl->fifo[5] = ks;
1447 return;
1448 case 3:
1449 /* track too big */
1450 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
1451 fdctrl->fifo[3] = kt;
1452 fdctrl->fifo[4] = kh;
1453 fdctrl->fifo[5] = ks;
1454 return;
1455 case 4:
1456 /* No seek enabled */
1457 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1458 fdctrl->fifo[3] = kt;
1459 fdctrl->fifo[4] = kh;
1460 fdctrl->fifo[5] = ks;
1461 return;
1462 case 1:
1463 fdctrl->status0 |= FD_SR0_SEEK;
1464 break;
1465 default:
1466 break;
1469 /* Check the data rate. If the programmed data rate does not match
1470 * the currently inserted medium, the operation has to fail. */
1471 if (fdctrl->check_media_rate &&
1472 (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
1473 FLOPPY_DPRINTF("data rate mismatch (fdc=%d, media=%d)\n",
1474 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
1475 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00);
1476 fdctrl->fifo[3] = kt;
1477 fdctrl->fifo[4] = kh;
1478 fdctrl->fifo[5] = ks;
1479 return;
1482 /* Set the FIFO state */
1483 fdctrl->data_dir = direction;
1484 fdctrl->data_pos = 0;
1485 assert(fdctrl->msr & FD_MSR_CMDBUSY);
1486 if (fdctrl->fifo[0] & 0x80)
1487 fdctrl->data_state |= FD_STATE_MULTI;
1488 else
1489 fdctrl->data_state &= ~FD_STATE_MULTI;
1490 if (fdctrl->fifo[5] == 0) {
1491 fdctrl->data_len = fdctrl->fifo[8];
1492 } else {
1493 int tmp;
1494 fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
1495 tmp = (fdctrl->fifo[6] - ks + 1);
1496 if (fdctrl->fifo[0] & 0x80)
1497 tmp += fdctrl->fifo[6];
1498 fdctrl->data_len *= tmp;
1500 fdctrl->eot = fdctrl->fifo[6];
1501 if (fdctrl->dor & FD_DOR_DMAEN) {
1502 int dma_mode;
1503 /* DMA transfer are enabled. Check if DMA channel is well programmed */
1504 dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
1505 dma_mode = (dma_mode >> 2) & 3;
1506 FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
1507 dma_mode, direction,
1508 (128 << fdctrl->fifo[5]) *
1509 (cur_drv->last_sect - ks + 1), fdctrl->data_len);
1510 if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
1511 direction == FD_DIR_SCANH) && dma_mode == 0) ||
1512 (direction == FD_DIR_WRITE && dma_mode == 2) ||
1513 (direction == FD_DIR_READ && dma_mode == 1) ||
1514 (direction == FD_DIR_VERIFY)) {
1515 /* No access is allowed until DMA transfer has completed */
1516 fdctrl->msr &= ~FD_MSR_RQM;
1517 if (direction != FD_DIR_VERIFY) {
1518 /* Now, we just have to wait for the DMA controller to
1519 * recall us...
1521 DMA_hold_DREQ(fdctrl->dma_chann);
1522 DMA_schedule();
1523 } else {
1524 /* Start transfer */
1525 fdctrl_transfer_handler(fdctrl, fdctrl->dma_chann, 0,
1526 fdctrl->data_len);
1528 return;
1529 } else {
1530 FLOPPY_DPRINTF("bad dma_mode=%d direction=%d\n", dma_mode,
1531 direction);
1534 FLOPPY_DPRINTF("start non-DMA transfer\n");
1535 fdctrl->msr |= FD_MSR_NONDMA | FD_MSR_RQM;
1536 if (direction != FD_DIR_WRITE)
1537 fdctrl->msr |= FD_MSR_DIO;
1538 /* IO based transfer: calculate len */
1539 fdctrl_raise_irq(fdctrl);
1542 /* Prepare a transfer of deleted data */
1543 static void fdctrl_start_transfer_del(FDCtrl *fdctrl, int direction)
1545 qemu_log_mask(LOG_UNIMP, "fdctrl_start_transfer_del() unimplemented\n");
1547 /* We don't handle deleted data,
1548 * so we don't return *ANYTHING*
1550 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1553 /* handlers for DMA transfers */
1554 static int fdctrl_transfer_handler (void *opaque, int nchan,
1555 int dma_pos, int dma_len)
1557 FDCtrl *fdctrl;
1558 FDrive *cur_drv;
1559 int len, start_pos, rel_pos;
1560 uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
1562 fdctrl = opaque;
1563 if (fdctrl->msr & FD_MSR_RQM) {
1564 FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
1565 return 0;
1567 cur_drv = get_cur_drv(fdctrl);
1568 if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
1569 fdctrl->data_dir == FD_DIR_SCANH)
1570 status2 = FD_SR2_SNS;
1571 if (dma_len > fdctrl->data_len)
1572 dma_len = fdctrl->data_len;
1573 if (cur_drv->blk == NULL) {
1574 if (fdctrl->data_dir == FD_DIR_WRITE)
1575 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1576 else
1577 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1578 len = 0;
1579 goto transfer_error;
1581 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
1582 for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) {
1583 len = dma_len - fdctrl->data_pos;
1584 if (len + rel_pos > FD_SECTOR_LEN)
1585 len = FD_SECTOR_LEN - rel_pos;
1586 FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x "
1587 "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos,
1588 fdctrl->data_len, GET_CUR_DRV(fdctrl), cur_drv->head,
1589 cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
1590 fd_sector(cur_drv) * FD_SECTOR_LEN);
1591 if (fdctrl->data_dir != FD_DIR_WRITE ||
1592 len < FD_SECTOR_LEN || rel_pos != 0) {
1593 /* READ & SCAN commands and realign to a sector for WRITE */
1594 if (blk_read(cur_drv->blk, fd_sector(cur_drv),
1595 fdctrl->fifo, 1) < 0) {
1596 FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
1597 fd_sector(cur_drv));
1598 /* Sure, image size is too small... */
1599 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1602 switch (fdctrl->data_dir) {
1603 case FD_DIR_READ:
1604 /* READ commands */
1605 DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
1606 fdctrl->data_pos, len);
1607 break;
1608 case FD_DIR_WRITE:
1609 /* WRITE commands */
1610 if (cur_drv->ro) {
1611 /* Handle readonly medium early, no need to do DMA, touch the
1612 * LED or attempt any writes. A real floppy doesn't attempt
1613 * to write to readonly media either. */
1614 fdctrl_stop_transfer(fdctrl,
1615 FD_SR0_ABNTERM | FD_SR0_SEEK, FD_SR1_NW,
1616 0x00);
1617 goto transfer_error;
1620 DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
1621 fdctrl->data_pos, len);
1622 if (blk_write(cur_drv->blk, fd_sector(cur_drv),
1623 fdctrl->fifo, 1) < 0) {
1624 FLOPPY_DPRINTF("error writing sector %d\n",
1625 fd_sector(cur_drv));
1626 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1627 goto transfer_error;
1629 break;
1630 case FD_DIR_VERIFY:
1631 /* VERIFY commands */
1632 break;
1633 default:
1634 /* SCAN commands */
1636 uint8_t tmpbuf[FD_SECTOR_LEN];
1637 int ret;
1638 DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
1639 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
1640 if (ret == 0) {
1641 status2 = FD_SR2_SEH;
1642 goto end_transfer;
1644 if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) ||
1645 (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) {
1646 status2 = 0x00;
1647 goto end_transfer;
1650 break;
1652 fdctrl->data_pos += len;
1653 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
1654 if (rel_pos == 0) {
1655 /* Seek to next sector */
1656 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv))
1657 break;
1660 end_transfer:
1661 len = fdctrl->data_pos - start_pos;
1662 FLOPPY_DPRINTF("end transfer %d %d %d\n",
1663 fdctrl->data_pos, len, fdctrl->data_len);
1664 if (fdctrl->data_dir == FD_DIR_SCANE ||
1665 fdctrl->data_dir == FD_DIR_SCANL ||
1666 fdctrl->data_dir == FD_DIR_SCANH)
1667 status2 = FD_SR2_SEH;
1668 fdctrl->data_len -= len;
1669 fdctrl_stop_transfer(fdctrl, status0, status1, status2);
1670 transfer_error:
1672 return len;
1675 /* Data register : 0x05 */
1676 static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
1678 FDrive *cur_drv;
1679 uint32_t retval = 0;
1680 uint32_t pos;
1682 cur_drv = get_cur_drv(fdctrl);
1683 fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1684 if (!(fdctrl->msr & FD_MSR_RQM) || !(fdctrl->msr & FD_MSR_DIO)) {
1685 FLOPPY_DPRINTF("error: controller not ready for reading\n");
1686 return 0;
1689 /* If data_len spans multiple sectors, the current position in the FIFO
1690 * wraps around while fdctrl->data_pos is the real position in the whole
1691 * request. */
1692 pos = fdctrl->data_pos;
1693 pos %= FD_SECTOR_LEN;
1695 switch (fdctrl->phase) {
1696 case FD_PHASE_EXECUTION:
1697 assert(fdctrl->msr & FD_MSR_NONDMA);
1698 if (pos == 0) {
1699 if (fdctrl->data_pos != 0)
1700 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
1701 FLOPPY_DPRINTF("error seeking to next sector %d\n",
1702 fd_sector(cur_drv));
1703 return 0;
1705 if (blk_read(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1)
1706 < 0) {
1707 FLOPPY_DPRINTF("error getting sector %d\n",
1708 fd_sector(cur_drv));
1709 /* Sure, image size is too small... */
1710 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1714 if (++fdctrl->data_pos == fdctrl->data_len) {
1715 fdctrl->msr &= ~FD_MSR_RQM;
1716 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1718 break;
1720 case FD_PHASE_RESULT:
1721 assert(!(fdctrl->msr & FD_MSR_NONDMA));
1722 if (++fdctrl->data_pos == fdctrl->data_len) {
1723 fdctrl->msr &= ~FD_MSR_RQM;
1724 fdctrl_to_command_phase(fdctrl);
1725 fdctrl_reset_irq(fdctrl);
1727 break;
1729 case FD_PHASE_COMMAND:
1730 default:
1731 abort();
1734 retval = fdctrl->fifo[pos];
1735 FLOPPY_DPRINTF("data register: 0x%02x\n", retval);
1737 return retval;
1740 static void fdctrl_format_sector(FDCtrl *fdctrl)
1742 FDrive *cur_drv;
1743 uint8_t kh, kt, ks;
1745 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1746 cur_drv = get_cur_drv(fdctrl);
1747 kt = fdctrl->fifo[6];
1748 kh = fdctrl->fifo[7];
1749 ks = fdctrl->fifo[8];
1750 FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n",
1751 GET_CUR_DRV(fdctrl), kh, kt, ks,
1752 fd_sector_calc(kh, kt, ks, cur_drv->last_sect,
1753 NUM_SIDES(cur_drv)));
1754 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
1755 case 2:
1756 /* sect too big */
1757 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1758 fdctrl->fifo[3] = kt;
1759 fdctrl->fifo[4] = kh;
1760 fdctrl->fifo[5] = ks;
1761 return;
1762 case 3:
1763 /* track too big */
1764 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
1765 fdctrl->fifo[3] = kt;
1766 fdctrl->fifo[4] = kh;
1767 fdctrl->fifo[5] = ks;
1768 return;
1769 case 4:
1770 /* No seek enabled */
1771 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1772 fdctrl->fifo[3] = kt;
1773 fdctrl->fifo[4] = kh;
1774 fdctrl->fifo[5] = ks;
1775 return;
1776 case 1:
1777 fdctrl->status0 |= FD_SR0_SEEK;
1778 break;
1779 default:
1780 break;
1782 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1783 if (cur_drv->blk == NULL ||
1784 blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
1785 FLOPPY_DPRINTF("error formatting sector %d\n", fd_sector(cur_drv));
1786 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1787 } else {
1788 if (cur_drv->sect == cur_drv->last_sect) {
1789 fdctrl->data_state &= ~FD_STATE_FORMAT;
1790 /* Last sector done */
1791 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1792 } else {
1793 /* More to do */
1794 fdctrl->data_pos = 0;
1795 fdctrl->data_len = 4;
1800 static void fdctrl_handle_lock(FDCtrl *fdctrl, int direction)
1802 fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
1803 fdctrl->fifo[0] = fdctrl->lock << 4;
1804 fdctrl_to_result_phase(fdctrl, 1);
1807 static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
1809 FDrive *cur_drv = get_cur_drv(fdctrl);
1811 /* Drives position */
1812 fdctrl->fifo[0] = drv0(fdctrl)->track;
1813 fdctrl->fifo[1] = drv1(fdctrl)->track;
1814 #if MAX_FD == 4
1815 fdctrl->fifo[2] = drv2(fdctrl)->track;
1816 fdctrl->fifo[3] = drv3(fdctrl)->track;
1817 #else
1818 fdctrl->fifo[2] = 0;
1819 fdctrl->fifo[3] = 0;
1820 #endif
1821 /* timers */
1822 fdctrl->fifo[4] = fdctrl->timer0;
1823 fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0);
1824 fdctrl->fifo[6] = cur_drv->last_sect;
1825 fdctrl->fifo[7] = (fdctrl->lock << 7) |
1826 (cur_drv->perpendicular << 2);
1827 fdctrl->fifo[8] = fdctrl->config;
1828 fdctrl->fifo[9] = fdctrl->precomp_trk;
1829 fdctrl_to_result_phase(fdctrl, 10);
1832 static void fdctrl_handle_version(FDCtrl *fdctrl, int direction)
1834 /* Controller's version */
1835 fdctrl->fifo[0] = fdctrl->version;
1836 fdctrl_to_result_phase(fdctrl, 1);
1839 static void fdctrl_handle_partid(FDCtrl *fdctrl, int direction)
1841 fdctrl->fifo[0] = 0x41; /* Stepping 1 */
1842 fdctrl_to_result_phase(fdctrl, 1);
1845 static void fdctrl_handle_restore(FDCtrl *fdctrl, int direction)
1847 FDrive *cur_drv = get_cur_drv(fdctrl);
1849 /* Drives position */
1850 drv0(fdctrl)->track = fdctrl->fifo[3];
1851 drv1(fdctrl)->track = fdctrl->fifo[4];
1852 #if MAX_FD == 4
1853 drv2(fdctrl)->track = fdctrl->fifo[5];
1854 drv3(fdctrl)->track = fdctrl->fifo[6];
1855 #endif
1856 /* timers */
1857 fdctrl->timer0 = fdctrl->fifo[7];
1858 fdctrl->timer1 = fdctrl->fifo[8];
1859 cur_drv->last_sect = fdctrl->fifo[9];
1860 fdctrl->lock = fdctrl->fifo[10] >> 7;
1861 cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF;
1862 fdctrl->config = fdctrl->fifo[11];
1863 fdctrl->precomp_trk = fdctrl->fifo[12];
1864 fdctrl->pwrd = fdctrl->fifo[13];
1865 fdctrl_to_command_phase(fdctrl);
1868 static void fdctrl_handle_save(FDCtrl *fdctrl, int direction)
1870 FDrive *cur_drv = get_cur_drv(fdctrl);
1872 fdctrl->fifo[0] = 0;
1873 fdctrl->fifo[1] = 0;
1874 /* Drives position */
1875 fdctrl->fifo[2] = drv0(fdctrl)->track;
1876 fdctrl->fifo[3] = drv1(fdctrl)->track;
1877 #if MAX_FD == 4
1878 fdctrl->fifo[4] = drv2(fdctrl)->track;
1879 fdctrl->fifo[5] = drv3(fdctrl)->track;
1880 #else
1881 fdctrl->fifo[4] = 0;
1882 fdctrl->fifo[5] = 0;
1883 #endif
1884 /* timers */
1885 fdctrl->fifo[6] = fdctrl->timer0;
1886 fdctrl->fifo[7] = fdctrl->timer1;
1887 fdctrl->fifo[8] = cur_drv->last_sect;
1888 fdctrl->fifo[9] = (fdctrl->lock << 7) |
1889 (cur_drv->perpendicular << 2);
1890 fdctrl->fifo[10] = fdctrl->config;
1891 fdctrl->fifo[11] = fdctrl->precomp_trk;
1892 fdctrl->fifo[12] = fdctrl->pwrd;
1893 fdctrl->fifo[13] = 0;
1894 fdctrl->fifo[14] = 0;
1895 fdctrl_to_result_phase(fdctrl, 15);
1898 static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
1900 FDrive *cur_drv = get_cur_drv(fdctrl);
1902 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
1903 timer_mod(fdctrl->result_timer,
1904 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (get_ticks_per_sec() / 50));
1907 static void fdctrl_handle_format_track(FDCtrl *fdctrl, int direction)
1909 FDrive *cur_drv;
1911 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1912 cur_drv = get_cur_drv(fdctrl);
1913 fdctrl->data_state |= FD_STATE_FORMAT;
1914 if (fdctrl->fifo[0] & 0x80)
1915 fdctrl->data_state |= FD_STATE_MULTI;
1916 else
1917 fdctrl->data_state &= ~FD_STATE_MULTI;
1918 cur_drv->bps =
1919 fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
1920 #if 0
1921 cur_drv->last_sect =
1922 cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
1923 fdctrl->fifo[3] / 2;
1924 #else
1925 cur_drv->last_sect = fdctrl->fifo[3];
1926 #endif
1927 /* TODO: implement format using DMA expected by the Bochs BIOS
1928 * and Linux fdformat (read 3 bytes per sector via DMA and fill
1929 * the sector with the specified fill byte
1931 fdctrl->data_state &= ~FD_STATE_FORMAT;
1932 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1935 static void fdctrl_handle_specify(FDCtrl *fdctrl, int direction)
1937 fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
1938 fdctrl->timer1 = fdctrl->fifo[2] >> 1;
1939 if (fdctrl->fifo[2] & 1)
1940 fdctrl->dor &= ~FD_DOR_DMAEN;
1941 else
1942 fdctrl->dor |= FD_DOR_DMAEN;
1943 /* No result back */
1944 fdctrl_to_command_phase(fdctrl);
1947 static void fdctrl_handle_sense_drive_status(FDCtrl *fdctrl, int direction)
1949 FDrive *cur_drv;
1951 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1952 cur_drv = get_cur_drv(fdctrl);
1953 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
1954 /* 1 Byte status back */
1955 fdctrl->fifo[0] = (cur_drv->ro << 6) |
1956 (cur_drv->track == 0 ? 0x10 : 0x00) |
1957 (cur_drv->head << 2) |
1958 GET_CUR_DRV(fdctrl) |
1959 0x28;
1960 fdctrl_to_result_phase(fdctrl, 1);
1963 static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction)
1965 FDrive *cur_drv;
1967 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1968 cur_drv = get_cur_drv(fdctrl);
1969 fd_recalibrate(cur_drv);
1970 fdctrl_to_command_phase(fdctrl);
1971 /* Raise Interrupt */
1972 fdctrl->status0 |= FD_SR0_SEEK;
1973 fdctrl_raise_irq(fdctrl);
1976 static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
1978 FDrive *cur_drv = get_cur_drv(fdctrl);
1980 if (fdctrl->reset_sensei > 0) {
1981 fdctrl->fifo[0] =
1982 FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei;
1983 fdctrl->reset_sensei--;
1984 } else if (!(fdctrl->sra & FD_SRA_INTPEND)) {
1985 fdctrl->fifo[0] = FD_SR0_INVCMD;
1986 fdctrl_to_result_phase(fdctrl, 1);
1987 return;
1988 } else {
1989 fdctrl->fifo[0] =
1990 (fdctrl->status0 & ~(FD_SR0_HEAD | FD_SR0_DS1 | FD_SR0_DS0))
1991 | GET_CUR_DRV(fdctrl);
1994 fdctrl->fifo[1] = cur_drv->track;
1995 fdctrl_to_result_phase(fdctrl, 2);
1996 fdctrl_reset_irq(fdctrl);
1997 fdctrl->status0 = FD_SR0_RDYCHG;
2000 static void fdctrl_handle_seek(FDCtrl *fdctrl, int direction)
2002 FDrive *cur_drv;
2004 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
2005 cur_drv = get_cur_drv(fdctrl);
2006 fdctrl_to_command_phase(fdctrl);
2007 /* The seek command just sends step pulses to the drive and doesn't care if
2008 * there is a medium inserted of if it's banging the head against the drive.
2010 fd_seek(cur_drv, cur_drv->head, fdctrl->fifo[2], cur_drv->sect, 1);
2011 /* Raise Interrupt */
2012 fdctrl->status0 |= FD_SR0_SEEK;
2013 fdctrl_raise_irq(fdctrl);
2016 static void fdctrl_handle_perpendicular_mode(FDCtrl *fdctrl, int direction)
2018 FDrive *cur_drv = get_cur_drv(fdctrl);
2020 if (fdctrl->fifo[1] & 0x80)
2021 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
2022 /* No result back */
2023 fdctrl_to_command_phase(fdctrl);
2026 static void fdctrl_handle_configure(FDCtrl *fdctrl, int direction)
2028 fdctrl->config = fdctrl->fifo[2];
2029 fdctrl->precomp_trk = fdctrl->fifo[3];
2030 /* No result back */
2031 fdctrl_to_command_phase(fdctrl);
2034 static void fdctrl_handle_powerdown_mode(FDCtrl *fdctrl, int direction)
2036 fdctrl->pwrd = fdctrl->fifo[1];
2037 fdctrl->fifo[0] = fdctrl->fifo[1];
2038 fdctrl_to_result_phase(fdctrl, 1);
2041 static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
2043 /* No result back */
2044 fdctrl_to_command_phase(fdctrl);
2047 static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction)
2049 FDrive *cur_drv = get_cur_drv(fdctrl);
2050 uint32_t pos;
2052 pos = fdctrl->data_pos - 1;
2053 pos %= FD_SECTOR_LEN;
2054 if (fdctrl->fifo[pos] & 0x80) {
2055 /* Command parameters done */
2056 if (fdctrl->fifo[pos] & 0x40) {
2057 fdctrl->fifo[0] = fdctrl->fifo[1];
2058 fdctrl->fifo[2] = 0;
2059 fdctrl->fifo[3] = 0;
2060 fdctrl_to_result_phase(fdctrl, 4);
2061 } else {
2062 fdctrl_to_command_phase(fdctrl);
2064 } else if (fdctrl->data_len > 7) {
2065 /* ERROR */
2066 fdctrl->fifo[0] = 0x80 |
2067 (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
2068 fdctrl_to_result_phase(fdctrl, 1);
2072 static void fdctrl_handle_relative_seek_in(FDCtrl *fdctrl, int direction)
2074 FDrive *cur_drv;
2076 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
2077 cur_drv = get_cur_drv(fdctrl);
2078 if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
2079 fd_seek(cur_drv, cur_drv->head, cur_drv->max_track - 1,
2080 cur_drv->sect, 1);
2081 } else {
2082 fd_seek(cur_drv, cur_drv->head,
2083 cur_drv->track + fdctrl->fifo[2], cur_drv->sect, 1);
2085 fdctrl_to_command_phase(fdctrl);
2086 /* Raise Interrupt */
2087 fdctrl->status0 |= FD_SR0_SEEK;
2088 fdctrl_raise_irq(fdctrl);
2091 static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
2093 FDrive *cur_drv;
2095 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
2096 cur_drv = get_cur_drv(fdctrl);
2097 if (fdctrl->fifo[2] > cur_drv->track) {
2098 fd_seek(cur_drv, cur_drv->head, 0, cur_drv->sect, 1);
2099 } else {
2100 fd_seek(cur_drv, cur_drv->head,
2101 cur_drv->track - fdctrl->fifo[2], cur_drv->sect, 1);
2103 fdctrl_to_command_phase(fdctrl);
2104 /* Raise Interrupt */
2105 fdctrl->status0 |= FD_SR0_SEEK;
2106 fdctrl_raise_irq(fdctrl);
2110 * Handlers for the execution phase of each command
2112 typedef struct FDCtrlCommand {
2113 uint8_t value;
2114 uint8_t mask;
2115 const char* name;
2116 int parameters;
2117 void (*handler)(FDCtrl *fdctrl, int direction);
2118 int direction;
2119 } FDCtrlCommand;
2121 static const FDCtrlCommand handlers[] = {
2122 { FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ },
2123 { FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE },
2124 { FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek },
2125 { FD_CMD_SENSE_INTERRUPT_STATUS, 0xff, "SENSE INTERRUPT STATUS", 0, fdctrl_handle_sense_interrupt_status },
2126 { FD_CMD_RECALIBRATE, 0xff, "RECALIBRATE", 1, fdctrl_handle_recalibrate },
2127 { FD_CMD_FORMAT_TRACK, 0xbf, "FORMAT TRACK", 5, fdctrl_handle_format_track },
2128 { FD_CMD_READ_TRACK, 0xbf, "READ TRACK", 8, fdctrl_start_transfer, FD_DIR_READ },
2129 { FD_CMD_RESTORE, 0xff, "RESTORE", 17, fdctrl_handle_restore }, /* part of READ DELETED DATA */
2130 { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */
2131 { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ },
2132 { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE },
2133 { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_start_transfer, FD_DIR_VERIFY },
2134 { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL },
2135 { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH },
2136 { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE },
2137 { FD_CMD_READ_ID, 0xbf, "READ ID", 1, fdctrl_handle_readid },
2138 { FD_CMD_SPECIFY, 0xff, "SPECIFY", 2, fdctrl_handle_specify },
2139 { FD_CMD_SENSE_DRIVE_STATUS, 0xff, "SENSE DRIVE STATUS", 1, fdctrl_handle_sense_drive_status },
2140 { FD_CMD_PERPENDICULAR_MODE, 0xff, "PERPENDICULAR MODE", 1, fdctrl_handle_perpendicular_mode },
2141 { FD_CMD_CONFIGURE, 0xff, "CONFIGURE", 3, fdctrl_handle_configure },
2142 { FD_CMD_POWERDOWN_MODE, 0xff, "POWERDOWN MODE", 2, fdctrl_handle_powerdown_mode },
2143 { FD_CMD_OPTION, 0xff, "OPTION", 1, fdctrl_handle_option },
2144 { FD_CMD_DRIVE_SPECIFICATION_COMMAND, 0xff, "DRIVE SPECIFICATION COMMAND", 5, fdctrl_handle_drive_specification_command },
2145 { FD_CMD_RELATIVE_SEEK_OUT, 0xff, "RELATIVE SEEK OUT", 2, fdctrl_handle_relative_seek_out },
2146 { FD_CMD_FORMAT_AND_WRITE, 0xff, "FORMAT AND WRITE", 10, fdctrl_unimplemented },
2147 { FD_CMD_RELATIVE_SEEK_IN, 0xff, "RELATIVE SEEK IN", 2, fdctrl_handle_relative_seek_in },
2148 { FD_CMD_LOCK, 0x7f, "LOCK", 0, fdctrl_handle_lock },
2149 { FD_CMD_DUMPREG, 0xff, "DUMPREG", 0, fdctrl_handle_dumpreg },
2150 { FD_CMD_VERSION, 0xff, "VERSION", 0, fdctrl_handle_version },
2151 { FD_CMD_PART_ID, 0xff, "PART ID", 0, fdctrl_handle_partid },
2152 { FD_CMD_WRITE, 0x1f, "WRITE (BeOS)", 8, fdctrl_start_transfer, FD_DIR_WRITE }, /* not in specification ; BeOS 4.5 bug */
2153 { 0, 0, "unknown", 0, fdctrl_unimplemented }, /* default handler */
2155 /* Associate command to an index in the 'handlers' array */
2156 static uint8_t command_to_handler[256];
2158 static const FDCtrlCommand *get_command(uint8_t cmd)
2160 int idx;
2162 idx = command_to_handler[cmd];
2163 FLOPPY_DPRINTF("%s command\n", handlers[idx].name);
2164 return &handlers[idx];
2167 static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
2169 FDrive *cur_drv;
2170 const FDCtrlCommand *cmd;
2171 uint32_t pos;
2173 /* Reset mode */
2174 if (!(fdctrl->dor & FD_DOR_nRESET)) {
2175 FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
2176 return;
2178 if (!(fdctrl->msr & FD_MSR_RQM) || (fdctrl->msr & FD_MSR_DIO)) {
2179 FLOPPY_DPRINTF("error: controller not ready for writing\n");
2180 return;
2182 fdctrl->dsr &= ~FD_DSR_PWRDOWN;
2184 FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
2186 /* If data_len spans multiple sectors, the current position in the FIFO
2187 * wraps around while fdctrl->data_pos is the real position in the whole
2188 * request. */
2189 pos = fdctrl->data_pos++;
2190 pos %= FD_SECTOR_LEN;
2191 fdctrl->fifo[pos] = value;
2193 if (fdctrl->data_pos == fdctrl->data_len) {
2194 fdctrl->msr &= ~FD_MSR_RQM;
2197 switch (fdctrl->phase) {
2198 case FD_PHASE_EXECUTION:
2199 /* For DMA requests, RQM should be cleared during execution phase, so
2200 * we would have errored out above. */
2201 assert(fdctrl->msr & FD_MSR_NONDMA);
2203 /* FIFO data write */
2204 if (pos == FD_SECTOR_LEN - 1 ||
2205 fdctrl->data_pos == fdctrl->data_len) {
2206 cur_drv = get_cur_drv(fdctrl);
2207 if (blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1)
2208 < 0) {
2209 FLOPPY_DPRINTF("error writing sector %d\n",
2210 fd_sector(cur_drv));
2211 break;
2213 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
2214 FLOPPY_DPRINTF("error seeking to next sector %d\n",
2215 fd_sector(cur_drv));
2216 break;
2220 /* Switch to result phase when done with the transfer */
2221 if (fdctrl->data_pos == fdctrl->data_len) {
2222 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
2224 break;
2226 case FD_PHASE_COMMAND:
2227 assert(!(fdctrl->msr & FD_MSR_NONDMA));
2228 assert(fdctrl->data_pos < FD_SECTOR_LEN);
2230 if (pos == 0) {
2231 /* The first byte specifies the command. Now we start reading
2232 * as many parameters as this command requires. */
2233 cmd = get_command(value);
2234 fdctrl->data_len = cmd->parameters + 1;
2235 if (cmd->parameters) {
2236 fdctrl->msr |= FD_MSR_RQM;
2238 fdctrl->msr |= FD_MSR_CMDBUSY;
2241 if (fdctrl->data_pos == fdctrl->data_len) {
2242 /* We have all parameters now, execute the command */
2243 fdctrl->phase = FD_PHASE_EXECUTION;
2245 if (fdctrl->data_state & FD_STATE_FORMAT) {
2246 fdctrl_format_sector(fdctrl);
2247 break;
2250 cmd = get_command(fdctrl->fifo[0]);
2251 FLOPPY_DPRINTF("Calling handler for '%s'\n", cmd->name);
2252 cmd->handler(fdctrl, cmd->direction);
2254 break;
2256 case FD_PHASE_RESULT:
2257 default:
2258 abort();
2262 static void fdctrl_result_timer(void *opaque)
2264 FDCtrl *fdctrl = opaque;
2265 FDrive *cur_drv = get_cur_drv(fdctrl);
2267 /* Pretend we are spinning.
2268 * This is needed for Coherent, which uses READ ID to check for
2269 * sector interleaving.
2271 if (cur_drv->last_sect != 0) {
2272 cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1;
2274 /* READ_ID can't automatically succeed! */
2275 if (fdctrl->check_media_rate &&
2276 (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
2277 FLOPPY_DPRINTF("read id rate mismatch (fdc=%d, media=%d)\n",
2278 fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
2279 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00);
2280 } else {
2281 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
2285 static void fdctrl_change_cb(void *opaque, bool load)
2287 FDrive *drive = opaque;
2289 drive->media_changed = 1;
2290 drive->media_validated = false;
2291 fd_revalidate(drive);
2294 static const BlockDevOps fdctrl_block_ops = {
2295 .change_media_cb = fdctrl_change_cb,
2298 /* Init functions */
2299 static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp)
2301 unsigned int i;
2302 FDrive *drive;
2304 for (i = 0; i < MAX_FD; i++) {
2305 drive = &fdctrl->drives[i];
2306 drive->fdctrl = fdctrl;
2308 if (drive->blk) {
2309 if (blk_get_on_error(drive->blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
2310 error_setg(errp, "fdc doesn't support drive option werror");
2311 return;
2313 if (blk_get_on_error(drive->blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
2314 error_setg(errp, "fdc doesn't support drive option rerror");
2315 return;
2319 fd_init(drive);
2320 if (drive->blk) {
2321 blk_set_dev_ops(drive->blk, &fdctrl_block_ops, drive);
2322 pick_drive_type(drive);
2324 fd_revalidate(drive);
2328 ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds)
2330 DeviceState *dev;
2331 ISADevice *isadev;
2333 isadev = isa_try_create(bus, TYPE_ISA_FDC);
2334 if (!isadev) {
2335 return NULL;
2337 dev = DEVICE(isadev);
2339 if (fds[0]) {
2340 qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fds[0]),
2341 &error_fatal);
2343 if (fds[1]) {
2344 qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fds[1]),
2345 &error_fatal);
2347 qdev_init_nofail(dev);
2349 return isadev;
2352 void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
2353 hwaddr mmio_base, DriveInfo **fds)
2355 FDCtrl *fdctrl;
2356 DeviceState *dev;
2357 SysBusDevice *sbd;
2358 FDCtrlSysBus *sys;
2360 dev = qdev_create(NULL, "sysbus-fdc");
2361 sys = SYSBUS_FDC(dev);
2362 fdctrl = &sys->state;
2363 fdctrl->dma_chann = dma_chann; /* FIXME */
2364 if (fds[0]) {
2365 qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fds[0]),
2366 &error_fatal);
2368 if (fds[1]) {
2369 qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fds[1]),
2370 &error_fatal);
2372 qdev_init_nofail(dev);
2373 sbd = SYS_BUS_DEVICE(dev);
2374 sysbus_connect_irq(sbd, 0, irq);
2375 sysbus_mmio_map(sbd, 0, mmio_base);
2378 void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
2379 DriveInfo **fds, qemu_irq *fdc_tc)
2381 DeviceState *dev;
2382 FDCtrlSysBus *sys;
2384 dev = qdev_create(NULL, "SUNW,fdtwo");
2385 if (fds[0]) {
2386 qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(fds[0]),
2387 &error_fatal);
2389 qdev_init_nofail(dev);
2390 sys = SYSBUS_FDC(dev);
2391 sysbus_connect_irq(SYS_BUS_DEVICE(sys), 0, irq);
2392 sysbus_mmio_map(SYS_BUS_DEVICE(sys), 0, io_base);
2393 *fdc_tc = qdev_get_gpio_in(dev, 0);
2396 static void fdctrl_realize_common(FDCtrl *fdctrl, Error **errp)
2398 int i, j;
2399 static int command_tables_inited = 0;
2401 if (fdctrl->fallback == FLOPPY_DRIVE_TYPE_AUTO) {
2402 error_setg(errp, "Cannot choose a fallback FDrive type of 'auto'");
2405 /* Fill 'command_to_handler' lookup table */
2406 if (!command_tables_inited) {
2407 command_tables_inited = 1;
2408 for (i = ARRAY_SIZE(handlers) - 1; i >= 0; i--) {
2409 for (j = 0; j < sizeof(command_to_handler); j++) {
2410 if ((j & handlers[i].mask) == handlers[i].value) {
2411 command_to_handler[j] = i;
2417 FLOPPY_DPRINTF("init controller\n");
2418 fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN);
2419 fdctrl->fifo_size = 512;
2420 fdctrl->result_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
2421 fdctrl_result_timer, fdctrl);
2423 fdctrl->version = 0x90; /* Intel 82078 controller */
2424 fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */
2425 fdctrl->num_floppies = MAX_FD;
2427 if (fdctrl->dma_chann != -1) {
2428 DMA_register_channel(fdctrl->dma_chann, &fdctrl_transfer_handler, fdctrl);
2430 fdctrl_connect_drives(fdctrl, errp);
2433 static const MemoryRegionPortio fdc_portio_list[] = {
2434 { 1, 5, 1, .read = fdctrl_read, .write = fdctrl_write },
2435 { 7, 1, 1, .read = fdctrl_read, .write = fdctrl_write },
2436 PORTIO_END_OF_LIST(),
2439 static void isabus_fdc_realize(DeviceState *dev, Error **errp)
2441 ISADevice *isadev = ISA_DEVICE(dev);
2442 FDCtrlISABus *isa = ISA_FDC(dev);
2443 FDCtrl *fdctrl = &isa->state;
2444 Error *err = NULL;
2446 isa_register_portio_list(isadev, isa->iobase, fdc_portio_list, fdctrl,
2447 "fdc");
2449 isa_init_irq(isadev, &fdctrl->irq, isa->irq);
2450 fdctrl->dma_chann = isa->dma;
2452 qdev_set_legacy_instance_id(dev, isa->iobase, 2);
2453 fdctrl_realize_common(fdctrl, &err);
2454 if (err != NULL) {
2455 error_propagate(errp, err);
2456 return;
2460 static void sysbus_fdc_initfn(Object *obj)
2462 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
2463 FDCtrlSysBus *sys = SYSBUS_FDC(obj);
2464 FDCtrl *fdctrl = &sys->state;
2466 fdctrl->dma_chann = -1;
2468 memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_ops, fdctrl,
2469 "fdc", 0x08);
2470 sysbus_init_mmio(sbd, &fdctrl->iomem);
2473 static void sun4m_fdc_initfn(Object *obj)
2475 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
2476 FDCtrlSysBus *sys = SYSBUS_FDC(obj);
2477 FDCtrl *fdctrl = &sys->state;
2479 memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_strict_ops,
2480 fdctrl, "fdctrl", 0x08);
2481 sysbus_init_mmio(sbd, &fdctrl->iomem);
2484 static void sysbus_fdc_common_initfn(Object *obj)
2486 DeviceState *dev = DEVICE(obj);
2487 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
2488 FDCtrlSysBus *sys = SYSBUS_FDC(obj);
2489 FDCtrl *fdctrl = &sys->state;
2491 qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */
2493 sysbus_init_irq(sbd, &fdctrl->irq);
2494 qdev_init_gpio_in(dev, fdctrl_handle_tc, 1);
2497 static void sysbus_fdc_common_realize(DeviceState *dev, Error **errp)
2499 FDCtrlSysBus *sys = SYSBUS_FDC(dev);
2500 FDCtrl *fdctrl = &sys->state;
2502 fdctrl_realize_common(fdctrl, errp);
2505 FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
2507 FDCtrlISABus *isa = ISA_FDC(fdc);
2509 return isa->state.drives[i].drive;
2512 static const VMStateDescription vmstate_isa_fdc ={
2513 .name = "fdc",
2514 .version_id = 2,
2515 .minimum_version_id = 2,
2516 .fields = (VMStateField[]) {
2517 VMSTATE_STRUCT(state, FDCtrlISABus, 0, vmstate_fdc, FDCtrl),
2518 VMSTATE_END_OF_LIST()
2522 static Property isa_fdc_properties[] = {
2523 DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0),
2524 DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6),
2525 DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2),
2526 DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].blk),
2527 DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].blk),
2528 DEFINE_PROP_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate,
2529 0, true),
2530 DEFINE_PROP_DEFAULT("fdtypeA", FDCtrlISABus, state.drives[0].drive,
2531 FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
2532 FloppyDriveType),
2533 DEFINE_PROP_DEFAULT("fdtypeB", FDCtrlISABus, state.drives[1].drive,
2534 FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
2535 FloppyDriveType),
2536 DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
2537 FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
2538 FloppyDriveType),
2539 DEFINE_PROP_END_OF_LIST(),
2542 static void isabus_fdc_class_init(ObjectClass *klass, void *data)
2544 DeviceClass *dc = DEVICE_CLASS(klass);
2546 dc->realize = isabus_fdc_realize;
2547 dc->fw_name = "fdc";
2548 dc->reset = fdctrl_external_reset_isa;
2549 dc->vmsd = &vmstate_isa_fdc;
2550 dc->props = isa_fdc_properties;
2551 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
2554 static void isabus_fdc_instance_init(Object *obj)
2556 FDCtrlISABus *isa = ISA_FDC(obj);
2558 device_add_bootindex_property(obj, &isa->bootindexA,
2559 "bootindexA", "/floppy@0",
2560 DEVICE(obj), NULL);
2561 device_add_bootindex_property(obj, &isa->bootindexB,
2562 "bootindexB", "/floppy@1",
2563 DEVICE(obj), NULL);
2566 static const TypeInfo isa_fdc_info = {
2567 .name = TYPE_ISA_FDC,
2568 .parent = TYPE_ISA_DEVICE,
2569 .instance_size = sizeof(FDCtrlISABus),
2570 .class_init = isabus_fdc_class_init,
2571 .instance_init = isabus_fdc_instance_init,
2574 static const VMStateDescription vmstate_sysbus_fdc ={
2575 .name = "fdc",
2576 .version_id = 2,
2577 .minimum_version_id = 2,
2578 .fields = (VMStateField[]) {
2579 VMSTATE_STRUCT(state, FDCtrlSysBus, 0, vmstate_fdc, FDCtrl),
2580 VMSTATE_END_OF_LIST()
2584 static Property sysbus_fdc_properties[] = {
2585 DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].blk),
2586 DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].blk),
2587 DEFINE_PROP_DEFAULT("fdtypeA", FDCtrlSysBus, state.drives[0].drive,
2588 FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
2589 FloppyDriveType),
2590 DEFINE_PROP_DEFAULT("fdtypeB", FDCtrlSysBus, state.drives[1].drive,
2591 FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
2592 FloppyDriveType),
2593 DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
2594 FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
2595 FloppyDriveType),
2596 DEFINE_PROP_END_OF_LIST(),
2599 static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
2601 DeviceClass *dc = DEVICE_CLASS(klass);
2603 dc->props = sysbus_fdc_properties;
2604 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
2607 static const TypeInfo sysbus_fdc_info = {
2608 .name = "sysbus-fdc",
2609 .parent = TYPE_SYSBUS_FDC,
2610 .instance_init = sysbus_fdc_initfn,
2611 .class_init = sysbus_fdc_class_init,
2614 static Property sun4m_fdc_properties[] = {
2615 DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].blk),
2616 DEFINE_PROP_DEFAULT("fdtype", FDCtrlSysBus, state.drives[0].drive,
2617 FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
2618 FloppyDriveType),
2619 DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
2620 FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
2621 FloppyDriveType),
2622 DEFINE_PROP_END_OF_LIST(),
2625 static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
2627 DeviceClass *dc = DEVICE_CLASS(klass);
2629 dc->props = sun4m_fdc_properties;
2630 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
2633 static const TypeInfo sun4m_fdc_info = {
2634 .name = "SUNW,fdtwo",
2635 .parent = TYPE_SYSBUS_FDC,
2636 .instance_init = sun4m_fdc_initfn,
2637 .class_init = sun4m_fdc_class_init,
2640 static void sysbus_fdc_common_class_init(ObjectClass *klass, void *data)
2642 DeviceClass *dc = DEVICE_CLASS(klass);
2644 dc->realize = sysbus_fdc_common_realize;
2645 dc->reset = fdctrl_external_reset_sysbus;
2646 dc->vmsd = &vmstate_sysbus_fdc;
2649 static const TypeInfo sysbus_fdc_type_info = {
2650 .name = TYPE_SYSBUS_FDC,
2651 .parent = TYPE_SYS_BUS_DEVICE,
2652 .instance_size = sizeof(FDCtrlSysBus),
2653 .instance_init = sysbus_fdc_common_initfn,
2654 .abstract = true,
2655 .class_init = sysbus_fdc_common_class_init,
2658 static void fdc_register_types(void)
2660 type_register_static(&isa_fdc_info);
2661 type_register_static(&sysbus_fdc_type_info);
2662 type_register_static(&sysbus_fdc_info);
2663 type_register_static(&sun4m_fdc_info);
2666 type_init(fdc_register_types)