Пример #1
0
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;
}
Пример #2
0
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);
    }
}
Пример #3
0
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;
}
Пример #4
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);
    }
}
Пример #5
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);
}
Пример #6
0
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;
    }
}
Пример #7
0
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;
    }
}