1 /*
2 * QEMU Macintosh floppy disk controller emulator (SWIM)
3 *
4 * Copyright (c) 2014-2018 Laurent Vivier <laurent@vivier.eu>
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2. See
7 * the COPYING file in the top-level directory.
8 *
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.
11 */
12
13 #include "qemu/osdep.h"
14 #include "qemu/main-loop.h"
15 #include "qapi/error.h"
16 #include "system/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"
22 #include "trace.h"
23
24
25 /* IWM latch bits */
26
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
33 #define IWMLB_L6 6
34 #define IWMLB_L7 7
35
36 /* IWM registers */
37
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
46
47 /* SWIM registers */
48
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
57
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
66
67 #define REG_SHIFT 9
68
69 #define SWIM_MODE_STATUS_BIT 6
70 #define SWIM_MODE_IWM 0
71 #define SWIM_MODE_ISM 1
72
73 /* bits in phase register */
74
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
86
87 /* Select values for swim_select and swim_readbit */
88
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
101
102 /* Bits in handshake register */
103
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
112
113 /* bits in setup register */
114
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
123
124 /* bits in mode register */
125
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
133
134 static const char *iwm_reg_names[] = {
135 "READALLONES", "READDATA", "READSTATUS0", "READSTATUS1",
136 "READWHANDSHAKE0", "READWHANDSHAKE1", "WRITESETMODE", "WRITEDATA"
137 };
138
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"
144 };
145
fd_recalibrate(FDrive * drive)146 static void fd_recalibrate(FDrive *drive)
147 {
148 }
149
swim_change_cb(void * opaque,bool load,Error ** errp)150 static void swim_change_cb(void *opaque, bool load, Error **errp)
151 {
152 FDrive *drive = opaque;
153
154 if (!load) {
155 blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort);
156 } else {
157 if (!blkconf_apply_backend_options(drive->conf,
158 !blk_supports_write_perm(drive->blk),
159 false, errp)) {
160 return;
161 }
162 }
163 }
164
165 static const BlockDevOps swim_block_ops = {
166 .change_media_cb = swim_change_cb,
167 };
168
169 static const Property swim_drive_properties[] = {
170 DEFINE_PROP_INT32("unit", SWIMDrive, unit, -1),
171 DEFINE_BLOCK_PROPERTIES(SWIMDrive, conf),
172 };
173
swim_drive_realize(DeviceState * qdev,Error ** errp)174 static void swim_drive_realize(DeviceState *qdev, Error **errp)
175 {
176 SWIMDrive *dev = SWIM_DRIVE(qdev);
177 SWIMBus *bus = SWIM_BUS(qdev->parent_bus);
178 FDrive *drive;
179 int ret;
180
181 if (dev->unit == -1) {
182 for (dev->unit = 0; dev->unit < SWIM_MAX_FD; dev->unit++) {
183 drive = &bus->ctrl->drives[dev->unit];
184 if (!drive->blk) {
185 break;
186 }
187 }
188 }
189
190 if (dev->unit >= SWIM_MAX_FD) {
191 error_setg(errp, "Can't create floppy unit %d, bus supports "
192 "only %d units", dev->unit, SWIM_MAX_FD);
193 return;
194 }
195
196 drive = &bus->ctrl->drives[dev->unit];
197 if (drive->blk) {
198 error_setg(errp, "Floppy unit %d is in use", dev->unit);
199 return;
200 }
201
202 if (!dev->conf.blk) {
203 /* Anonymous BlockBackend for an empty drive */
204 dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
205 ret = blk_attach_dev(dev->conf.blk, qdev);
206 assert(ret == 0);
207 }
208
209 if (!blkconf_blocksizes(&dev->conf, errp)) {
210 return;
211 }
212
213 if (dev->conf.logical_block_size != 512 ||
214 dev->conf.physical_block_size != 512)
215 {
216 error_setg(errp, "Physical and logical block size must "
217 "be 512 for floppy");
218 return;
219 }
220
221 /*
222 * rerror/werror aren't supported by fdc and therefore not even registered
223 * with qdev. So set the defaults manually before they are used in
224 * blkconf_apply_backend_options().
225 */
226 dev->conf.rerror = BLOCKDEV_ON_ERROR_AUTO;
227 dev->conf.werror = BLOCKDEV_ON_ERROR_AUTO;
228
229 if (!blkconf_apply_backend_options(&dev->conf,
230 !blk_supports_write_perm(dev->conf.blk),
231 false, errp)) {
232 return;
233 }
234
235 /*
236 * 'enospc' is the default for -drive, 'report' is what blk_new() gives us
237 * for empty drives.
238 */
239 if (blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC &&
240 blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_REPORT) {
241 error_setg(errp, "fdc doesn't support drive option werror");
242 return;
243 }
244 if (blk_get_on_error(dev->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
245 error_setg(errp, "fdc doesn't support drive option rerror");
246 return;
247 }
248
249 drive->conf = &dev->conf;
250 drive->blk = dev->conf.blk;
251 drive->swimctrl = bus->ctrl;
252
253 blk_set_dev_ops(drive->blk, &swim_block_ops, drive);
254 }
255
swim_drive_class_init(ObjectClass * klass,const void * data)256 static void swim_drive_class_init(ObjectClass *klass, const void *data)
257 {
258 DeviceClass *k = DEVICE_CLASS(klass);
259 k->realize = swim_drive_realize;
260 set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
261 k->bus_type = TYPE_SWIM_BUS;
262 device_class_set_props(k, swim_drive_properties);
263 k->desc = "virtual SWIM drive";
264 }
265
266 static const TypeInfo swim_drive_info = {
267 .name = TYPE_SWIM_DRIVE,
268 .parent = TYPE_DEVICE,
269 .instance_size = sizeof(SWIMDrive),
270 .class_init = swim_drive_class_init,
271 };
272
273 static const TypeInfo swim_bus_info = {
274 .name = TYPE_SWIM_BUS,
275 .parent = TYPE_BUS,
276 .instance_size = sizeof(SWIMBus),
277 };
278
iwmctrl_write(void * opaque,hwaddr addr,uint64_t value,unsigned size)279 static void iwmctrl_write(void *opaque, hwaddr addr, uint64_t value,
280 unsigned size)
281 {
282 SWIMCtrl *swimctrl = opaque;
283 uint8_t latch, reg, ism_bit;
284
285 addr >>= REG_SHIFT;
286
287 /* A3-A1 select a latch, A0 specifies the value */
288 latch = (addr >> 1) & 7;
289 if (addr & 1) {
290 swimctrl->iwm_latches |= (1 << latch);
291 } else {
292 swimctrl->iwm_latches &= ~(1 << latch);
293 }
294
295 reg = (swimctrl->iwm_latches & 0xc0) >> 5 |
296 (swimctrl->iwm_latches & 0x10) >> 4;
297
298 swimctrl->iwmregs[reg] = value;
299 trace_swim_iwmctrl_write(reg, iwm_reg_names[reg], size, value);
300
301 switch (reg) {
302 case IWM_WRITESETMODE:
303 /* detect sequence to switch from IWM mode to SWIM mode */
304 ism_bit = (value & (1 << SWIM_MODE_STATUS_BIT));
305
306 switch (swimctrl->iwm_switch) {
307 case 0:
308 if (ism_bit) { /* 1 */
309 swimctrl->iwm_switch++;
310 }
311 break;
312 case 1:
313 if (!ism_bit) { /* 0 */
314 swimctrl->iwm_switch++;
315 }
316 break;
317 case 2:
318 if (ism_bit) { /* 1 */
319 swimctrl->iwm_switch++;
320 }
321 break;
322 case 3:
323 if (ism_bit) { /* 1 */
324 swimctrl->iwm_switch++;
325
326 swimctrl->mode = SWIM_MODE_ISM;
327 swimctrl->swim_mode |= (1 << SWIM_MODE_STATUS_BIT);
328 swimctrl->iwm_switch = 0;
329 trace_swim_switch_to_ism();
330
331 /* Switch to ISM registers */
332 memory_region_del_subregion(&swimctrl->swim, &swimctrl->iwm);
333 memory_region_add_subregion(&swimctrl->swim, 0x0,
334 &swimctrl->ism);
335 }
336 break;
337 }
338 break;
339 default:
340 break;
341 }
342 }
343
iwmctrl_read(void * opaque,hwaddr addr,unsigned size)344 static uint64_t iwmctrl_read(void *opaque, hwaddr addr, unsigned size)
345 {
346 SWIMCtrl *swimctrl = opaque;
347 uint8_t latch, reg, value;
348
349 addr >>= REG_SHIFT;
350
351 /* A3-A1 select a latch, A0 specifies the value */
352 latch = (addr >> 1) & 7;
353 if (addr & 1) {
354 swimctrl->iwm_latches |= (1 << latch);
355 } else {
356 swimctrl->iwm_latches &= ~(1 << latch);
357 }
358
359 reg = (swimctrl->iwm_latches & 0xc0) >> 5 |
360 (swimctrl->iwm_latches & 0x10) >> 4;
361
362 switch (reg) {
363 case IWM_READALLONES:
364 value = 0xff;
365 break;
366 default:
367 value = 0;
368 break;
369 }
370
371 trace_swim_iwmctrl_read(reg, iwm_reg_names[reg], size, value);
372 return value;
373 }
374
375 static const MemoryRegionOps swimctrl_iwm_ops = {
376 .write = iwmctrl_write,
377 .read = iwmctrl_read,
378 .endianness = DEVICE_BIG_ENDIAN,
379 };
380
ismctrl_write(void * opaque,hwaddr reg,uint64_t value,unsigned size)381 static void ismctrl_write(void *opaque, hwaddr reg, uint64_t value,
382 unsigned size)
383 {
384 SWIMCtrl *swimctrl = opaque;
385
386 reg >>= REG_SHIFT;
387
388 trace_swim_ismctrl_write(reg, ism_reg_names[reg], size, value);
389
390 switch (reg) {
391 case SWIM_WRITE_PHASE:
392 swimctrl->swim_phase = value;
393 break;
394 case SWIM_WRITE_MODE0:
395 swimctrl->swim_mode &= ~value;
396 /* Any access to MODE0 register resets PRAM index */
397 swimctrl->pram_idx = 0;
398
399 if (!(swimctrl->swim_mode & (1 << SWIM_MODE_STATUS_BIT))) {
400 /* Clearing the mode bit switches to IWM mode */
401 swimctrl->mode = SWIM_MODE_IWM;
402 swimctrl->iwm_latches = 0;
403 trace_swim_switch_to_iwm();
404
405 /* Switch to IWM registers */
406 memory_region_del_subregion(&swimctrl->swim, &swimctrl->ism);
407 memory_region_add_subregion(&swimctrl->swim, 0x0,
408 &swimctrl->iwm);
409 }
410 break;
411 case SWIM_WRITE_MODE1:
412 swimctrl->swim_mode |= value;
413 break;
414 case SWIM_WRITE_PARAMETER:
415 swimctrl->pram[swimctrl->pram_idx++] = value;
416 swimctrl->pram_idx &= 0xf;
417 break;
418 case SWIM_WRITE_DATA:
419 case SWIM_WRITE_MARK:
420 case SWIM_WRITE_CRC:
421 case SWIM_WRITE_SETUP:
422 break;
423 }
424 }
425
ismctrl_read(void * opaque,hwaddr reg,unsigned size)426 static uint64_t ismctrl_read(void *opaque, hwaddr reg, unsigned size)
427 {
428 SWIMCtrl *swimctrl = opaque;
429 uint32_t value = 0;
430
431 reg >>= REG_SHIFT;
432
433 switch (reg) {
434 case SWIM_READ_PHASE:
435 value = swimctrl->swim_phase;
436 break;
437 case SWIM_READ_HANDSHAKE:
438 if (swimctrl->swim_phase == SWIM_DRIVE_PRESENT) {
439 /* always answer "no drive present" */
440 value = SWIM_SENSE;
441 }
442 break;
443 case SWIM_READ_PARAMETER:
444 value = swimctrl->pram[swimctrl->pram_idx++];
445 swimctrl->pram_idx &= 0xf;
446 break;
447 case SWIM_READ_STATUS:
448 value = swimctrl->swim_status & ~(1 << SWIM_MODE_STATUS_BIT);
449 if (swimctrl->swim_mode == SWIM_MODE_ISM) {
450 value |= (1 << SWIM_MODE_STATUS_BIT);
451 }
452 break;
453 case SWIM_READ_DATA:
454 case SWIM_READ_MARK:
455 case SWIM_READ_ERROR:
456 case SWIM_READ_SETUP:
457 break;
458 }
459
460 trace_swim_ismctrl_read(reg, ism_reg_names[reg], size, value);
461 return value;
462 }
463
464 static const MemoryRegionOps swimctrl_ism_ops = {
465 .write = ismctrl_write,
466 .read = ismctrl_read,
467 .endianness = DEVICE_BIG_ENDIAN,
468 };
469
sysbus_swim_reset(DeviceState * d)470 static void sysbus_swim_reset(DeviceState *d)
471 {
472 Swim *sys = SWIM(d);
473 SWIMCtrl *ctrl = &sys->ctrl;
474 int i;
475
476 ctrl->mode = 0;
477 ctrl->iwm_switch = 0;
478 memset(ctrl->iwmregs, 0, sizeof(ctrl->iwmregs));
479
480 ctrl->swim_phase = 0;
481 ctrl->swim_mode = 0;
482 memset(ctrl->ismregs, 0, sizeof(ctrl->ismregs));
483 for (i = 0; i < SWIM_MAX_FD; i++) {
484 fd_recalibrate(&ctrl->drives[i]);
485 }
486 }
487
sysbus_swim_init(Object * obj)488 static void sysbus_swim_init(Object *obj)
489 {
490 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
491 Swim *sbs = SWIM(obj);
492 SWIMCtrl *swimctrl = &sbs->ctrl;
493
494 memory_region_init(&swimctrl->swim, obj, "swim", 0x2000);
495 memory_region_init_io(&swimctrl->iwm, obj, &swimctrl_iwm_ops, swimctrl,
496 "iwm", 0x2000);
497 memory_region_init_io(&swimctrl->ism, obj, &swimctrl_ism_ops, swimctrl,
498 "ism", 0x2000);
499 sysbus_init_mmio(sbd, &swimctrl->swim);
500 }
501
sysbus_swim_realize(DeviceState * dev,Error ** errp)502 static void sysbus_swim_realize(DeviceState *dev, Error **errp)
503 {
504 Swim *sys = SWIM(dev);
505 SWIMCtrl *swimctrl = &sys->ctrl;
506
507 qbus_init(&swimctrl->bus, sizeof(SWIMBus), TYPE_SWIM_BUS, dev, NULL);
508 swimctrl->bus.ctrl = swimctrl;
509
510 /* Default register set is IWM */
511 memory_region_add_subregion(&swimctrl->swim, 0x0, &swimctrl->iwm);
512 }
513
514 static const VMStateDescription vmstate_fdrive = {
515 .name = "fdrive",
516 .version_id = 1,
517 .minimum_version_id = 1,
518 .fields = (const VMStateField[]) {
519 VMSTATE_END_OF_LIST()
520 },
521 };
522
523 static const VMStateDescription vmstate_swim = {
524 .name = "swim",
525 .version_id = 1,
526 .minimum_version_id = 1,
527 .fields = (const VMStateField[]) {
528 VMSTATE_INT32(mode, SWIMCtrl),
529 /* IWM mode */
530 VMSTATE_INT32(iwm_switch, SWIMCtrl),
531 VMSTATE_UINT8(iwm_latches, SWIMCtrl),
532 VMSTATE_UINT8_ARRAY(iwmregs, SWIMCtrl, 8),
533 /* SWIM mode */
534 VMSTATE_UINT8_ARRAY(ismregs, SWIMCtrl, 16),
535 VMSTATE_UINT8(swim_phase, SWIMCtrl),
536 VMSTATE_UINT8(swim_mode, SWIMCtrl),
537 /* Drives */
538 VMSTATE_STRUCT_ARRAY(drives, SWIMCtrl, SWIM_MAX_FD, 1,
539 vmstate_fdrive, FDrive),
540 VMSTATE_END_OF_LIST()
541 },
542 };
543
544 static const VMStateDescription vmstate_sysbus_swim = {
545 .name = "SWIM",
546 .version_id = 1,
547 .fields = (const VMStateField[]) {
548 VMSTATE_STRUCT(ctrl, Swim, 0, vmstate_swim, SWIMCtrl),
549 VMSTATE_END_OF_LIST()
550 }
551 };
552
sysbus_swim_class_init(ObjectClass * oc,const void * data)553 static void sysbus_swim_class_init(ObjectClass *oc, const void *data)
554 {
555 DeviceClass *dc = DEVICE_CLASS(oc);
556
557 dc->realize = sysbus_swim_realize;
558 device_class_set_legacy_reset(dc, sysbus_swim_reset);
559 dc->vmsd = &vmstate_sysbus_swim;
560 }
561
562 static const TypeInfo sysbus_swim_info = {
563 .name = TYPE_SWIM,
564 .parent = TYPE_SYS_BUS_DEVICE,
565 .instance_size = sizeof(Swim),
566 .instance_init = sysbus_swim_init,
567 .class_init = sysbus_swim_class_init,
568 };
569
swim_register_types(void)570 static void swim_register_types(void)
571 {
572 type_register_static(&sysbus_swim_info);
573 type_register_static(&swim_bus_info);
574 type_register_static(&swim_drive_info);
575 }
576
577 type_init(swim_register_types)
578