int drive_check_type(unsigned int drive_type, unsigned int dnr) { if (!drive_check_bus(drive_type, iec_available_busses())) return 0; if (drive_check_dual(drive_type)) { if (is_drive1(dnr)) { /* Dual drives only supported on even device numbers. */ return 0; } else { if (drive_context[mk_drive1(dnr)]->drive->type != DRIVE_TYPE_NONE) /* Disable dual drive if second device is enabled. */ return 0; } } else { if (is_drive1(dnr)) { if (drive_check_dual(drive_context[mk_drive0(dnr)]->drive->type)) /* Disable second device if dual drive is enabled. */ return drive_type == DRIVE_TYPE_NONE; } } if (machine_drive_rom_check_loaded(drive_type) < 0) return 0; return 1; }
void fdc_reset(unsigned int fnum, unsigned int drive_type) { fdc_t *thefdc = &fdc[fnum]; int drive1 = mk_drive1(fnum); disk_image_t *saved_image0, *saved_image1; #ifdef FDC_DEBUG log_message(fdc_log, "fdc_reset: drive %d type=%d\n",fnum, drive_type); #endif saved_image0 = fdc[fnum].realimage; saved_image1 = NULL; /* detach disk images */ if (thefdc->image) { thefdc->wps_change = 0; fdc_detach_image(thefdc->image, fnum + 8); } if (thefdc->num_drives == 2) { saved_image1 = fdc[drive1].realimage; if (fdc[drive1].image) { fdc[drive1].wps_change = 0; fdc_detach_image(fdc[drive1].image, drive1 + 8); } } if (drive_check_old(drive_type)) { thefdc->drive_type = drive_type; thefdc->num_drives = is_drive1(fnum) ? 1 : drive_check_dual(drive_type) ? 2 : 1; thefdc->fdc_state = FDC_RESET0; alarm_set(thefdc->fdc_alarm, drive_clk[fnum] + 20); } else { thefdc->drive_type = DRIVE_TYPE_NONE; alarm_unset(thefdc->fdc_alarm); thefdc->fdc_state = FDC_UNUSED; thefdc->num_drives = 0; } /* re-attach disk images */ if (saved_image0) { #ifdef FDC_DEBUG printf("ieee/fdc.c:fdc_reset dev %d type %d drive 0 re-attach image %p (drive: %p)\n", fnum+8, drive_type, saved_image0, drive_context[fnum]->drive->image); #endif fdc_attach_image(saved_image0, fnum + 8); } if (saved_image1) { #ifdef FDC_DEBUG printf("ieee/fdc.c:fdc_reset dev %d type %d drive 1 re-attach image %p (drive: %p)\n", fnum+8, drive_type, saved_image0, drive_context[drive1]->drive->image); #endif fdc_attach_image(saved_image1, drive1 + 8); } }
int drive_set_disk_drive_type(unsigned int type, struct drive_context_s *drv) { unsigned int dnr; drive_t *drive; drive_t *drive1; dnr = drv->mynumber; if (machine_drive_rom_check_loaded(type) < 0) { return -1; } drive = drv->drive; rotation_rotate_disk(drive); drivesync_clock_frequency(type, drive); rotation_init(0, dnr); drive->type = type; if (type == DRIVE_TYPE_2000 || type == DRIVE_TYPE_4000) { drivecpu65c02_setup_context(drv, 0); } else { drivecpu_setup_context(drv, 0); } drive->side = 0; machine_drive_rom_setup_image(dnr); drivesync_factor(drv); drive_set_active_led_color(type, dnr); /* set up (relatively) easy detection of dual drives */ drive1 = drive_context[mk_drive1(dnr)]->drive; drive->drive0 = NULL; drive1->drive1 = NULL; if (is_drive0(dnr) && drive_check_dual(type)) { drive->drive1 = drive1; drive1->drive0 = drive; } else { drive->drive1 = NULL; drive1->drive0 = NULL; } if (type == DRIVE_TYPE_2000 || type == DRIVE_TYPE_4000) { drivecpu65c02_init(drv, type); } else { drivecpu_init(drv, type); } return 0; }
static void store_prb(riot_context_t *riot_context, BYTE byte) { driveriot2_context_t *riot2p; riot2p = (driveriot2_context_t *)(riot_context->prv); /* bit 3 Act LED 1 */ /* bit 4 Act LED 0 */ /* bit 5 Error LED */ /* 1001 only needs LED 0 and Error LED */ riot2p->drive->led_status = (byte >> 4) & 0x03; if ((is_drive0(riot2p->number)) && (drive_check_dual(riot2p->drive->type))) { drive_context[mk_drive1(riot2p->number)]->drive->led_status = ((byte & 8) ? 1 : 0) | ((byte & 32) ? 2 : 0); } }
static void undump_prb(riot_context_t *riot_context, BYTE byte) { driveriot2_context_t *riot2p; riot2p = (driveriot2_context_t *)(riot_context->prv); /* bit 3 Act LED 1 */ /* bit 4 Act LED 0 */ /* bit 5 Error LED */ /* 1001 only needs LED 0 and Error LED */ riot2p->drive->led_status = (byte >> 4) & 0x03; if ((is_drive0(riot2p->number)) && (drive_check_dual(riot2p->drive->type))) { drive_context[mk_drive1(riot2p->number)]->drive->led_status = ((byte & 8) ? 1 : 0) | ((byte & 32) ? 2 : 0); } if (riot2p->drive->led_status & 1) { riot2p->drive->led_active_ticks += *(riot_context->clk_ptr) - riot2p->drive->led_last_change_clk; } riot2p->drive->led_last_change_clk = *(riot_context->clk_ptr); }
static int drive_resources_type(int val, void *param) { unsigned int type, dnr; int busses; drive_t *drive, *drive0; dnr = vice_ptr_to_uint(param); drive = drive_context[dnr]->drive; type = (unsigned int)val; busses = iec_available_busses(); /* if bus for drive type is not allowed, set to default value for bus */ if (!drive_check_bus(type, busses)) { if (busses & IEC_BUS_IEC) { type = DRIVE_TYPE_1541; } else if (busses & IEC_BUS_IEEE) { type = DRIVE_TYPE_2031; } else { type = DRIVE_TYPE_NONE; } } if (is_drive0(dnr)) { if (drive_check_dual(type)) { int drive1 = mk_drive1(dnr); /* dual disk drives disable second emulated unit */ log_warning(drive->log, "Dual disk drive %d disables emulated drive %d", dnr, drive1); drive_resources_type(DRIVE_TYPE_NONE, int_to_void_ptr(drive1)); } } else { drive0 = drive_context[mk_drive0(dnr)]->drive; if (drive0->enable && drive_check_dual(drive0->type)) { /* dual disk drives disable second emulated unit */ log_warning(drive->log, "Dual disk drive %d disables emulated drive %d", mk_drive0(dnr), dnr); type = DRIVE_TYPE_NONE; } } switch (type) { case DRIVE_TYPE_1541: case DRIVE_TYPE_1541II: case DRIVE_TYPE_1551: case DRIVE_TYPE_1570: case DRIVE_TYPE_1571: case DRIVE_TYPE_1571CR: case DRIVE_TYPE_1581: case DRIVE_TYPE_2000: case DRIVE_TYPE_4000: case DRIVE_TYPE_2031: case DRIVE_TYPE_1001: case DRIVE_TYPE_2040: case DRIVE_TYPE_3040: case DRIVE_TYPE_4040: case DRIVE_TYPE_8050: case DRIVE_TYPE_8250: if (drive->type != type) { drive->current_half_track = 2 * 18; if ((type == DRIVE_TYPE_1001) || (type == DRIVE_TYPE_8050) || (type == DRIVE_TYPE_8250)) { drive->current_half_track = 2 * 38; } } drive->type = type; if (drive_true_emulation) { drive->enable = 1; drive_enable(drive_context[dnr]); /* 1551 drive does not use the IEC bus */ machine_bus_status_drivetype_set(dnr + 8, drive_check_bus(type, IEC_BUS_IEC)); } else { drive_enable_update_ui(drive_context[dnr]); } drive_set_disk_drive_type(type, drive_context[dnr]); driverom_initialize_traps(drive); machine_drive_idling_method(dnr); return 0; case DRIVE_TYPE_NONE: drive->type = type; drive_disable(drive_context[dnr]); machine_bus_status_drivetype_set(dnr + 8, 0); return 0; default: return -1; } }
static void int_fdc(CLOCK offset, void *data) { CLOCK rclk; int i, j; drive_t *drive; unsigned int fnum; drive_context_t *drv = (drive_context_t *)data; fnum = drv->mynumber; rclk = drive_clk[fnum] - offset; #ifdef FDC_DEBUG if (fdc[fnum].fdc_state < FDC_RUN) { static int old_state[NUM_FDC] = { -1, -1 }; if (fdc[fnum].fdc_state != old_state[fnum]) log_message(fdc_log, "int_fdc%d %d: state=%d\n", fnum, rclk, fdc[fnum].fdc_state); old_state[fnum] = fdc[fnum].fdc_state; } #endif switch(fdc[fnum].fdc_state) { case FDC_RESET0: drive = drive_context[fnum]->drive; if (DOS_IS_80(fdc[fnum].drive_type)) { drive->current_half_track = 2 * 38; fdc[fnum].buffer[0] = 2; } else { drive->current_half_track = 2 * 18; fdc[fnum].buffer[0] = 0x3f; } if (DOS_IS_20(fdc[fnum].drive_type)) { fdc[fnum].fdc_state = FDC_RUN; } else { fdc[fnum].fdc_state++; } fdc[fnum].alarm_clk = rclk + 2000; alarm_set(fdc[fnum].fdc_alarm, fdc[fnum].alarm_clk); break; case FDC_RESET1: if (DOS_IS_80(fdc[fnum].drive_type)) { if (fdc[fnum].buffer[0] == 0) { fdc[fnum].buffer[0] = 1; fdc[fnum].fdc_state++; } } else { if (fdc[fnum].buffer[3] == 0xd0) { fdc[fnum].buffer[3] = 0; fdc[fnum].fdc_state++; } } fdc[fnum].alarm_clk = rclk + 2000; alarm_set(fdc[fnum].fdc_alarm, fdc[fnum].alarm_clk); break; case FDC_RESET2: if (DOS_IS_80(fdc[fnum].drive_type)) { if (fdc[fnum].buffer[0] == 0) { /* emulate routine written to buffer RAM */ fdc[fnum].buffer[1] = 0x0e; fdc[fnum].buffer[2] = 0x2d; /* number of sides on disk drive */ fdc[fnum].buffer[0xac] = (fdc[fnum].drive_type == DRIVE_TYPE_8050) ? 1 : 2; /* 0 = 4040 (2A), 1 = 8x80 (2C) drive type */ fdc[fnum].buffer[0xea] = 1; fdc[fnum].buffer[0xee] = 5; /* 3 for 4040, 5 for 8x50 */ fdc[fnum].buffer[0] = 3; /* 5 for 4040, 3 for 8x50 */ fdc[fnum].fdc_state = FDC_RUN; fdc[fnum].alarm_clk = rclk + 10000; } else { fdc[fnum].alarm_clk = rclk + 2000; } } else if (DOS_IS_40(fdc[fnum].drive_type) || DOS_IS_30(fdc[fnum].drive_type) ) { if (fdc[fnum].buffer[0] == 0) { fdc[fnum].buffer[0] = 0x0f; fdc[fnum].fdc_state = FDC_RUN; fdc[fnum].alarm_clk = rclk + 10000; } else { fdc[fnum].alarm_clk = rclk + 2000; } } alarm_set(fdc[fnum].fdc_alarm, fdc[fnum].alarm_clk); break; case FDC_RUN: /* check write protect switch */ if (fdc[fnum].wps_change) { fdc[fnum].buffer[0xA6] = 1; fdc[fnum].wps_change--; #ifdef FDC_DEBUG log_message(fdc_log, "Detect Unit %d Drive %d wps change", fnum + 8, fnum); #endif } if (fdc[fnum].num_drives == 2) { if (fdc[mk_drive1(fnum)].wps_change) { fdc[fnum].buffer[0xA6 + 1] = 1; fdc[mk_drive1(fnum)].wps_change--; #ifdef FDC_DEBUG log_message(fdc_log, "Detect Unit %d Drive 1 wps change", fnum + 8); #endif } } /* check buffers */ for (i=14; i >= 0; i--) { /* job there? */ if (fdc[fnum].buffer[i + 3] > 127) { /* pointer to buffer/block header: +0 = ID1 +1 = ID2 +2 = Track +3 = Sector */ j = 0x21 + (i << 3); #ifdef FDC_DEBUG log_message(fdc_log, "D/Buf %d/%x: Job code %02x t:%02d s:%02d", fnum, i, fdc[fnum].buffer[i+3], fdc[fnum].buffer[j+2],fdc[fnum].buffer[j+3]); #endif fdc[fnum].buffer[i + 3] = fdc_do_job(fnum, /* FDC# */ i, /* buffer# */ (unsigned int)fdc[fnum].buffer[i+3] & 1, /* drive */ (BYTE)(fdc[fnum].buffer[i+3] & 0xfe), /* job code */ &(fdc[fnum].buffer[j]) /* header */ ); } } /* check "move head", by half tracks I guess... */ for (i = 0; i < 2; i++) { if (fdc[fnum].buffer[i + 0xa1]) { #ifdef FDC_DEBUG log_message(fdc_log, "D %d: move head %d", fnum, fdc[fnum].buffer[i + 0xa1]); #endif fdc[fnum].buffer[i + 0xa1] = 0; } } fdc[fnum].alarm_clk = rclk + 30000; alarm_set(fdc[fnum].fdc_alarm, fdc[fnum].alarm_clk); /* job loop */ break; } }