2 * QEMU Macintosh floppy disk controller emulator (SWIM)
4 * Copyright (c) 2014-2018 Laurent Vivier <laurent@vivier.eu>
6 * This work is licensed under the terms of the GNU GPL, version 2. See
7 * the COPYING file in the top-level directory.
9 * Only the basic support: it allows to switch from IWM (Integrated WOZ
10 * Machine) mode to the SWIM mode and makes the linux driver happy.
13 #include "qemu/osdep.h"
14 #include "qemu/main-loop.h"
15 #include "qapi/error.h"
16 #include "sysemu/block-backend.h"
17 #include "hw/sysbus.h"
18 #include "migration/vmstate.h"
19 #include "hw/block/block.h"
20 #include "hw/block/swim.h"
21 #include "hw/qdev-properties.h"
27 #define IWMLB_PHASE0 0
28 #define IWMLB_PHASE1 1
29 #define IWMLB_PHASE2 2
30 #define IWMLB_PHASE3 3
31 #define IWMLB_MOTORON 4
32 #define IWMLB_DRIVESEL 5
38 #define IWM_READALLONES 0
39 #define IWM_READDATA 1
40 #define IWM_READSTATUS0 2
41 #define IWM_READSTATUS1 3
42 #define IWM_READWHANDSHAKE0 4
43 #define IWM_READWHANDSHAKE1 5
44 #define IWM_WRITESETMODE 6
45 #define IWM_WRITEDATA 7
49 #define SWIM_WRITE_DATA 0
50 #define SWIM_WRITE_MARK 1
51 #define SWIM_WRITE_CRC 2
52 #define SWIM_WRITE_PARAMETER 3
53 #define SWIM_WRITE_PHASE 4
54 #define SWIM_WRITE_SETUP 5
55 #define SWIM_WRITE_MODE0 6
56 #define SWIM_WRITE_MODE1 7
58 #define SWIM_READ_DATA 8
59 #define SWIM_READ_MARK 9
60 #define SWIM_READ_ERROR 10
61 #define SWIM_READ_PARAMETER 11
62 #define SWIM_READ_PHASE 12
63 #define SWIM_READ_SETUP 13
64 #define SWIM_READ_STATUS 14
65 #define SWIM_READ_HANDSHAKE 15
69 #define SWIM_MODE_STATUS_BIT 6
70 #define SWIM_MODE_IWM 0
71 #define SWIM_MODE_ISM 1
73 /* bits in phase register */
75 #define SWIM_SEEK_NEGATIVE 0x074
76 #define SWIM_STEP 0x071
77 #define SWIM_MOTOR_ON 0x072
78 #define SWIM_MOTOR_OFF 0x076
79 #define SWIM_INDEX 0x073
80 #define SWIM_EJECT 0x077
81 #define SWIM_SETMFM 0x171
82 #define SWIM_SETGCR 0x175
83 #define SWIM_RELAX 0x033
84 #define SWIM_LSTRB 0x008
85 #define SWIM_CA_MASK 0x077
87 /* Select values for swim_select and swim_readbit */
89 #define SWIM_READ_DATA_0 0x074
90 #define SWIM_TWOMEG_DRIVE 0x075
91 #define SWIM_SINGLE_SIDED 0x076
92 #define SWIM_DRIVE_PRESENT 0x077
93 #define SWIM_DISK_IN 0x170
94 #define SWIM_WRITE_PROT 0x171
95 #define SWIM_TRACK_ZERO 0x172
96 #define SWIM_TACHO 0x173
97 #define SWIM_READ_DATA_1 0x174
98 #define SWIM_MFM_MODE 0x175
99 #define SWIM_SEEK_COMPLETE 0x176
100 #define SWIM_ONEMEG_MEDIA 0x177
102 /* Bits in handshake register */
104 #define SWIM_MARK_BYTE 0x01
105 #define SWIM_CRC_ZERO 0x02
106 #define SWIM_RDDATA 0x04
107 #define SWIM_SENSE 0x08
108 #define SWIM_MOTEN 0x10
109 #define SWIM_ERROR 0x20
110 #define SWIM_DAT2BYTE 0x40
111 #define SWIM_DAT1BYTE 0x80
113 /* bits in setup register */
115 #define SWIM_S_INV_WDATA 0x01
116 #define SWIM_S_3_5_SELECT 0x02
117 #define SWIM_S_GCR 0x04
118 #define SWIM_S_FCLK_DIV2 0x08
119 #define SWIM_S_ERROR_CORR 0x10
120 #define SWIM_S_IBM_DRIVE 0x20
121 #define SWIM_S_GCR_WRITE 0x40
122 #define SWIM_S_TIMEOUT 0x80
124 /* bits in mode register */
126 #define SWIM_CLFIFO 0x01
127 #define SWIM_ENBL1 0x02
128 #define SWIM_ENBL2 0x04
129 #define SWIM_ACTION 0x08
130 #define SWIM_WRITE_MODE 0x10
131 #define SWIM_HEDSEL 0x20
132 #define SWIM_MOTON 0x80
134 static const char *iwm_reg_names
[] = {
135 "READALLONES", "READDATA", "READSTATUS0", "READSTATUS1",
136 "READWHANDSHAKE0", "READWHANDSHAKE1", "WRITESETMODE", "WRITEDATA"
139 static const char *ism_reg_names
[] = {
140 "WRITE_DATA", "WRITE_MARK", "WRITE_CRC", "WRITE_PARAMETER",
141 "WRITE_PHASE", "WRITE_SETUP", "WRITE_MODE0", "WRITE_MODE1",
142 "READ_DATA", "READ_MARK", "READ_ERROR", "READ_PARAMETER",
143 "READ_PHASE", "READ_SETUP", "READ_STATUS", "READ_HANDSHAKE"
146 static void fd_recalibrate(FDrive
*drive
)
150 static void swim_change_cb(void *opaque
, bool load
, Error
**errp
)
152 FDrive
*drive
= opaque
;
155 blk_set_perm(drive
->blk
, 0, BLK_PERM_ALL
, &error_abort
);
157 if (!blkconf_apply_backend_options(drive
->conf
,
158 !blk_supports_write_perm(drive
->blk
),
165 static const BlockDevOps swim_block_ops
= {
166 .change_media_cb
= swim_change_cb
,
169 static Property swim_drive_properties
[] = {
170 DEFINE_PROP_INT32("unit", SWIMDrive
, unit
, -1),
171 DEFINE_BLOCK_PROPERTIES(SWIMDrive
, conf
),
172 DEFINE_PROP_END_OF_LIST(),
175 static void swim_drive_realize(DeviceState
*qdev
, Error
**errp
)
177 SWIMDrive
*dev
= SWIM_DRIVE(qdev
);
178 SWIMBus
*bus
= SWIM_BUS(qdev
->parent_bus
);
182 if (dev
->unit
== -1) {
183 for (dev
->unit
= 0; dev
->unit
< SWIM_MAX_FD
; dev
->unit
++) {
184 drive
= &bus
->ctrl
->drives
[dev
->unit
];
191 if (dev
->unit
>= SWIM_MAX_FD
) {
192 error_setg(errp
, "Can't create floppy unit %d, bus supports "
193 "only %d units", dev
->unit
, SWIM_MAX_FD
);
197 drive
= &bus
->ctrl
->drives
[dev
->unit
];
199 error_setg(errp
, "Floppy unit %d is in use", dev
->unit
);
203 if (!dev
->conf
.blk
) {
204 /* Anonymous BlockBackend for an empty drive */
205 dev
->conf
.blk
= blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL
);
206 ret
= blk_attach_dev(dev
->conf
.blk
, qdev
);
210 if (!blkconf_blocksizes(&dev
->conf
, errp
)) {
214 if (dev
->conf
.logical_block_size
!= 512 ||
215 dev
->conf
.physical_block_size
!= 512)
217 error_setg(errp
, "Physical and logical block size must "
218 "be 512 for floppy");
223 * rerror/werror aren't supported by fdc and therefore not even registered
224 * with qdev. So set the defaults manually before they are used in
225 * blkconf_apply_backend_options().
227 dev
->conf
.rerror
= BLOCKDEV_ON_ERROR_AUTO
;
228 dev
->conf
.werror
= BLOCKDEV_ON_ERROR_AUTO
;
230 if (!blkconf_apply_backend_options(&dev
->conf
,
231 !blk_supports_write_perm(dev
->conf
.blk
),
237 * 'enospc' is the default for -drive, 'report' is what blk_new() gives us
240 if (blk_get_on_error(dev
->conf
.blk
, 0) != BLOCKDEV_ON_ERROR_ENOSPC
&&
241 blk_get_on_error(dev
->conf
.blk
, 0) != BLOCKDEV_ON_ERROR_REPORT
) {
242 error_setg(errp
, "fdc doesn't support drive option werror");
245 if (blk_get_on_error(dev
->conf
.blk
, 1) != BLOCKDEV_ON_ERROR_REPORT
) {
246 error_setg(errp
, "fdc doesn't support drive option rerror");
250 drive
->conf
= &dev
->conf
;
251 drive
->blk
= dev
->conf
.blk
;
252 drive
->swimctrl
= bus
->ctrl
;
254 blk_set_dev_ops(drive
->blk
, &swim_block_ops
, drive
);
257 static void swim_drive_class_init(ObjectClass
*klass
, void *data
)
259 DeviceClass
*k
= DEVICE_CLASS(klass
);
260 k
->realize
= swim_drive_realize
;
261 set_bit(DEVICE_CATEGORY_STORAGE
, k
->categories
);
262 k
->bus_type
= TYPE_SWIM_BUS
;
263 device_class_set_props(k
, swim_drive_properties
);
264 k
->desc
= "virtual SWIM drive";
267 static const TypeInfo swim_drive_info
= {
268 .name
= TYPE_SWIM_DRIVE
,
269 .parent
= TYPE_DEVICE
,
270 .instance_size
= sizeof(SWIMDrive
),
271 .class_init
= swim_drive_class_init
,
274 static const TypeInfo swim_bus_info
= {
275 .name
= TYPE_SWIM_BUS
,
277 .instance_size
= sizeof(SWIMBus
),
280 static void iwmctrl_write(void *opaque
, hwaddr addr
, uint64_t value
,
283 SWIMCtrl
*swimctrl
= opaque
;
284 uint8_t latch
, reg
, ism_bit
;
288 /* A3-A1 select a latch, A0 specifies the value */
289 latch
= (addr
>> 1) & 7;
291 swimctrl
->iwm_latches
|= (1 << latch
);
293 swimctrl
->iwm_latches
&= ~(1 << latch
);
296 reg
= (swimctrl
->iwm_latches
& 0xc0) >> 5 |
297 (swimctrl
->iwm_latches
& 0x10) >> 4;
299 swimctrl
->iwmregs
[reg
] = value
;
300 trace_swim_iwmctrl_write(reg
, iwm_reg_names
[reg
], size
, value
);
303 case IWM_WRITESETMODE
:
304 /* detect sequence to switch from IWM mode to SWIM mode */
305 ism_bit
= (value
& (1 << SWIM_MODE_STATUS_BIT
));
307 switch (swimctrl
->iwm_switch
) {
309 if (ism_bit
) { /* 1 */
310 swimctrl
->iwm_switch
++;
314 if (!ism_bit
) { /* 0 */
315 swimctrl
->iwm_switch
++;
319 if (ism_bit
) { /* 1 */
320 swimctrl
->iwm_switch
++;
324 if (ism_bit
) { /* 1 */
325 swimctrl
->iwm_switch
++;
327 swimctrl
->mode
= SWIM_MODE_ISM
;
328 swimctrl
->swim_mode
|= (1 << SWIM_MODE_STATUS_BIT
);
329 swimctrl
->iwm_switch
= 0;
330 trace_swim_switch_to_ism();
332 /* Switch to ISM registers */
333 memory_region_del_subregion(&swimctrl
->swim
, &swimctrl
->iwm
);
334 memory_region_add_subregion(&swimctrl
->swim
, 0x0,
345 static uint64_t iwmctrl_read(void *opaque
, hwaddr addr
, unsigned size
)
347 SWIMCtrl
*swimctrl
= opaque
;
348 uint8_t latch
, reg
, value
;
352 /* A3-A1 select a latch, A0 specifies the value */
353 latch
= (addr
>> 1) & 7;
355 swimctrl
->iwm_latches
|= (1 << latch
);
357 swimctrl
->iwm_latches
&= ~(1 << latch
);
360 reg
= (swimctrl
->iwm_latches
& 0xc0) >> 5 |
361 (swimctrl
->iwm_latches
& 0x10) >> 4;
364 case IWM_READALLONES
:
372 trace_swim_iwmctrl_read(reg
, iwm_reg_names
[reg
], size
, value
);
376 static const MemoryRegionOps swimctrl_iwm_ops
= {
377 .write
= iwmctrl_write
,
378 .read
= iwmctrl_read
,
379 .endianness
= DEVICE_BIG_ENDIAN
,
382 static void ismctrl_write(void *opaque
, hwaddr reg
, uint64_t value
,
385 SWIMCtrl
*swimctrl
= opaque
;
389 trace_swim_ismctrl_write(reg
, ism_reg_names
[reg
], size
, value
);
392 case SWIM_WRITE_PHASE
:
393 swimctrl
->swim_phase
= value
;
395 case SWIM_WRITE_MODE0
:
396 swimctrl
->swim_mode
&= ~value
;
397 /* Any access to MODE0 register resets PRAM index */
398 swimctrl
->pram_idx
= 0;
400 if (!(swimctrl
->swim_mode
& (1 << SWIM_MODE_STATUS_BIT
))) {
401 /* Clearing the mode bit switches to IWM mode */
402 swimctrl
->mode
= SWIM_MODE_IWM
;
403 swimctrl
->iwm_latches
= 0;
404 trace_swim_switch_to_iwm();
406 /* Switch to IWM registers */
407 memory_region_del_subregion(&swimctrl
->swim
, &swimctrl
->ism
);
408 memory_region_add_subregion(&swimctrl
->swim
, 0x0,
412 case SWIM_WRITE_MODE1
:
413 swimctrl
->swim_mode
|= value
;
415 case SWIM_WRITE_PARAMETER
:
416 swimctrl
->pram
[swimctrl
->pram_idx
++] = value
;
417 swimctrl
->pram_idx
&= 0xf;
419 case SWIM_WRITE_DATA
:
420 case SWIM_WRITE_MARK
:
422 case SWIM_WRITE_SETUP
:
427 static uint64_t ismctrl_read(void *opaque
, hwaddr reg
, unsigned size
)
429 SWIMCtrl
*swimctrl
= opaque
;
435 case SWIM_READ_PHASE
:
436 value
= swimctrl
->swim_phase
;
438 case SWIM_READ_HANDSHAKE
:
439 if (swimctrl
->swim_phase
== SWIM_DRIVE_PRESENT
) {
440 /* always answer "no drive present" */
444 case SWIM_READ_PARAMETER
:
445 value
= swimctrl
->pram
[swimctrl
->pram_idx
++];
446 swimctrl
->pram_idx
&= 0xf;
448 case SWIM_READ_STATUS
:
449 value
= swimctrl
->swim_status
& ~(1 << SWIM_MODE_STATUS_BIT
);
450 if (swimctrl
->swim_mode
== SWIM_MODE_ISM
) {
451 value
|= (1 << SWIM_MODE_STATUS_BIT
);
456 case SWIM_READ_ERROR
:
457 case SWIM_READ_SETUP
:
461 trace_swim_ismctrl_read(reg
, ism_reg_names
[reg
], size
, value
);
465 static const MemoryRegionOps swimctrl_ism_ops
= {
466 .write
= ismctrl_write
,
467 .read
= ismctrl_read
,
468 .endianness
= DEVICE_BIG_ENDIAN
,
471 static void sysbus_swim_reset(DeviceState
*d
)
474 SWIMCtrl
*ctrl
= &sys
->ctrl
;
478 ctrl
->iwm_switch
= 0;
479 memset(ctrl
->iwmregs
, 0, sizeof(ctrl
->iwmregs
));
481 ctrl
->swim_phase
= 0;
483 memset(ctrl
->ismregs
, 0, sizeof(ctrl
->ismregs
));
484 for (i
= 0; i
< SWIM_MAX_FD
; i
++) {
485 fd_recalibrate(&ctrl
->drives
[i
]);
489 static void sysbus_swim_init(Object
*obj
)
491 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
492 Swim
*sbs
= SWIM(obj
);
493 SWIMCtrl
*swimctrl
= &sbs
->ctrl
;
495 memory_region_init(&swimctrl
->swim
, obj
, "swim", 0x2000);
496 memory_region_init_io(&swimctrl
->iwm
, obj
, &swimctrl_iwm_ops
, swimctrl
,
498 memory_region_init_io(&swimctrl
->ism
, obj
, &swimctrl_ism_ops
, swimctrl
,
500 sysbus_init_mmio(sbd
, &swimctrl
->swim
);
503 static void sysbus_swim_realize(DeviceState
*dev
, Error
**errp
)
505 Swim
*sys
= SWIM(dev
);
506 SWIMCtrl
*swimctrl
= &sys
->ctrl
;
508 qbus_init(&swimctrl
->bus
, sizeof(SWIMBus
), TYPE_SWIM_BUS
, dev
, NULL
);
509 swimctrl
->bus
.ctrl
= swimctrl
;
511 /* Default register set is IWM */
512 memory_region_add_subregion(&swimctrl
->swim
, 0x0, &swimctrl
->iwm
);
515 static const VMStateDescription vmstate_fdrive
= {
518 .minimum_version_id
= 1,
519 .fields
= (VMStateField
[]) {
520 VMSTATE_END_OF_LIST()
524 static const VMStateDescription vmstate_swim
= {
527 .minimum_version_id
= 1,
528 .fields
= (VMStateField
[]) {
529 VMSTATE_INT32(mode
, SWIMCtrl
),
531 VMSTATE_INT32(iwm_switch
, SWIMCtrl
),
532 VMSTATE_UINT8(iwm_latches
, SWIMCtrl
),
533 VMSTATE_UINT8_ARRAY(iwmregs
, SWIMCtrl
, 8),
535 VMSTATE_UINT8_ARRAY(ismregs
, SWIMCtrl
, 16),
536 VMSTATE_UINT8(swim_phase
, SWIMCtrl
),
537 VMSTATE_UINT8(swim_mode
, SWIMCtrl
),
539 VMSTATE_STRUCT_ARRAY(drives
, SWIMCtrl
, SWIM_MAX_FD
, 1,
540 vmstate_fdrive
, FDrive
),
541 VMSTATE_END_OF_LIST()
545 static const VMStateDescription vmstate_sysbus_swim
= {
548 .fields
= (VMStateField
[]) {
549 VMSTATE_STRUCT(ctrl
, Swim
, 0, vmstate_swim
, SWIMCtrl
),
550 VMSTATE_END_OF_LIST()
554 static void sysbus_swim_class_init(ObjectClass
*oc
, void *data
)
556 DeviceClass
*dc
= DEVICE_CLASS(oc
);
558 dc
->realize
= sysbus_swim_realize
;
559 dc
->reset
= sysbus_swim_reset
;
560 dc
->vmsd
= &vmstate_sysbus_swim
;
563 static const TypeInfo sysbus_swim_info
= {
565 .parent
= TYPE_SYS_BUS_DEVICE
,
566 .instance_size
= sizeof(Swim
),
567 .instance_init
= sysbus_swim_init
,
568 .class_init
= sysbus_swim_class_init
,
571 static void swim_register_types(void)
573 type_register_static(&sysbus_swim_info
);
574 type_register_static(&swim_bus_info
);
575 type_register_static(&swim_drive_info
);
578 type_init(swim_register_types
)