trunk/src/emu/machine/hdc9234.c
| r31134 | r31135 | |
| 27 | 27 | /* |
| 28 | 28 | Register names of the HDC. The left part is the set of write registers, |
| 29 | 29 | while the right part are the read registers. |
| 30 | |
| 31 | +------+------+------+------+------+------+------+------+ |
| 32 | DHEAD: | 0 | Sector size | 0 | Desired head (OUTPUT2) | AT mode |
| 33 | +------+------+------+------+------+------+------+------+ |
| 34 | | 0 | Desired cylinder | Desired head (OUTPUT2) | SMC mode |
| 35 | +------+------+------+------+------+------+------+------+ |
| 36 | +------+------+------+------+------+------+------+------+ |
| 37 | RETRY: | Retry count | Progr. output (OUTPUT1) | |
| 38 | +------+------+------+------+------+------+------+------+ |
| 39 | +------+------+------+------+------+------+------+------+ |
| 40 | MODE: | HD | use CRC/ECC | FM | 0 | step rate | |
| 41 | +------+------+------+------+------+------+------+------+ |
| 42 | +------+------+------+------+------+------+------+------+ |
| 43 | INTCOMM:| 1 | 0 | Done | DelD | User | WrPrt| Ready|Wfault| |
| 44 | +------+------+------+------+------+------+------+------+ |
| 45 | +------+------+------+------+------+------+------+------+ |
| 46 | DDELAY: | 0 | 0 | Sector size | 0 | 0 | Zone | AT mode |
| 47 | +------+------+------+------+------+------+------+------+ |
| 48 | | Data to be written on disk | writing |
| 49 | +------+------+------+------+------+------+------+------+ |
| 50 | | Head load timer count | drselect |
| 51 | +------+------+------+------+------+------+------+------+ |
| 30 | 52 | */ |
| 31 | 53 | enum |
| 32 | 54 | { |
| r31134 | r31135 | |
| 51 | 73 | */ |
| 52 | 74 | enum |
| 53 | 75 | { |
| 54 | | ST_INTPEND = 0x80 , // interrupt pending |
| 55 | | ST_DMAREQ = 0x40 , // DMA request |
| 56 | | ST_DONE = 0x20 , // command done |
| 57 | | ST_TERMCOD = 0x18 , // termination code (see below) |
| 58 | | TC_SUCCESS = 0x00 , // Successful completion |
| 59 | | TC_RDIDERR = 0x08 , // Error in READ-ID sequence |
| 60 | | TC_SEEKERR = 0x10 , // Error in SEEK sequence |
| 61 | | TC_DATAERR = 0x18 , // Error in DATA-TRANSFER seq. |
| 62 | | ST_RDYCHNG = 0x04 , // ready change |
| 63 | | ST_OVRUN = 0x02 , // overrun/underrun |
| 64 | | ST_BADSECT = 0x01 // bad sector |
| 76 | ST_INTPEND = 0x80, // interrupt pending |
| 77 | ST_DMAREQ = 0x40, // DMA request |
| 78 | ST_DONE = 0x20, // command done |
| 79 | ST_TERMCOD = 0x18, // termination code (see below) |
| 80 | TC_SUCCESS = 0x00, // Successful completion |
| 81 | TC_RDIDERR = 0x08, // Error in READ-ID sequence |
| 82 | TC_SEEKERR = 0x10, // Error in SEEK sequence |
| 83 | TC_DATAERR = 0x18, // Error in DATA-TRANSFER seq. |
| 84 | ST_RDYCHNG = 0x04, // ready change |
| 85 | ST_OVRUN = 0x02, // overrun/underrun |
| 86 | ST_BADSECT = 0x01 // bad sector |
| 65 | 87 | }; |
| 66 | 88 | |
| 67 | 89 | /* |
| 90 | Definition of bits in the Termination-Conditions register |
| 91 | */ |
| 92 | enum |
| 93 | { |
| 94 | TC_CRCPRE = 0x80, // CRC register preset, must be 1 |
| 95 | TC_UNUSED = 0x40, // bit 6 is not used and must be 0 |
| 96 | TC_INTDONE = 0x20, // interrupt on command completion |
| 97 | TC_TDELDAT = 0x10, // terminate on deleted data mark detection |
| 98 | TC_TDUSER = 0x08, // user-defined condition |
| 99 | TC_TWPROT = 0x04, // terminate on write protection |
| 100 | TC_INTRDCH = 0x02, // interrupt on ready change |
| 101 | TC_TWRFLT = 0x01 // interrupt on write fault |
| 102 | }; |
| 103 | |
| 104 | /* |
| 68 | 105 | Bits in the internal output registers. The registers are output via the |
| 69 | 106 | auxiliary bus (AB) |
| 70 | 107 | |
| r31134 | r31135 | |
| 117 | 154 | m_out_intrq(*this), |
| 118 | 155 | m_out_dip(*this), |
| 119 | 156 | m_out_auxbus(*this), |
| 120 | | m_in_auxbus(*this), |
| 121 | 157 | m_in_dma(*this), |
| 122 | 158 | m_out_dma(*this) |
| 123 | 159 | { |
| r31134 | r31135 | |
| 189 | 225 | // done when no drive is in use |
| 190 | 226 | if (TRACE_ACT) logerror("%s: drdeselect command\n", tag()); |
| 191 | 227 | set_bits(m_output1, OUT1_DRVSEL3|OUT1_DRVSEL2|OUT1_DRVSEL1|OUT1_DRVSEL0, false); |
| 192 | | set_bits(m_output2, OUT2_DRVSEL3I, true); // inverted level |
| 228 | sync_latches_out(); |
| 193 | 229 | } |
| 194 | 230 | else if (opcode >= 0x20 && opcode <= 0x3f) |
| 195 | 231 | { |
| 196 | 232 | // DRIVE SELECT |
| 197 | | if (TRACE_ACT) logerror("%s: drselect command %02x\n", tag(), opcode); |
| 198 | 233 | drive_select(opcode&0x1f); |
| 199 | 234 | } |
| 200 | 235 | else if (opcode >= 0x40 && opcode <= 0x4f) |
| 201 | 236 | { |
| 202 | 237 | // SETREGPTR |
| 203 | | if (TRACE_ACT) logerror("%s: setregptr command %02x\n", tag(), opcode); |
| 204 | 238 | m_register_pointer = opcode & 0xf; |
| 239 | if (TRACE_ACT) logerror("%s: setregptr command; start reg=%d\n", tag(), m_register_pointer); |
| 205 | 240 | // Spec does not say anything about the effect of setting an |
| 206 | 241 | // invalid value (only "care should be taken") |
| 207 | 242 | if (m_register_pointer > 10) |
| r31134 | r31135 | |
| 210 | 245 | m_register_pointer = 10; |
| 211 | 246 | } |
| 212 | 247 | } |
| 248 | |
| 249 | set_command_done(); |
| 213 | 250 | } |
| 214 | 251 | |
| 252 | /* |
| 253 | Assert Command Done status bit, triggering interrupts as needed |
| 254 | */ |
| 255 | void hdc9234_device::set_command_done(int flags) |
| 256 | { |
| 257 | set_bits(m_register_r[INT_STATUS], ST_DONE, true); |
| 258 | |
| 259 | if (flags != -1) |
| 260 | { |
| 261 | set_bits(m_register_r[INT_STATUS], ST_TERMCOD, false); // clear the previously set flags |
| 262 | m_register_r[INT_STATUS] |= flags; |
| 263 | if (TRACE_ACT) logerror("%s: command %02x done, flags=%02x\n", tag(), m_command, flags); |
| 264 | } |
| 265 | else |
| 266 | { |
| 267 | if (TRACE_ACT) logerror("%s: command %02x done\n", tag(), m_command); |
| 268 | } |
| 269 | |
| 270 | // [1], p. 6 |
| 271 | if (m_register_w[INT_COMM_TERM] & TC_INTDONE) |
| 272 | set_interrupt(ASSERT_LINE); |
| 273 | } |
| 274 | |
| 275 | /* |
| 276 | Preserve previously set termination code |
| 277 | */ |
| 278 | void hdc9234_device::set_command_done() |
| 279 | { |
| 280 | set_command_done(-1); |
| 281 | } |
| 282 | |
| 215 | 283 | void hdc9234_device::drive_select(int driveparm) |
| 216 | 284 | { |
| 217 | 285 | // Command word |
| r31134 | r31135 | |
| 222 | 290 | // +-----+-----+-----+-----+-----+-----+-----+-----+ |
| 223 | 291 | // |
| 224 | 292 | // [1] p.5: lower 4 bits of retry count register is put on OUTPUT1 |
| 293 | |
| 225 | 294 | m_output1 = (0x10 << (driveparm & 0x03)) | (m_register_w[RETRY_COUNT]&0x0f); |
| 295 | // Bit 7 of OUTPUT2 is complement of Bit 7 of OUTPUT1 |
| 226 | 296 | |
| 227 | 297 | // The drive type is used to configure DMA burst mode ([1], p.12) |
| 228 | 298 | // and to select the timing parameters |
| 229 | 299 | m_selected_drive_type = (driveparm>>2) & 0x03; |
| 230 | 300 | m_head_load_delay_enable = (driveparm>>4)&0x01; |
| 231 | 301 | |
| 302 | if (TRACE_ACT) logerror("%s: drive select command: head load delay=%d, type=%d, drive=%d\n", tag(), m_head_load_delay_enable, m_selected_drive_type, driveparm&3); |
| 303 | |
| 232 | 304 | /* |
| 233 | 305 | // We need to store the type of the drive for the poll_drives command |
| 234 | 306 | // to be able to correctly select the device (floppy or hard disk). |
| r31134 | r31135 | |
| 244 | 316 | m_register_r[CHIP_STATUS] = (m_register_r[CHIP_STATUS] & 0xfc) | (driveparm & 0x03); |
| 245 | 317 | |
| 246 | 318 | sync_latches_out(); |
| 247 | | sync_status_in(); |
| 248 | 319 | } |
| 249 | 320 | |
| 250 | 321 | /* |
| r31134 | r31135 | |
| 257 | 328 | } |
| 258 | 329 | |
| 259 | 330 | /* |
| 260 | | Get the state from outside and latch it in the register. |
| 261 | | There should be a bus driver on the PCB which provides the signals from |
| 262 | | both the hard and floppy drives during S0=S1=0 and STB*=0 times via the |
| 263 | | auxiliary bus. |
| 264 | | */ |
| 265 | | void hdc9234_device::sync_status_in() |
| 266 | | { |
| 267 | | UINT8 prev = m_register_r[DRIVE_STATUS]; |
| 268 | | m_register_r[DRIVE_STATUS] = m_in_auxbus(0); |
| 269 | | |
| 270 | | // Raise interrupt if ready changes. |
| 271 | | if (((m_register_r[DRIVE_STATUS] & HDC_DS_READY) != (prev & HDC_DS_READY)) |
| 272 | | & (m_register_r[INT_STATUS] & ST_RDYCHNG)) |
| 273 | | { |
| 274 | | set_interrupt(ASSERT_LINE); |
| 275 | | } |
| 276 | | } |
| 277 | | |
| 278 | | /* |
| 279 | | Push the output registers over the auxiliary bus. It is expected that |
| 280 | | the PCB contains latches to store the values. |
| 281 | | TODO: Timing (the spec is not clear at that point) |
| 282 | | */ |
| 283 | | void hdc9234_device::sync_latches_out() |
| 284 | | { |
| 285 | | m_output1 = (m_output1 & 0xf0) | (m_register_w[RETRY_COUNT]&0x0f); |
| 286 | | m_out_auxbus((offs_t)HDC_OUTPUT_1, m_output1); |
| 287 | | m_out_auxbus((offs_t)HDC_OUTPUT_2, m_output2); |
| 288 | | } |
| 289 | | |
| 290 | | /* |
| 291 | 331 | Read a byte of data from the controller |
| 292 | 332 | The address (offset) encodes the C/D* line (command and /data) |
| 293 | 333 | */ |
| r31134 | r31135 | |
| 351 | 391 | } |
| 352 | 392 | |
| 353 | 393 | /* |
| 394 | Auxiliary bus operation. |
| 395 | |
| 396 | The auxbus of the HDC9234 is used to poll the drive status of the cur- |
| 397 | rently selected drive, to transmit DMA address bytes, to output the |
| 398 | OUTPUT1 register, and to output the OUTPUT2 register. |
| 399 | |
| 400 | The specification is not really precise on the times when this bus is |
| 401 | used, but at least we can rely on this information: |
| 402 | |
| 403 | - Whenever there is no output of data, the bus is sampled. ([1], p.8, |
| 404 | Drive status register). Data is sampled at the rising edge of STB*. |
| 405 | As the minimum STB* pulse is 800ns with min 100ns S0/S1 settling time |
| 406 | and min 100ns hold time we can say that the bus is polled at a maximum |
| 407 | rate of 1 MHz. |
| 408 | |
| 409 | - Data for the DMA address is output only when the address is initially |
| 410 | set; also when the address must be set again on error ([1], p.5, |
| 411 | DMA registers). The external memory system has to take care of the |
| 412 | addressing for subsequent bytes. The address will be increased by the |
| 413 | length of a sector during multiple sector read/write operations. |
| 414 | |
| 415 | We may assume that the OUTPUT1 and OUTPUT2 operations only occur on |
| 416 | changes to the registers in the controller. The values showing up on the |
| 417 | auxiliary bus must be latched anyway. |
| 418 | |
| 419 | For the sampling of drive status values, the emulation would have to |
| 420 | invoke a callback to the hosting board at a rate of about 1 MHz. Since |
| 421 | the devices like floppy or hard disks are pushing their status changes, |
| 422 | it makes much more sense to allow for an incoming call to the controller |
| 423 | instead of a polling. This also allows to raise interrupts as soon |
| 424 | as the drive status changes. The difference to the real controller |
| 425 | would be less than 3 microseconds (in the worst case when the auxbus is |
| 426 | currently outputting data as the drive status change occurs). |
| 427 | |
| 428 | Drive status read |
| 429 | S0 = 0, S1 = 0 |
| 430 | +------+------+------+------+------+------+------+------+ |
| 431 | | ECC |Index | SeekC| Tr00 | User | WrPrt| Ready|Fault | |
| 432 | +------+------+------+------+------+------+------+------+ |
| 433 | |
| 434 | |
| 435 | OUTPUT1 register contents |
| 436 | S0 = 0, S1 = 1 |
| 437 | +------+------+------+------+------+------+------+------+ |
| 438 | | Drv3 | Drv2 | Drv1 | Drv0 | PO3 | PO2 | PO1 | PO0 | |
| 439 | +------+------+------+------+------+------+------+------+ |
| 440 | |
| 441 | DrvX = select Drive X (only one bit allowed) |
| 442 | POX = Programmable output X (contents from low 4 bits of register RETRY_COUNT) |
| 443 | |
| 444 | |
| 445 | OUTPUT2 register contents |
| 446 | S0 = 1, S1 = 1 |
| 447 | +------+------+------+------+------+------+------+------+ |
| 448 | | Drv3*| WCur | Dir | Step | Head | |
| 449 | +------+------+------+------+------+------+------+------+ |
| 450 | |
| 451 | Drv3* = inverted Drv3 signal of OUTPUT1 |
| 452 | WCur = Reduced write current |
| 453 | Dir = Step direction (0 = towards track 0) |
| 454 | Step = Step pulse |
| 455 | Head = desired head |
| 456 | */ |
| 457 | |
| 458 | /* |
| 459 | Read the drive status over the auxbus |
| 460 | (as said, let the controller board push the values into the controller) |
| 461 | */ |
| 462 | void hdc9234_device::auxbus_in(UINT8 data) |
| 463 | { |
| 464 | if (TRACE_ACT) logerror("%s: Got value %02x via auxbus\n", tag(), data); |
| 465 | UINT8 prev = m_register_r[DRIVE_STATUS]; |
| 466 | m_register_r[DRIVE_STATUS] = data; |
| 467 | |
| 468 | // Raise interrupt if ready changes. |
| 469 | if (((m_register_r[DRIVE_STATUS] & HDC_DS_READY) != (prev & HDC_DS_READY)) |
| 470 | & (m_register_r[INT_STATUS] & ST_RDYCHNG)) |
| 471 | { |
| 472 | set_interrupt(ASSERT_LINE); |
| 473 | } |
| 474 | } |
| 475 | |
| 476 | /* |
| 477 | Push the output registers over the auxiliary bus. It is expected that |
| 478 | the PCB contains latches to store the values. |
| 479 | */ |
| 480 | void hdc9234_device::sync_latches_out() |
| 481 | { |
| 482 | m_out_auxbus((offs_t)HDC_OUTPUT_1, m_output1); |
| 483 | set_bits(m_output2, OUT2_DRVSEL3I, (m_output1 & 0x80)==0); |
| 484 | m_out_auxbus((offs_t)HDC_OUTPUT_2, m_output2); |
| 485 | } |
| 486 | |
| 487 | /* |
| 354 | 488 | Reset the controller. Negative logic, but we use ASSERT_LINE. |
| 355 | 489 | */ |
| 356 | 490 | WRITE_LINE_MEMBER( hdc9234_device::reset ) |
| r31134 | r31135 | |
| 368 | 502 | m_out_intrq.resolve_safe(); |
| 369 | 503 | m_out_dip.resolve_safe(); |
| 370 | 504 | m_out_auxbus.resolve_safe(); |
| 371 | | m_in_auxbus.resolve_safe(0); |
| 372 | 505 | m_out_dma.resolve_safe(); |
| 373 | 506 | m_in_dma.resolve_safe(0); |
| 374 | 507 | |
| r31134 | r31135 | |
| 381 | 514 | m_selected_drive_type = 0; |
| 382 | 515 | m_head_load_delay_enable = false; |
| 383 | 516 | m_register_pointer = 0; |
| 517 | m_output1 = 0; |
| 518 | m_output2 = 0x80; |
| 519 | |
| 520 | set_interrupt(CLEAR_LINE); |
| 521 | m_out_dip(CLEAR_LINE); |
| 522 | |
| 523 | for (int i=0; i<=11; i++) |
| 524 | m_register_r[i] = m_register_w[i] = 0; |
| 384 | 525 | } |
| 385 | 526 | |
| 386 | 527 | const device_type HDC9234 = &device_creator<hdc9234_device>; |
trunk/src/emu/bus/ti99_peb/hfdc.c
| r31134 | r31135 | |
| 352 | 352 | m_ram_page[(bit-4)/5] |= 1 << ((bit-9)%5); |
| 353 | 353 | else |
| 354 | 354 | m_ram_page[(bit-4)/5] &= ~(1 << ((bit-9)%5)); |
| 355 | |
| 356 | if (TRACE_CRU) |
| 357 | { |
| 358 | if (bit==0x0d) logerror("%s: RAM page @5400 = %d\n", tag(), m_ram_page[1]); |
| 359 | if (bit==0x12) logerror("%s: RAM page @5800 = %d\n", tag(), m_ram_page[2]); |
| 360 | if (bit==0x17) logerror("%s: RAM page @5C00 = %d\n", tag(), m_ram_page[3]); |
| 361 | } |
| 355 | 362 | return; |
| 356 | 363 | } |
| 357 | 364 | |
| 358 | 365 | switch (bit) |
| 359 | 366 | { |
| 360 | 367 | case 0: |
| 361 | | m_selected = (data!=0); |
| 362 | | if (TRACE_CRU) logerror("%s: selected = %d\n", tag(), m_selected); |
| 363 | | break; |
| 364 | | |
| 368 | { |
| 369 | bool turnOn = (data!=0); |
| 370 | // Avoid too many meaningless log outputs |
| 371 | if (TRACE_CRU) if (m_selected != turnOn) logerror("%s: card %s\n", tag(), turnOn? "selected" : "unselected"); |
| 372 | m_selected = turnOn; |
| 373 | break; |
| 374 | } |
| 365 | 375 | case 1: |
| 366 | 376 | if (TRACE_CRU) if (data==0) logerror("%s: trigger HDC reset\n", tag()); |
| 367 | 377 | m_hdc9234->reset((data == 0)? ASSERT_LINE : CLEAR_LINE); |
| r31134 | r31135 | |
| 382 | 392 | case 3: |
| 383 | 393 | m_CD = (data != 0)? (m_CD | 2) : (m_CD & 0xfd); |
| 384 | 394 | m_rom_page = (data != 0)? (m_rom_page | 2) : (m_rom_page & 0xfd); |
| 395 | if (TRACE_CRU) logerror("%s: ROM page = %d, CD = %d\n", tag(), m_rom_page, m_CD); |
| 385 | 396 | break; |
| 386 | 397 | |
| 387 | 398 | case 4: |
| 388 | 399 | m_see_switches = (data != 0); |
| 389 | 400 | m_rom_page = (data != 0)? (m_rom_page | 1) : (m_rom_page & 0xfe); |
| 401 | if (TRACE_CRU) logerror("%s: ROM page = %d, see_switches = %d\n", tag(), m_rom_page, m_see_switches); |
| 390 | 402 | break; |
| 391 | 403 | |
| 392 | 404 | default: |
| r31134 | r31135 | |
| 411 | 423 | logerror("%s: Index callback level=%d\n", tag(), state); |
| 412 | 424 | // m_status_latch = (state==ASSERT_LINE)? (m_status_latch | HDC_DS_INDEX) : (m_status_latch & ~HDC_DS_INDEX); |
| 413 | 425 | set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE)); |
| 426 | signal_drive_status(); |
| 414 | 427 | } |
| 415 | 428 | |
| 416 | 429 | void myarc_hfdc_device::set_bits(UINT8& byte, int mask, bool set) |
| r31134 | r31135 | |
| 435 | 448 | } |
| 436 | 449 | |
| 437 | 450 | /* |
| 438 | | Read the selected latch via the auxbus. This is always the status register. |
| 451 | Notify the controller about the status change |
| 439 | 452 | */ |
| 440 | | READ8_MEMBER( myarc_hfdc_device::auxbus_in ) |
| 453 | void myarc_hfdc_device::signal_drive_status() |
| 441 | 454 | { |
| 442 | | //UINT8 reply = 0; |
| 455 | UINT8 reply = 0; |
| 443 | 456 | //int index = 0; |
| 444 | 457 | |
| 445 | | if ((m_output1_latch & 0xf0)==0) |
| 446 | | { |
| 447 | | logerror("%s: no drive selected, returning 0\n", tag()); |
| 448 | | // No HD and no floppy |
| 449 | | return 0; /* is that the correct default value? */ |
| 450 | | } |
| 458 | // Status byte as defined by HDC9234 |
| 459 | // +------+------+------+------+------+------+------+------+ |
| 460 | // | ECC |Index | SeekC| Tr00 | User | WrPrt| Ready|Fault | |
| 461 | // +------+------+------+------+------+------+------+------+ |
| 462 | // |
| 463 | // Set by HFDC |
| 464 | // 74LS240 is used for driving the lines; it also inverts the inputs |
| 465 | // If no hard drive or floppy is connected, all lines are 0 |
| 466 | // +------+------+------+------+------+------+------+------+ |
| 467 | // | 0 | Index| SeekC| Tr00 | 0 | WrPrt| Ready|Fault | |
| 468 | // +------+------+------+------+------+------+------+------+ |
| 469 | // |
| 470 | // Ready = WDS.ready | DSK |
| 471 | // SeekComplete = WDS.seekComplete | DSK |
| 451 | 472 | |
| 452 | | return m_status_latch; |
| 473 | // If DSK is selected, set Ready and SeekComplete to 1 |
| 474 | // If WDS is selected but not connected, Ready and SeekComplete are 1 |
| 475 | if ((m_output1_latch & 0x10)!=0) reply |= 0x22; |
| 476 | |
| 477 | reply |= m_status_latch; |
| 478 | |
| 479 | m_hdc9234->auxbus_in(reply); |
| 453 | 480 | } |
| 454 | 481 | |
| 455 | | |
| 456 | 482 | /* |
| 457 | 483 | When the HDC outputs a byte via its AB (auxiliary bus), we need to latch it. |
| 458 | 484 | The target of the transfer is determined by two control lines (S1,S0). |
| r31134 | r31135 | |
| 463 | 489 | */ |
| 464 | 490 | WRITE8_MEMBER( myarc_hfdc_device::auxbus_out ) |
| 465 | 491 | { |
| 466 | | //int index; |
| 492 | int index; |
| 467 | 493 | switch (offset) |
| 468 | 494 | { |
| 469 | 495 | case HDC_INPUT_STATUS: |
| r31134 | r31135 | |
| 496 | 522 | else |
| 497 | 523 | { |
| 498 | 524 | // HD selected |
| 499 | | // index = slog2((data>>4) & 0x0f); |
| 500 | | // if (index>=0) m_hdc9234->connect_hard_drive(m_harddisk_unit[index-1]); |
| 501 | | set_bits(m_status_latch, HDC_DS_READY, false); |
| 525 | index = slog2((data>>4) & 0x0f); |
| 526 | if (index == -1) |
| 527 | { |
| 528 | logerror("%s: Unselect all drives\n", tag()); |
| 529 | } |
| 530 | else |
| 531 | { |
| 532 | logerror("%s: Select hard disk WDS%d\n", tag(), index); |
| 533 | // if (index>=0) m_hdc9234->connect_hard_drive(m_harddisk_unit[index-1]); |
| 534 | } |
| 535 | if (m_current_harddisk==NULL) |
| 536 | { |
| 537 | set_bits(m_status_latch, HDC_DS_READY | HDC_DS_SKCOM, true); |
| 538 | } |
| 502 | 539 | } |
| 503 | 540 | break; |
| 504 | 541 | |
| 505 | 542 | case HDC_OUTPUT_2: |
| 506 | 543 | // value is output2 |
| 544 | // DS3* = /WDS3 |
| 545 | // WCur = Reduced Write Current |
| 546 | // Dir = Step direction |
| 547 | // Step = Step pulse |
| 548 | // Head = Selected head number (floppy: 0000 or 0001) |
| 549 | // +------+------+------+------+------+------+------+------+ |
| 550 | // | DS3* | WCur | Dir | Step | Head | |
| 551 | // +------+------+------+------+------+------+------+------+ |
| 507 | 552 | logerror("%s: Setting OUTPUT2 latch to %02x\n", tag(), data); |
| 508 | 553 | m_output2_latch = data; |
| 554 | |
| 555 | // Output the step pulse to the selected floppy drive |
| 556 | if (m_current_floppy != NULL) |
| 557 | { |
| 558 | m_current_floppy->dir_w((data & 0x20)==0); |
| 559 | m_current_floppy->stp_w(0); |
| 560 | m_current_floppy->stp_w(1); |
| 561 | } |
| 562 | |
| 509 | 563 | break; |
| 510 | 564 | } |
| 565 | |
| 566 | // We are pushing the drive status after every output |
| 567 | signal_drive_status(); |
| 511 | 568 | } |
| 512 | 569 | |
| 513 | 570 | enum |
| r31134 | r31135 | |
| 523 | 580 | { |
| 524 | 581 | if (m_floppy_unit[index] != m_current_floppy) |
| 525 | 582 | { |
| 526 | | logerror("%s: Connect floppy drive %d\n", tag(), index); |
| 583 | logerror("%s: Select floppy drive DSK%d\n", tag(), index); |
| 527 | 584 | if (m_current_floppy != NULL) |
| 528 | 585 | { |
| 529 | 586 | // Disconnect old drive from index line |
| r31134 | r31135 | |
| 539 | 596 | } |
| 540 | 597 | m_hdc9234->connect_floppy_drive(m_floppy_unit[index]); |
| 541 | 598 | } |
| 542 | | set_ready(HFDC_FLOPPY, true); |
| 543 | 599 | } |
| 544 | 600 | else |
| 545 | 601 | { |
| 546 | | logerror("%s: Disconnect all floppy drives\n", tag()); |
| 602 | logerror("%s: Unselect all floppy drives\n", tag()); |
| 547 | 603 | // Disconnect current floppy |
| 548 | 604 | if (m_current_floppy != NULL) |
| 549 | 605 | { |
| 550 | 606 | m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb()); |
| 551 | 607 | m_current_floppy = NULL; |
| 552 | 608 | } |
| 553 | | set_ready(HFDC_FLOPPY, false); |
| 554 | 609 | } |
| 610 | signal_drive_status(); |
| 555 | 611 | } |
| 556 | 612 | |
| 557 | 613 | void myarc_hfdc_device::connect_harddisk_unit(int index) |
| 558 | 614 | { |
| 559 | | set_ready(HFDC_HARDDISK, false); |
| 615 | // if (index < 0) |
| 616 | // { |
| 617 | m_current_harddisk = NULL; |
| 618 | // } |
| 619 | signal_drive_status(); |
| 560 | 620 | } |
| 561 | 621 | |
| 562 | 622 | /* |
| 563 | | Joins the ready lines from the floppy drives and the hard drives |
| 564 | | */ |
| 565 | | void myarc_hfdc_device::set_ready(int dev, bool ready) |
| 566 | | { |
| 567 | | m_readyflags = ready? (m_readyflags | dev) : (m_readyflags & ~dev); |
| 568 | | set_bits(m_status_latch, HDC_DS_READY, (m_readyflags != 0)); |
| 569 | | } |
| 570 | | |
| 571 | | /* |
| 572 | 623 | All floppy motors are operated by the same line. |
| 573 | 624 | */ |
| 574 | 625 | void myarc_hfdc_device::set_floppy_motors_running(bool run) |
| r31134 | r31135 | |
| 638 | 689 | m_buffer_ram = memregion(BUFFER)->base(); |
| 639 | 690 | m_motor_on_timer = timer_alloc(MOTOR_TIMER); |
| 640 | 691 | // The HFDC does not use READY; it has on-board RAM for DMA |
| 692 | m_current_floppy = NULL; |
| 641 | 693 | } |
| 642 | 694 | |
| 643 | 695 | void myarc_hfdc_device::device_reset() |
| r31134 | r31135 | |
| 665 | 717 | for (int i=1; i < 4; i++) m_ram_page[i] = 0; |
| 666 | 718 | |
| 667 | 719 | m_output1_latch = m_output2_latch = 0; |
| 720 | |
| 721 | m_status_latch = 0x00; |
| 722 | |
| 668 | 723 | m_dip = m_irq = CLEAR_LINE; |
| 669 | 724 | m_see_switches = false; |
| 670 | 725 | m_CD = 0; |
| r31134 | r31135 | |
| 742 | 797 | MCFG_HDC9234_INTRQ_CALLBACK(WRITELINE(myarc_hfdc_device, intrq_w)) |
| 743 | 798 | MCFG_HDC9234_DIP_CALLBACK(WRITELINE(myarc_hfdc_device, dip_w)) |
| 744 | 799 | MCFG_HDC9234_AUXBUS_OUT_CALLBACK(WRITE8(myarc_hfdc_device, auxbus_out)) |
| 745 | | MCFG_HDC9234_AUXBUS_IN_CALLBACK(READ8(myarc_hfdc_device, auxbus_in)) |
| 746 | 800 | MCFG_HDC9234_DMA_IN_CALLBACK(READ8(myarc_hfdc_device, read_buffer)) |
| 747 | 801 | MCFG_HDC9234_DMA_OUT_CALLBACK(WRITE8(myarc_hfdc_device, write_buffer)) |
| 748 | 802 | |