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 "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" 22 23 /* IWM registers */ 24 25 #define IWM_PH0L 0 26 #define IWM_PH0H 1 27 #define IWM_PH1L 2 28 #define IWM_PH1H 3 29 #define IWM_PH2L 4 30 #define IWM_PH2H 5 31 #define IWM_PH3L 6 32 #define IWM_PH3H 7 33 #define IWM_MTROFF 8 34 #define IWM_MTRON 9 35 #define IWM_INTDRIVE 10 36 #define IWM_EXTDRIVE 11 37 #define IWM_Q6L 12 38 #define IWM_Q6H 13 39 #define IWM_Q7L 14 40 #define IWM_Q7H 15 41 42 /* SWIM registers */ 43 44 #define SWIM_WRITE_DATA 0 45 #define SWIM_WRITE_MARK 1 46 #define SWIM_WRITE_CRC 2 47 #define SWIM_WRITE_PARAMETER 3 48 #define SWIM_WRITE_PHASE 4 49 #define SWIM_WRITE_SETUP 5 50 #define SWIM_WRITE_MODE0 6 51 #define SWIM_WRITE_MODE1 7 52 53 #define SWIM_READ_DATA 8 54 #define SWIM_READ_MARK 9 55 #define SWIM_READ_ERROR 10 56 #define SWIM_READ_PARAMETER 11 57 #define SWIM_READ_PHASE 12 58 #define SWIM_READ_SETUP 13 59 #define SWIM_READ_STATUS 14 60 #define SWIM_READ_HANDSHAKE 15 61 62 #define REG_SHIFT 9 63 64 #define SWIM_MODE_IWM 0 65 #define SWIM_MODE_SWIM 1 66 67 /* bits in phase register */ 68 69 #define SWIM_SEEK_NEGATIVE 0x074 70 #define SWIM_STEP 0x071 71 #define SWIM_MOTOR_ON 0x072 72 #define SWIM_MOTOR_OFF 0x076 73 #define SWIM_INDEX 0x073 74 #define SWIM_EJECT 0x077 75 #define SWIM_SETMFM 0x171 76 #define SWIM_SETGCR 0x175 77 #define SWIM_RELAX 0x033 78 #define SWIM_LSTRB 0x008 79 #define SWIM_CA_MASK 0x077 80 81 /* Select values for swim_select and swim_readbit */ 82 83 #define SWIM_READ_DATA_0 0x074 84 #define SWIM_TWOMEG_DRIVE 0x075 85 #define SWIM_SINGLE_SIDED 0x076 86 #define SWIM_DRIVE_PRESENT 0x077 87 #define SWIM_DISK_IN 0x170 88 #define SWIM_WRITE_PROT 0x171 89 #define SWIM_TRACK_ZERO 0x172 90 #define SWIM_TACHO 0x173 91 #define SWIM_READ_DATA_1 0x174 92 #define SWIM_MFM_MODE 0x175 93 #define SWIM_SEEK_COMPLETE 0x176 94 #define SWIM_ONEMEG_MEDIA 0x177 95 96 /* Bits in handshake register */ 97 98 #define SWIM_MARK_BYTE 0x01 99 #define SWIM_CRC_ZERO 0x02 100 #define SWIM_RDDATA 0x04 101 #define SWIM_SENSE 0x08 102 #define SWIM_MOTEN 0x10 103 #define SWIM_ERROR 0x20 104 #define SWIM_DAT2BYTE 0x40 105 #define SWIM_DAT1BYTE 0x80 106 107 /* bits in setup register */ 108 109 #define SWIM_S_INV_WDATA 0x01 110 #define SWIM_S_3_5_SELECT 0x02 111 #define SWIM_S_GCR 0x04 112 #define SWIM_S_FCLK_DIV2 0x08 113 #define SWIM_S_ERROR_CORR 0x10 114 #define SWIM_S_IBM_DRIVE 0x20 115 #define SWIM_S_GCR_WRITE 0x40 116 #define SWIM_S_TIMEOUT 0x80 117 118 /* bits in mode register */ 119 120 #define SWIM_CLFIFO 0x01 121 #define SWIM_ENBL1 0x02 122 #define SWIM_ENBL2 0x04 123 #define SWIM_ACTION 0x08 124 #define SWIM_WRITE_MODE 0x10 125 #define SWIM_HEDSEL 0x20 126 #define SWIM_MOTON 0x80 127 128 static void fd_recalibrate(FDrive *drive) 129 { 130 } 131 132 static void swim_change_cb(void *opaque, bool load, Error **errp) 133 { 134 FDrive *drive = opaque; 135 136 if (!load) { 137 blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort); 138 } else { 139 if (!blkconf_apply_backend_options(drive->conf, 140 blk_is_read_only(drive->blk), false, 141 errp)) { 142 return; 143 } 144 } 145 } 146 147 static const BlockDevOps swim_block_ops = { 148 .change_media_cb = swim_change_cb, 149 }; 150 151 static Property swim_drive_properties[] = { 152 DEFINE_PROP_INT32("unit", SWIMDrive, unit, -1), 153 DEFINE_BLOCK_PROPERTIES(SWIMDrive, conf), 154 DEFINE_PROP_END_OF_LIST(), 155 }; 156 157 static void swim_drive_realize(DeviceState *qdev, Error **errp) 158 { 159 SWIMDrive *dev = SWIM_DRIVE(qdev); 160 SWIMBus *bus = SWIM_BUS(qdev->parent_bus); 161 FDrive *drive; 162 int ret; 163 164 if (dev->unit == -1) { 165 for (dev->unit = 0; dev->unit < SWIM_MAX_FD; dev->unit++) { 166 drive = &bus->ctrl->drives[dev->unit]; 167 if (!drive->blk) { 168 break; 169 } 170 } 171 } 172 173 if (dev->unit >= SWIM_MAX_FD) { 174 error_setg(errp, "Can't create floppy unit %d, bus supports " 175 "only %d units", dev->unit, SWIM_MAX_FD); 176 return; 177 } 178 179 drive = &bus->ctrl->drives[dev->unit]; 180 if (drive->blk) { 181 error_setg(errp, "Floppy unit %d is in use", dev->unit); 182 return; 183 } 184 185 if (!dev->conf.blk) { 186 /* Anonymous BlockBackend for an empty drive */ 187 dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); 188 ret = blk_attach_dev(dev->conf.blk, qdev); 189 assert(ret == 0); 190 } 191 192 blkconf_blocksizes(&dev->conf); 193 if (dev->conf.logical_block_size != 512 || 194 dev->conf.physical_block_size != 512) 195 { 196 error_setg(errp, "Physical and logical block size must " 197 "be 512 for floppy"); 198 return; 199 } 200 201 /* 202 * rerror/werror aren't supported by fdc and therefore not even registered 203 * with qdev. So set the defaults manually before they are used in 204 * blkconf_apply_backend_options(). 205 */ 206 dev->conf.rerror = BLOCKDEV_ON_ERROR_AUTO; 207 dev->conf.werror = BLOCKDEV_ON_ERROR_AUTO; 208 209 if (!blkconf_apply_backend_options(&dev->conf, 210 blk_is_read_only(dev->conf.blk), 211 false, errp)) { 212 return; 213 } 214 215 /* 216 * 'enospc' is the default for -drive, 'report' is what blk_new() gives us 217 * for empty drives. 218 */ 219 if (blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC && 220 blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_REPORT) { 221 error_setg(errp, "fdc doesn't support drive option werror"); 222 return; 223 } 224 if (blk_get_on_error(dev->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) { 225 error_setg(errp, "fdc doesn't support drive option rerror"); 226 return; 227 } 228 229 drive->conf = &dev->conf; 230 drive->blk = dev->conf.blk; 231 drive->swimctrl = bus->ctrl; 232 233 blk_set_dev_ops(drive->blk, &swim_block_ops, drive); 234 } 235 236 static void swim_drive_class_init(ObjectClass *klass, void *data) 237 { 238 DeviceClass *k = DEVICE_CLASS(klass); 239 k->realize = swim_drive_realize; 240 set_bit(DEVICE_CATEGORY_STORAGE, k->categories); 241 k->bus_type = TYPE_SWIM_BUS; 242 device_class_set_props(k, swim_drive_properties); 243 k->desc = "virtual SWIM drive"; 244 } 245 246 static const TypeInfo swim_drive_info = { 247 .name = TYPE_SWIM_DRIVE, 248 .parent = TYPE_DEVICE, 249 .instance_size = sizeof(SWIMDrive), 250 .class_init = swim_drive_class_init, 251 }; 252 253 static const TypeInfo swim_bus_info = { 254 .name = TYPE_SWIM_BUS, 255 .parent = TYPE_BUS, 256 .instance_size = sizeof(SWIMBus), 257 }; 258 259 static void iwmctrl_write(void *opaque, hwaddr reg, uint64_t value, 260 unsigned size) 261 { 262 SWIMCtrl *swimctrl = opaque; 263 264 reg >>= REG_SHIFT; 265 266 swimctrl->regs[reg >> 1] = reg & 1; 267 268 if (swimctrl->regs[IWM_Q6] && 269 swimctrl->regs[IWM_Q7]) { 270 if (swimctrl->regs[IWM_MTR]) { 271 /* data register */ 272 swimctrl->iwm_data = value; 273 } else { 274 /* mode register */ 275 swimctrl->iwm_mode = value; 276 /* detect sequence to switch from IWM mode to SWIM mode */ 277 switch (swimctrl->iwm_switch) { 278 case 0: 279 if (value == 0x57) { 280 swimctrl->iwm_switch++; 281 } 282 break; 283 case 1: 284 if (value == 0x17) { 285 swimctrl->iwm_switch++; 286 } 287 break; 288 case 2: 289 if (value == 0x57) { 290 swimctrl->iwm_switch++; 291 } 292 break; 293 case 3: 294 if (value == 0x57) { 295 swimctrl->mode = SWIM_MODE_SWIM; 296 swimctrl->iwm_switch = 0; 297 } 298 break; 299 } 300 } 301 } 302 } 303 304 static uint64_t iwmctrl_read(void *opaque, hwaddr reg, unsigned size) 305 { 306 SWIMCtrl *swimctrl = opaque; 307 308 reg >>= REG_SHIFT; 309 310 swimctrl->regs[reg >> 1] = reg & 1; 311 312 return 0; 313 } 314 315 static void swimctrl_write(void *opaque, hwaddr reg, uint64_t value, 316 unsigned size) 317 { 318 SWIMCtrl *swimctrl = opaque; 319 320 if (swimctrl->mode == SWIM_MODE_IWM) { 321 iwmctrl_write(opaque, reg, value, size); 322 return; 323 } 324 325 reg >>= REG_SHIFT; 326 327 switch (reg) { 328 case SWIM_WRITE_PHASE: 329 swimctrl->swim_phase = value; 330 break; 331 case SWIM_WRITE_MODE0: 332 swimctrl->swim_mode &= ~value; 333 break; 334 case SWIM_WRITE_MODE1: 335 swimctrl->swim_mode |= value; 336 break; 337 case SWIM_WRITE_DATA: 338 case SWIM_WRITE_MARK: 339 case SWIM_WRITE_CRC: 340 case SWIM_WRITE_PARAMETER: 341 case SWIM_WRITE_SETUP: 342 break; 343 } 344 } 345 346 static uint64_t swimctrl_read(void *opaque, hwaddr reg, unsigned size) 347 { 348 SWIMCtrl *swimctrl = opaque; 349 uint32_t value = 0; 350 351 if (swimctrl->mode == SWIM_MODE_IWM) { 352 return iwmctrl_read(opaque, reg, size); 353 } 354 355 reg >>= REG_SHIFT; 356 357 switch (reg) { 358 case SWIM_READ_PHASE: 359 value = swimctrl->swim_phase; 360 break; 361 case SWIM_READ_HANDSHAKE: 362 if (swimctrl->swim_phase == SWIM_DRIVE_PRESENT) { 363 /* always answer "no drive present" */ 364 value = SWIM_SENSE; 365 } 366 break; 367 case SWIM_READ_DATA: 368 case SWIM_READ_MARK: 369 case SWIM_READ_ERROR: 370 case SWIM_READ_PARAMETER: 371 case SWIM_READ_SETUP: 372 case SWIM_READ_STATUS: 373 break; 374 } 375 376 return value; 377 } 378 379 static const MemoryRegionOps swimctrl_mem_ops = { 380 .write = swimctrl_write, 381 .read = swimctrl_read, 382 .endianness = DEVICE_NATIVE_ENDIAN, 383 }; 384 385 static void sysbus_swim_reset(DeviceState *d) 386 { 387 SWIM *sys = SWIM(d); 388 SWIMCtrl *ctrl = &sys->ctrl; 389 int i; 390 391 ctrl->mode = 0; 392 ctrl->iwm_switch = 0; 393 for (i = 0; i < 8; i++) { 394 ctrl->regs[i] = 0; 395 } 396 ctrl->iwm_data = 0; 397 ctrl->iwm_mode = 0; 398 ctrl->swim_phase = 0; 399 ctrl->swim_mode = 0; 400 for (i = 0; i < SWIM_MAX_FD; i++) { 401 fd_recalibrate(&ctrl->drives[i]); 402 } 403 } 404 405 static void sysbus_swim_init(Object *obj) 406 { 407 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 408 SWIM *sbs = SWIM(obj); 409 SWIMCtrl *swimctrl = &sbs->ctrl; 410 411 memory_region_init_io(&swimctrl->iomem, obj, &swimctrl_mem_ops, swimctrl, 412 "swim", 0x2000); 413 sysbus_init_mmio(sbd, &swimctrl->iomem); 414 } 415 416 static void sysbus_swim_realize(DeviceState *dev, Error **errp) 417 { 418 SWIM *sys = SWIM(dev); 419 SWIMCtrl *swimctrl = &sys->ctrl; 420 421 qbus_create_inplace(&swimctrl->bus, sizeof(SWIMBus), TYPE_SWIM_BUS, dev, 422 NULL); 423 swimctrl->bus.ctrl = swimctrl; 424 } 425 426 static const VMStateDescription vmstate_fdrive = { 427 .name = "fdrive", 428 .version_id = 1, 429 .minimum_version_id = 1, 430 .fields = (VMStateField[]) { 431 VMSTATE_END_OF_LIST() 432 }, 433 }; 434 435 static const VMStateDescription vmstate_swim = { 436 .name = "swim", 437 .version_id = 1, 438 .minimum_version_id = 1, 439 .fields = (VMStateField[]) { 440 VMSTATE_INT32(mode, SWIMCtrl), 441 /* IWM mode */ 442 VMSTATE_INT32(iwm_switch, SWIMCtrl), 443 VMSTATE_UINT16_ARRAY(regs, SWIMCtrl, 8), 444 VMSTATE_UINT8(iwm_data, SWIMCtrl), 445 VMSTATE_UINT8(iwm_mode, SWIMCtrl), 446 /* SWIM mode */ 447 VMSTATE_UINT8(swim_phase, SWIMCtrl), 448 VMSTATE_UINT8(swim_mode, SWIMCtrl), 449 /* Drives */ 450 VMSTATE_STRUCT_ARRAY(drives, SWIMCtrl, SWIM_MAX_FD, 1, 451 vmstate_fdrive, FDrive), 452 VMSTATE_END_OF_LIST() 453 }, 454 }; 455 456 static const VMStateDescription vmstate_sysbus_swim = { 457 .name = "SWIM", 458 .version_id = 1, 459 .fields = (VMStateField[]) { 460 VMSTATE_STRUCT(ctrl, SWIM, 0, vmstate_swim, SWIMCtrl), 461 VMSTATE_END_OF_LIST() 462 } 463 }; 464 465 static void sysbus_swim_class_init(ObjectClass *oc, void *data) 466 { 467 DeviceClass *dc = DEVICE_CLASS(oc); 468 469 dc->realize = sysbus_swim_realize; 470 dc->reset = sysbus_swim_reset; 471 dc->vmsd = &vmstate_sysbus_swim; 472 } 473 474 static const TypeInfo sysbus_swim_info = { 475 .name = TYPE_SWIM, 476 .parent = TYPE_SYS_BUS_DEVICE, 477 .instance_size = sizeof(SWIM), 478 .instance_init = sysbus_swim_init, 479 .class_init = sysbus_swim_class_init, 480 }; 481 482 static void swim_register_types(void) 483 { 484 type_register_static(&sysbus_swim_info); 485 type_register_static(&swim_bus_info); 486 type_register_static(&swim_drive_info); 487 } 488 489 type_init(swim_register_types) 490