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 if (!blkconf_blocksizes(&dev->conf, errp)) { 193 return; 194 } 195 196 if (dev->conf.logical_block_size != 512 || 197 dev->conf.physical_block_size != 512) 198 { 199 error_setg(errp, "Physical and logical block size must " 200 "be 512 for floppy"); 201 return; 202 } 203 204 /* 205 * rerror/werror aren't supported by fdc and therefore not even registered 206 * with qdev. So set the defaults manually before they are used in 207 * blkconf_apply_backend_options(). 208 */ 209 dev->conf.rerror = BLOCKDEV_ON_ERROR_AUTO; 210 dev->conf.werror = BLOCKDEV_ON_ERROR_AUTO; 211 212 if (!blkconf_apply_backend_options(&dev->conf, 213 blk_is_read_only(dev->conf.blk), 214 false, errp)) { 215 return; 216 } 217 218 /* 219 * 'enospc' is the default for -drive, 'report' is what blk_new() gives us 220 * for empty drives. 221 */ 222 if (blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC && 223 blk_get_on_error(dev->conf.blk, 0) != BLOCKDEV_ON_ERROR_REPORT) { 224 error_setg(errp, "fdc doesn't support drive option werror"); 225 return; 226 } 227 if (blk_get_on_error(dev->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) { 228 error_setg(errp, "fdc doesn't support drive option rerror"); 229 return; 230 } 231 232 drive->conf = &dev->conf; 233 drive->blk = dev->conf.blk; 234 drive->swimctrl = bus->ctrl; 235 236 blk_set_dev_ops(drive->blk, &swim_block_ops, drive); 237 } 238 239 static void swim_drive_class_init(ObjectClass *klass, void *data) 240 { 241 DeviceClass *k = DEVICE_CLASS(klass); 242 k->realize = swim_drive_realize; 243 set_bit(DEVICE_CATEGORY_STORAGE, k->categories); 244 k->bus_type = TYPE_SWIM_BUS; 245 device_class_set_props(k, swim_drive_properties); 246 k->desc = "virtual SWIM drive"; 247 } 248 249 static const TypeInfo swim_drive_info = { 250 .name = TYPE_SWIM_DRIVE, 251 .parent = TYPE_DEVICE, 252 .instance_size = sizeof(SWIMDrive), 253 .class_init = swim_drive_class_init, 254 }; 255 256 static const TypeInfo swim_bus_info = { 257 .name = TYPE_SWIM_BUS, 258 .parent = TYPE_BUS, 259 .instance_size = sizeof(SWIMBus), 260 }; 261 262 static void iwmctrl_write(void *opaque, hwaddr reg, uint64_t value, 263 unsigned size) 264 { 265 SWIMCtrl *swimctrl = opaque; 266 267 reg >>= REG_SHIFT; 268 269 swimctrl->regs[reg >> 1] = reg & 1; 270 271 if (swimctrl->regs[IWM_Q6] && 272 swimctrl->regs[IWM_Q7]) { 273 if (swimctrl->regs[IWM_MTR]) { 274 /* data register */ 275 swimctrl->iwm_data = value; 276 } else { 277 /* mode register */ 278 swimctrl->iwm_mode = value; 279 /* detect sequence to switch from IWM mode to SWIM mode */ 280 switch (swimctrl->iwm_switch) { 281 case 0: 282 if (value == 0x57) { 283 swimctrl->iwm_switch++; 284 } 285 break; 286 case 1: 287 if (value == 0x17) { 288 swimctrl->iwm_switch++; 289 } 290 break; 291 case 2: 292 if (value == 0x57) { 293 swimctrl->iwm_switch++; 294 } 295 break; 296 case 3: 297 if (value == 0x57) { 298 swimctrl->mode = SWIM_MODE_SWIM; 299 swimctrl->iwm_switch = 0; 300 } 301 break; 302 } 303 } 304 } 305 } 306 307 static uint64_t iwmctrl_read(void *opaque, hwaddr reg, unsigned size) 308 { 309 SWIMCtrl *swimctrl = opaque; 310 311 reg >>= REG_SHIFT; 312 313 swimctrl->regs[reg >> 1] = reg & 1; 314 315 return 0; 316 } 317 318 static void swimctrl_write(void *opaque, hwaddr reg, uint64_t value, 319 unsigned size) 320 { 321 SWIMCtrl *swimctrl = opaque; 322 323 if (swimctrl->mode == SWIM_MODE_IWM) { 324 iwmctrl_write(opaque, reg, value, size); 325 return; 326 } 327 328 reg >>= REG_SHIFT; 329 330 switch (reg) { 331 case SWIM_WRITE_PHASE: 332 swimctrl->swim_phase = value; 333 break; 334 case SWIM_WRITE_MODE0: 335 swimctrl->swim_mode &= ~value; 336 break; 337 case SWIM_WRITE_MODE1: 338 swimctrl->swim_mode |= value; 339 break; 340 case SWIM_WRITE_DATA: 341 case SWIM_WRITE_MARK: 342 case SWIM_WRITE_CRC: 343 case SWIM_WRITE_PARAMETER: 344 case SWIM_WRITE_SETUP: 345 break; 346 } 347 } 348 349 static uint64_t swimctrl_read(void *opaque, hwaddr reg, unsigned size) 350 { 351 SWIMCtrl *swimctrl = opaque; 352 uint32_t value = 0; 353 354 if (swimctrl->mode == SWIM_MODE_IWM) { 355 return iwmctrl_read(opaque, reg, size); 356 } 357 358 reg >>= REG_SHIFT; 359 360 switch (reg) { 361 case SWIM_READ_PHASE: 362 value = swimctrl->swim_phase; 363 break; 364 case SWIM_READ_HANDSHAKE: 365 if (swimctrl->swim_phase == SWIM_DRIVE_PRESENT) { 366 /* always answer "no drive present" */ 367 value = SWIM_SENSE; 368 } 369 break; 370 case SWIM_READ_DATA: 371 case SWIM_READ_MARK: 372 case SWIM_READ_ERROR: 373 case SWIM_READ_PARAMETER: 374 case SWIM_READ_SETUP: 375 case SWIM_READ_STATUS: 376 break; 377 } 378 379 return value; 380 } 381 382 static const MemoryRegionOps swimctrl_mem_ops = { 383 .write = swimctrl_write, 384 .read = swimctrl_read, 385 .endianness = DEVICE_NATIVE_ENDIAN, 386 }; 387 388 static void sysbus_swim_reset(DeviceState *d) 389 { 390 Swim *sys = SWIM(d); 391 SWIMCtrl *ctrl = &sys->ctrl; 392 int i; 393 394 ctrl->mode = 0; 395 ctrl->iwm_switch = 0; 396 for (i = 0; i < 8; i++) { 397 ctrl->regs[i] = 0; 398 } 399 ctrl->iwm_data = 0; 400 ctrl->iwm_mode = 0; 401 ctrl->swim_phase = 0; 402 ctrl->swim_mode = 0; 403 for (i = 0; i < SWIM_MAX_FD; i++) { 404 fd_recalibrate(&ctrl->drives[i]); 405 } 406 } 407 408 static void sysbus_swim_init(Object *obj) 409 { 410 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 411 Swim *sbs = SWIM(obj); 412 SWIMCtrl *swimctrl = &sbs->ctrl; 413 414 memory_region_init_io(&swimctrl->iomem, obj, &swimctrl_mem_ops, swimctrl, 415 "swim", 0x2000); 416 sysbus_init_mmio(sbd, &swimctrl->iomem); 417 } 418 419 static void sysbus_swim_realize(DeviceState *dev, Error **errp) 420 { 421 Swim *sys = SWIM(dev); 422 SWIMCtrl *swimctrl = &sys->ctrl; 423 424 qbus_create_inplace(&swimctrl->bus, sizeof(SWIMBus), TYPE_SWIM_BUS, dev, 425 NULL); 426 swimctrl->bus.ctrl = swimctrl; 427 } 428 429 static const VMStateDescription vmstate_fdrive = { 430 .name = "fdrive", 431 .version_id = 1, 432 .minimum_version_id = 1, 433 .fields = (VMStateField[]) { 434 VMSTATE_END_OF_LIST() 435 }, 436 }; 437 438 static const VMStateDescription vmstate_swim = { 439 .name = "swim", 440 .version_id = 1, 441 .minimum_version_id = 1, 442 .fields = (VMStateField[]) { 443 VMSTATE_INT32(mode, SWIMCtrl), 444 /* IWM mode */ 445 VMSTATE_INT32(iwm_switch, SWIMCtrl), 446 VMSTATE_UINT16_ARRAY(regs, SWIMCtrl, 8), 447 VMSTATE_UINT8(iwm_data, SWIMCtrl), 448 VMSTATE_UINT8(iwm_mode, SWIMCtrl), 449 /* SWIM mode */ 450 VMSTATE_UINT8(swim_phase, SWIMCtrl), 451 VMSTATE_UINT8(swim_mode, SWIMCtrl), 452 /* Drives */ 453 VMSTATE_STRUCT_ARRAY(drives, SWIMCtrl, SWIM_MAX_FD, 1, 454 vmstate_fdrive, FDrive), 455 VMSTATE_END_OF_LIST() 456 }, 457 }; 458 459 static const VMStateDescription vmstate_sysbus_swim = { 460 .name = "SWIM", 461 .version_id = 1, 462 .fields = (VMStateField[]) { 463 VMSTATE_STRUCT(ctrl, Swim, 0, vmstate_swim, SWIMCtrl), 464 VMSTATE_END_OF_LIST() 465 } 466 }; 467 468 static void sysbus_swim_class_init(ObjectClass *oc, void *data) 469 { 470 DeviceClass *dc = DEVICE_CLASS(oc); 471 472 dc->realize = sysbus_swim_realize; 473 dc->reset = sysbus_swim_reset; 474 dc->vmsd = &vmstate_sysbus_swim; 475 } 476 477 static const TypeInfo sysbus_swim_info = { 478 .name = TYPE_SWIM, 479 .parent = TYPE_SYS_BUS_DEVICE, 480 .instance_size = sizeof(Swim), 481 .instance_init = sysbus_swim_init, 482 .class_init = sysbus_swim_class_init, 483 }; 484 485 static void swim_register_types(void) 486 { 487 type_register_static(&sysbus_swim_info); 488 type_register_static(&swim_bus_info); 489 type_register_static(&swim_drive_info); 490 } 491 492 type_init(swim_register_types) 493