Esempio n. 1
0
File: mfdc.c Progetto: ProtoSD/simh
/* Attach routine */
t_stat mfdc_attach(UNIT *uptr, char *cptr)
{
    t_stat r;
    unsigned int i = 0;

    r = attach_unit(uptr, cptr);    /* attach unit  */
    if ( r != SCPE_OK)              /* error?       */
        return r;

    /* Determine length of this disk */
    if(sim_fsize(uptr->fileref) != 0) {
        uptr->capac = sim_fsize(uptr->fileref);
    } else {
        uptr->capac = MFDC_CAPACITY;
    }

    i = find_unit_index(uptr);

    /* Default for new file is DSK */
    uptr->u3 = IMAGE_TYPE_DSK;

    if(uptr->capac > 0) {
        r = assignDiskType(uptr);
        if (r != SCPE_OK) {
            mfdc_detach(uptr);
            return r;
        }
    }

    if (uptr->flags & UNIT_MFDC_VERBOSE)
        printf("MDSK%d, attached to '%s', type=%s, len=%d\n", i, cptr,
            uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",
            uptr->capac);

    if(uptr->u3 == IMAGE_TYPE_IMD) {
        if(uptr->capac < 318000) {
            printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n");
            mfdc_detach(uptr);
            return SCPE_OPENERR;
        }

        if (uptr->flags & UNIT_MFDC_VERBOSE)
            printf("--------------------------------------------------------\n");
        mfdc_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_MFDC_VERBOSE));
        if (uptr->flags & UNIT_MFDC_VERBOSE)
            printf("\n");
    } else {
        mfdc_info->drive[i].imd = NULL;
    }

    return SCPE_OK;
}
Esempio n. 2
0
/* Attach routine */
static t_stat mdsad_attach(UNIT *uptr, CONST char *cptr)
{
    char header[4];
    t_stat r;
    unsigned int i = 0;

    r = attach_unit(uptr, cptr);    /* attach unit  */
    if(r != SCPE_OK)                /* error?       */
        return r;

    /* Determine length of this disk */
    if(sim_fsize(uptr->fileref) != 0) {
        uptr->capac = sim_fsize(uptr->fileref);
    } else {
        uptr->capac = MDSAD_CAPACITY;
    }

    for(i = 0; i < MDSAD_MAX_DRIVES; i++) {
        mdsad_info->drive[i].uptr = &mdsad_dev.units[i];
    }

    for(i = 0; i < MDSAD_MAX_DRIVES; i++) {
        if(mdsad_dev.units[i].fileref == uptr->fileref) {
            break;
        }

    mdsad_info->orders.st = 0;      /* ensure valid state */
    }

    /* Default for new file is DSK */
    uptr->u3 = IMAGE_TYPE_DSK;

    if(uptr->capac > 0) {
        char *rtn = fgets(header, 4, uptr->fileref);
        if((rtn != NULL) && (strncmp(header, "CPT", 3) == 0)) {
            sim_printf("CPT images not yet supported\n");
            uptr->u3 = IMAGE_TYPE_CPT;
            mdsad_detach(uptr);
            return SCPE_OPENERR;
        } else {
            uptr->u3 = IMAGE_TYPE_DSK;
        }
    }

    if (uptr->flags & UNIT_MDSAD_VERBOSE)
        sim_printf("MDSAD%d, attached to '%s', type=%s, len=%d\n", i, cptr,
            uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",
            uptr->capac);

    return SCPE_OK;
}
Esempio n. 3
0
uint32 sim_fsize_name (char *fname)
{
FILE *fp;
uint32 sz;

if ((fp = sim_fopen (fname, "rb")) == NULL) return 0;
sz = sim_fsize (fp);
fclose (fp);
return sz;
}
Esempio n. 4
0
/* Attach routine */
static t_stat disk3_attach(UNIT *uptr, char *cptr)
{
    t_stat r = SCPE_OK;
    DISK3_DRIVE_INFO *pDrive;
    int i = 0;

    i = find_unit_index(uptr);
    if (i == -1) {
        return (SCPE_IERR);
    }
    pDrive = &disk3_info->drive[i];

    pDrive->ready = 1;
    pDrive->track = 5;
    pDrive->ntracks = C20MB_NTRACKS;
    pDrive->nheads = C20MB_NHEADS;
    pDrive->nsectors = C20MB_NSECTORS;
    pDrive->sectsize = C20MB_SECTSIZE;

    r = attach_unit(uptr, cptr);    /* attach unit  */
    if ( r != SCPE_OK)              /* error?       */
        return r;

    /* Determine length of this disk */
    if(sim_fsize(uptr->fileref) != 0) {
        uptr->capac = sim_fsize(uptr->fileref);
    } else {
        uptr->capac = (pDrive->ntracks * pDrive->nsectors * pDrive->nheads * pDrive->sectsize);
    }

    pDrive->uptr = uptr;

    /* Default for new file is DSK */
    uptr->u3 = IMAGE_TYPE_DSK;

    if(uptr->capac > 0) {
        r = assignDiskType(uptr);
        if (r != SCPE_OK) {
            disk3_detach(uptr);
            return r;
        }
    }

    if (uptr->flags & UNIT_DISK3_VERBOSE)
        printf("DISK3%d, attached to '%s', type=%s, len=%d\n", i, cptr,
            uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",
            uptr->capac);

    if(uptr->u3 == IMAGE_TYPE_IMD) {
        if(uptr->capac < 318000) {
            printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n");
            disk3_detach(uptr);
            return SCPE_OPENERR;
        }

        if (uptr->flags & UNIT_DISK3_VERBOSE)
            printf("--------------------------------------------------------\n");
        disk3_info->drive[i].imd = diskOpenEx((uptr->fileref), (uptr->flags & UNIT_DISK3_VERBOSE),
                                              &disk3_dev, VERBOSE_MSG, VERBOSE_MSG);
        if (uptr->flags & UNIT_DISK3_VERBOSE)
            printf("\n");
    } else {
        disk3_info->drive[i].imd = NULL;
    }

    return SCPE_OK;
}
Esempio n. 5
0
/* Attach routine */
static t_stat hdc1001_attach(UNIT *uptr, char *cptr)
{
    t_stat r = SCPE_OK;
    HDC1001_DRIVE_INFO *pDrive;
    char header[4];
    unsigned int i = 0;

    i = find_unit_index(uptr);
    if (i == -1) {
        return (SCPE_IERR);
    }
    pDrive = &hdc1001_info->drive[i];

    pDrive->ready = 1;
    pDrive->track = 5;
    pDrive->ntracks = 243;
    pDrive->nheads = 8;
    pDrive->nsectors = 11;
    pDrive->sectsize = 1024;

    r = attach_unit(uptr, cptr);    /* attach unit  */
    if ( r != SCPE_OK)              /* error?       */
        return r;

    /* Determine length of this disk */
    if(sim_fsize(uptr->fileref) != 0) {
        uptr->capac = sim_fsize(uptr->fileref);
    } else {
        uptr->capac = (pDrive->ntracks * pDrive->nsectors * pDrive->nheads * pDrive->sectsize);
    }

    pDrive->uptr = uptr;

    /* Default for new file is DSK */
    uptr->u3 = IMAGE_TYPE_DSK;

    if(uptr->capac > 0) {
        fgets(header, 4, uptr->fileref);
        if(!strcmp(header, "IMD")) {
            uptr->u3 = IMAGE_TYPE_IMD;
        } else if(!strcmp(header, "CPT")) {
            printf("CPT images not yet supported\n");
            uptr->u3 = IMAGE_TYPE_CPT;
            hdc1001_detach(uptr);
            return SCPE_OPENERR;
        } else {
            uptr->u3 = IMAGE_TYPE_DSK;
        }
    }

    if (uptr->flags & UNIT_HDC1001_VERBOSE)
        printf("HDC1001%d, attached to '%s', type=%s, len=%d\n", i, cptr,
            uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",
            uptr->capac);

    if(uptr->u3 == IMAGE_TYPE_IMD) {
        if(uptr->capac < 318000) {
            printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n");
            hdc1001_detach(uptr);
            return SCPE_OPENERR;
        }

        if (uptr->flags & UNIT_HDC1001_VERBOSE)
            printf("--------------------------------------------------------\n");
        hdc1001_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_HDC1001_VERBOSE));
        if (uptr->flags & UNIT_HDC1001_VERBOSE)
            printf("\n");
    } else {
        hdc1001_info->drive[i].imd = NULL;
    }

    return SCPE_OK;
}
Esempio n. 6
0
uint8 I8272_Write(const uint32 Addr, uint8 cData)
{
    I8272_DRIVE_INFO    *pDrive;
    uint32 flags = 0;
    uint32 readlen;
    uint8   disk_read = 0;
    int32 i;

    pDrive = &i8272_info->drive[i8272_info->sel_drive];

    if(pDrive->uptr == NULL) {
        return 0xFF;
    }

    switch(Addr & 0x3) {
        case I8272_FDC_MSR:
            sim_debug(WR_DATA_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                      " WR Drive Select Reg=%02x\n", PCX, cData);
            break;
        case I8272_FDC_DATA:
            i8272_info->fdc_msr &= 0xF0;
            sim_debug(VERBOSE_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                      " WR Data, phase=%d, index=%d\n",
                      PCX, i8272_info->fdc_phase, i8272_info->cmd_index);
            if(i8272_info->fdc_phase == CMD_PHASE) {
                i8272_info->cmd[i8272_info->cmd_index] = cData;

                if(i8272_info->cmd_index == 0) {
                    sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                              " CMD=0x%02x[%s]\n", PCX, cData & 0x1F, messages[cData & 0x1F]);
                    I8272_Setup_Cmd(cData & 0x1F);
                }
                i8272_info->cmd_index ++;

                if(i8272_info->cmd_len == i8272_info->cmd_index) {
                    i8272_info->cmd_index = 0;
                    i8272_info->fdc_phase = EXEC_PHASE;
                }
            }

            if(i8272_info->fdc_phase == EXEC_PHASE) {
                switch(i8272_info->cmd[0] & 0x1F) {
                    case I8272_READ_DATA:
                    case I8272_WRITE_DATA:
                    case I8272_READ_DELETED_DATA:
                    case I8272_WRITE_DELETED_DATA:
                    case I8272_READ_TRACK:
                    case I8272_SCAN_LOW_EQUAL:
                    case I8272_SCAN_HIGH_EQUAL:
                    case I8272_SCAN_EQUAL:
                        i8272_info->fdc_mt = (i8272_info->cmd[0] & 0x80) >> 7;
                        i8272_info->fdc_mfm = (i8272_info->cmd[0] & 0x40) >> 6;
                        i8272_info->fdc_sk = (i8272_info->cmd[0] & 0x20) >> 5;
                        i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2;
                        i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03);
                        pDrive = &i8272_info->drive[i8272_info->sel_drive];
                        if(pDrive->uptr == NULL) {
                            return 0xFF;
                        }

                        if(pDrive->track != i8272_info->cmd[2]) {
                            i8272_info->fdc_seek_end = 1;
                        } else {
                            i8272_info->fdc_seek_end = 0;
                        }
                        if(pDrive->track != i8272_info->cmd[2]) {
                            sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                      " ERROR: CMD=0x%02x[%s]: Drive: %d, Command wants track %d, "
                                      "but positioner is on track %d.\n",
                                      PCX, i8272_info->cmd[0] & 0x1F,
                                      messages[i8272_info->cmd[0] & 0x1F],
                                      i8272_info->sel_drive, i8272_info->cmd[2], pDrive->track);
                        }

                        pDrive->track = i8272_info->cmd[2];
                        i8272_info->fdc_head = i8272_info->cmd[3] & 1; /* AGN mask to head 0 or 1 */
                        i8272_info->fdc_sector = i8272_info->cmd[4];
                        i8272_info->fdc_sec_len = i8272_info->cmd[5];
                        if(i8272_info->fdc_sec_len > I8272_MAX_N) {
                            sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                      " Illegal sector size %d [N=%d]. Reset to %d [N=%d].\n",
                                      PCX, 128 << i8272_info->fdc_sec_len,
                                      i8272_info->fdc_sec_len, 128 << I8272_MAX_N, I8272_MAX_N);
                            i8272_info->fdc_sec_len = I8272_MAX_N;
                        }
                        i8272_info->fdc_eot = i8272_info->cmd[6];
                        i8272_info->fdc_gpl = i8272_info->cmd[7];
                        i8272_info->fdc_dtl = i8272_info->cmd[8];

                        sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                  " CMD=0x%02x[%s]: Drive: %d, %s %s, C=%d. H=%d. S=%d, N=%d, "
                                  "EOT=%02x, GPL=%02x, DTL=%02x\n", PCX,
                                  i8272_info->cmd[0] & 0x1F,
                                  messages[i8272_info->cmd[0] & 0x1F],
                                  i8272_info->sel_drive,
                                  i8272_info->fdc_mt ? "Multi" : "Single",
                                  i8272_info->fdc_mfm ? "MFM" : "FM",
                                  pDrive->track,
                                  i8272_info->fdc_head,
                                  i8272_info->fdc_sector,
                                  i8272_info->fdc_sec_len,
                                  i8272_info->fdc_eot,
                                  i8272_info->fdc_gpl,
                                  i8272_info->fdc_dtl);

                        i8272_info->fdc_status[0]  = (i8272_info->fdc_hds & 1) << 2;
                        i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 0x03);
                        i8272_info->fdc_status[0] |= 0x40;

                        i8272_info->fdc_status[1]  = 0;
                        i8272_info->fdc_status[2]  = 0;

                        i8272_info->result[0] = i8272_info->fdc_status[0];
                        i8272_info->result[1] = i8272_info->fdc_status[1];
                        i8272_info->result[2] = i8272_info->fdc_status[2];
                        i8272_info->result[3] = pDrive->imd->track[pDrive->track][i8272_info->fdc_head].logicalCyl[i8272_info->fdc_sector]; /* AGN logicalCyl */
                        i8272_info->result[4] = pDrive->imd->track[pDrive->track][i8272_info->fdc_head].logicalHead[i8272_info->fdc_sector];    /* AGN logicalHead */
                        i8272_info->result[5] = i8272_info->fdc_sector;
                        i8272_info->result[6] = i8272_info->fdc_sec_len;
                        break;
                    case I8272_READ_ID: /* READ ID */
                        i8272_info->fdc_mfm = (i8272_info->cmd[0] & 0x40) >> 6;
                        i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2;
                        i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03);
                        pDrive = &i8272_info->drive[i8272_info->sel_drive];
                        if(pDrive->uptr == NULL) {
                            return 0xFF;
                        }
                        /* Compute the i8272 "N" value from the sectorsize of this              */
                        /* disk's current track - i.e. N = log2(sectsize) - log2(128)           */
                        /* The calculation also works for non-standard format disk images with  */
                        /* sectorsizes of 2048, 4096 and 8192 bytes                             */
                        i8272_info->fdc_sec_len = floorlog2(
                            pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].sectsize) - 7; /* AGN fix to use fdc_hds (was fdc_head)*/
                        /* For now always return the starting sector number   */
                        /* but could return (say) a valid sector number based */
                        /* on elapsed time for a more "realistic" simulation. */
                        /* This would allow disk analysis programs that use   */
                        /* READID to detect non-standard disk formats.        */
                        i8272_info->fdc_sector = pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].start_sector;
                        if((i8272_info->fdc_sec_len == 0xF8) || (i8272_info->fdc_sec_len > I8272_MAX_N)) { /* Error calculating N or N too large */
                            sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                      " Illegal sector size N=%d. Reset to 0.\n",
                                      PCX, i8272_info->fdc_sec_len);
                            i8272_info->fdc_sec_len = 0;
                            return 0xFF;
                        }
                        i8272_info->fdc_status[0]  = (i8272_info->fdc_hds & 1) << 2;
                        i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 0x03);

                        i8272_info->fdc_status[1]  = 0;
                        i8272_info->fdc_status[2]  = 0;

                        i8272_info->result[0] = i8272_info->fdc_status[0];
                        i8272_info->result[1] = i8272_info->fdc_status[1];
                        i8272_info->result[2] = i8272_info->fdc_status[2];
                        i8272_info->result[3] = pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].logicalCyl[i8272_info->fdc_sector];  /* AGN logicalCyl */
                        i8272_info->result[4] = pDrive->imd->track[pDrive->track][i8272_info->fdc_hds].logicalHead[i8272_info->fdc_sector]; /* AGN logicalHead */
                        i8272_info->result[5] = i8272_info->fdc_sector;
                        i8272_info->result[6] = i8272_info->fdc_sec_len;
                        break;
                    case I8272_RECALIBRATE: /* RECALIBRATE */
                        i8272_info->sel_drive = i8272_info->cmd[1] & 0x03;
                        pDrive = &i8272_info->drive[i8272_info->sel_drive];
                        if(pDrive->uptr == NULL) {
                            return 0xFF;
                        }

                        pDrive->track = 0;
                        i8272_info->fdc_phase = CMD_PHASE;  /* No result phase */
                        i8272_info->fdc_seek_end = 1;
                        sim_debug(SEEK_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                  " Recalibrate: Drive 0x%02x\n",
                                  PCX, i8272_info->sel_drive);
                        break;
                    case I8272_FORMAT_TRACK:    /* FORMAT A TRACK */
                        i8272_info->fdc_mfm = (i8272_info->cmd[0] & 0x40) >> 6;
                        i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2;
                        i8272_info->fdc_head = i8272_info->fdc_hds;
                        i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03);
                        pDrive = &i8272_info->drive[i8272_info->sel_drive];
                        if(pDrive->uptr == NULL) {
                            return 0xFF;
                        }

                        if(pDrive->track != i8272_info->cmd[2]) {
                            i8272_info->fdc_seek_end = 1;
                        } else {
                            i8272_info->fdc_seek_end = 0;
                        }
                        i8272_info->fdc_sec_len = i8272_info->cmd[2];
                        if(i8272_info->fdc_sec_len > I8272_MAX_N) {
                            sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                      " Illegal sector size %d [N=%d]. Reset to %d [N=%d].\n",
                                      PCX, 128 << i8272_info->fdc_sec_len,
                                      i8272_info->fdc_sec_len, 128 << I8272_MAX_N, I8272_MAX_N);
                            i8272_info->fdc_sec_len = I8272_MAX_N;
                        }
                        i8272_info->fdc_sc = i8272_info->cmd[3];
                        i8272_info->fdc_gpl = i8272_info->cmd[4];
                        i8272_info->fdc_fillbyte = i8272_info->cmd[5];

                        sim_debug(FMT_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                  " Format Drive: %d, %s, C=%d. H=%d. N=%d, SC=%d, GPL=%02x, FILL=%02x\n",
                                  PCX,
                                  i8272_info->sel_drive,
                                  i8272_info->fdc_mfm ? "MFM" : "FM",
                                  pDrive->track,
                                  i8272_info->fdc_head,
                                  i8272_info->fdc_sec_len,
                                  i8272_info->fdc_sc,
                                  i8272_info->fdc_gpl,
                                  i8272_info->fdc_fillbyte);

                        i8272_info->fdc_status[0]  = (i8272_info->fdc_hds & 1) << 2;
                        i8272_info->fdc_status[0] |= (i8272_info->sel_drive & 0x03);

                        i8272_info->fdc_status[1]  = 0;
                        i8272_info->fdc_status[2]  = 0;
                        i8272_info->fdc_sectorcount = 0;

                        i8272_info->result[0] = i8272_info->fdc_status[0];
                        i8272_info->result[1] = i8272_info->fdc_status[1];
                        i8272_info->result[2] = i8272_info->fdc_status[2];
                        i8272_info->result[3] = pDrive->track;
                        i8272_info->result[4] = i8272_info->fdc_head;   /* AGN for now we cannot format with logicalHead */
                        i8272_info->result[5] = i8272_info->fdc_sector; /* AGN ditto for logicalCyl */
                        i8272_info->result[6] = i8272_info->fdc_sec_len;
                        break;
                    case I8272_SENSE_INTR_STATUS:   /* SENSE INTERRUPT STATUS */
                        sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                  " Sense Interrupt Status\n", PCX);
                        i8272_info->result[0]  = i8272_info->fdc_seek_end ? 0x20 : 0x00;  /* SEEK_END */
                        i8272_info->result[0] |= i8272_info->sel_drive;
                        i8272_info->result[1]  = pDrive->track;
                        i8272_irq = 0;
                        break;
                    case I8272_SPECIFY: /* SPECIFY */
                        i8272_info->fdc_srt = 16 - ((i8272_info->cmd[1] & 0xF0) >> 4);
                        i8272_info->fdc_hut = (i8272_info->cmd[1] & 0x0F) * 16;
                        i8272_info->fdc_hlt = ((i8272_info->cmd[2] & 0xFE) >> 1) * 2;
                        i8272_info->fdc_nd  = (i8272_info->cmd[2] & 0x01);
                        i8272_info->fdc_phase = CMD_PHASE;  /* No result phase */
                        sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                  " Specify: SRT=%d, HUT=%d, HLT=%d, ND=%s\n",
                                  PCX, i8272_info->fdc_srt,
                                  i8272_info->fdc_hut,
                                  i8272_info->fdc_hlt,
                                  i8272_info->fdc_nd ? "NON-DMA" : "DMA");
                        break;
                    case I8272_SENSE_DRIVE_STATUS:  /* Setup Status3 Byte */
                        i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2;
                        i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03);
                        pDrive = &i8272_info->drive[i8272_info->sel_drive];
                        if(pDrive->uptr == NULL) {
                            return 0xFF;
                        }

                        i8272_info->result[0]  = (pDrive->ready) ? DRIVE_STATUS_READY : 0; /* Drive Ready */
                        if(imdGetSides(pDrive->imd) == 2) {
                            i8272_info->result[0] |= DRIVE_STATUS_TWO_SIDED;    /* Two-sided?       */
                        }
                        if(imdIsWriteLocked(pDrive->imd)) {
                            i8272_info->result[0] |= DRIVE_STATUS_WP;           /* Write Protected? */
                        }
                        i8272_info->result[0] |= (i8272_info->fdc_hds & 1) << 2;
                        i8272_info->result[0] |= (i8272_info->sel_drive & 0x03);
                        i8272_info->result[0] |= (pDrive->track == 0) ? DRIVE_STATUS_TRACK0 : 0x00; /* Track 0 */
                        sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                  " Sense Drive Status = 0x%02x\n", PCX, i8272_info->result[0]);
                        break;
                    case I8272_SEEK:    /* SEEK */
                        i8272_info->fdc_mt = (i8272_info->cmd[0] & 0x80) >> 7;
                        i8272_info->fdc_mfm = (i8272_info->cmd[0] & 0x40) >> 6;
                        i8272_info->fdc_sk = (i8272_info->cmd[0] & 0x20) >> 5;
                        i8272_info->fdc_hds = (i8272_info->cmd[1] & 0x04) >> 2;
                        i8272_info->sel_drive = (i8272_info->cmd[1] & 0x03);
                        pDrive = &i8272_info->drive[i8272_info->sel_drive];
                        if(pDrive->uptr == NULL) {
                            return 0xFF;
                        }

                        pDrive->track = i8272_info->cmd[2];
                        i8272_info->fdc_head = i8272_info->fdc_hds; /*AGN seek should save the head */
                        i8272_info->fdc_seek_end = 1;
                        sim_debug(SEEK_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                  " Seek Drive: %d, %s %s, C=%d. Skip Deleted Data=%s Head Select=%s\n",
                                  PCX,
                                  i8272_info->sel_drive,
                                  i8272_info->fdc_mt ? "Multi" : "Single",
                                  i8272_info->fdc_mfm ? "MFM" : "FM",
                                  i8272_info->cmd[2],
                                  i8272_info->fdc_sk ? "True" : "False",
                                  i8272_info->fdc_hds ? "True" : "False");
                        break;
                    default:    /* INVALID */
                        break;
                }

                if(i8272_info->fdc_phase == EXEC_PHASE) {
                    switch(i8272_info->cmd[0] & 0x1F) {
                        case I8272_READ_TRACK:
                            printf("I8272: " ADDRESS_FORMAT " Read a track (untested.)" NLP, PCX);
                            i8272_info->fdc_sector = 1; /* Read entire track from sector 1...eot */
                        case I8272_READ_DATA:
                        case I8272_READ_DELETED_DATA:
                            disk_read = 1;
                        case I8272_WRITE_DATA:
                        case I8272_WRITE_DELETED_DATA:
                            for(;i8272_info->fdc_sector<=i8272_info->fdc_eot;i8272_info->fdc_sector++) {
                                sim_debug(RD_DATA_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                          " %s Data, sector: %d sector len=%d\n",
                                          PCX, disk_read ? "RD" : "WR",
                                          i8272_info->fdc_sector,
                                          128 << i8272_info->fdc_sec_len);

                                if(pDrive->imd == NULL) {
                                    printf(".imd is NULL!" NLP);
                                }
                                if(disk_read) { /* Read sector */
                                    sectRead(pDrive->imd,
                                        pDrive->track,
                                        i8272_info->fdc_head,
                                        i8272_info->fdc_sector,
                                        sdata.raw,
                                        128 << i8272_info->fdc_sec_len,
                                        &flags,
                                        &readlen);

                                    for(i=0;i<(128 << i8272_info->fdc_sec_len);i++) {
                                        PutByteDMA(i8272_info->fdc_dma_addr, sdata.raw[i]);
                                        i8272_info->fdc_dma_addr++;
                                    }
                                    sim_debug(RD_DATA_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                              " T:%d/H:%d/S:%d/L:%4d: Data transferred to RAM at 0x%06x\n",
                                              PCX, pDrive->track,
                                              i8272_info->fdc_head,
                                              i8272_info->fdc_sector,
                                              128 << i8272_info->fdc_sec_len,
                                              i8272_info->fdc_dma_addr - i);
                                } else { /* Write */
                                    for(i=0;i<(128 << i8272_info->fdc_sec_len);i++) {
                                        sdata.raw[i] = GetByteDMA(i8272_info->fdc_dma_addr);
                                        i8272_info->fdc_dma_addr++;
                                    }
                                    sim_debug(WR_DATA_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                              " Data transferred from RAM at 0x%06x\n",
                                              PCX, i8272_info->fdc_dma_addr);
                                    sectWrite(pDrive->imd,
                                        pDrive->track,
                                        i8272_info->fdc_head,
                                        i8272_info->fdc_sector,
                                        sdata.raw,
                                        128 << i8272_info->fdc_sec_len,
                                        &flags,
                                        &readlen);
                                }

                                i8272_info->result[5] = i8272_info->fdc_sector;
                                i8272_info->result[1] = 0x80;
                            }
                            break;
                        case I8272_FORMAT_TRACK:    /* FORMAT A TRACK */
                            for(i8272_info->fdc_sector = 1;i8272_info->fdc_sector<=i8272_info->fdc_sc;i8272_info->fdc_sector++) {
                                sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                          " Format Track %d, Sector=%d, len=%d\n", PCX, pDrive->track, i8272_info->fdc_sector, 128 << i8272_info->fdc_sec_len);

                                if(i8272_info->fdc_sectorcount >= I8272_MAX_SECTOR) {
                                    sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                              " Illegal sector count\n", PCX);
                                    i8272_info->fdc_sectorcount = 0;
                                }
                                i8272_info->fdc_sectormap[i8272_info->fdc_sectorcount] = i8272_info->fdc_sector;
                                i8272_info->fdc_sectorcount++;
                                if(i8272_info->fdc_sectorcount == i8272_info->fdc_sc) {
                                    trackWrite(pDrive->imd,
                                        pDrive->track,
                                        i8272_info->fdc_head,
                                        i8272_info->fdc_sc,
                                        128 << i8272_info->fdc_sec_len,
                                        i8272_info->fdc_sectormap,
                                        i8272_info->fdc_mfm ? 3 : 0,
                                        i8272_info->fdc_fillbyte,
                                        &flags);

                                    /* Recalculate disk size */
                                    pDrive->uptr->capac = sim_fsize(pDrive->uptr->fileref);

                                }
                            }
                            break;

                        case I8272_SCAN_LOW_EQUAL:  /* SCAN LOW OR EQUAL */
                        case I8272_SCAN_HIGH_EQUAL: /* SCAN HIGH OR EQUAL */
                        case I8272_SCAN_EQUAL:  /* SCAN EQUAL */
                            sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                      " Scan Data\n", PCX);
                            sim_debug(ERROR_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                      " ERROR: Scan not implemented.\n", PCX);
                            break;
                        case I8272_READ_ID:  /* READ ID */
                            sim_debug(CMD_MSG, &i8272_dev, "I8272: " ADDRESS_FORMAT
                                      " READ ID Drive %d result ST0=%02x ST1=%02x ST2=%02x "
                                      "C=%d H=%d R=%02x N=%d\n", PCX,
                                      i8272_info->sel_drive,
                                      i8272_info->result[0], i8272_info->result[1],
                                      i8272_info->result[2], i8272_info->result[3],
                                      i8272_info->result[4], i8272_info->result[5],
                                      i8272_info->result[6]);
                            break;

                        default:
                            break;
                    }
                }

                if(i8272_info->result_len != 0) {
                    i8272_info->fdc_phase ++;
                } else {
                    i8272_info->fdc_phase = CMD_PHASE;
                }

                i8272_info->result_index = 0;
                if((i8272_info->cmd[0] & 0x1F) != I8272_SENSE_INTR_STATUS) {
                    raise_i8272_interrupt();
                }
            }

            break;
    }

    cData = 0x00;

    return (cData);
}
Esempio n. 7
0
/* Attach routine */
t_stat i8272_attach(UNIT *uptr, char *cptr)
{
    char header[4];
    t_stat r;
    int32 i = 0;

    r = attach_unit(uptr, cptr);    /* attach unit  */
    if ( r != SCPE_OK)              /* error?       */
        return r;

    /* Determine length of this disk */
    uptr->capac = sim_fsize(uptr->fileref);

    i = find_unit_index(uptr);

    if (i == -1) {
        return (SCPE_IERR);
    }

    DBG_PRINT(("Attach I8272%d\n", i));
    i8272_info->drive[i].uptr = uptr;

    /* Default to drive not ready */
    i8272_info->drive[i].ready = 0;

    if(uptr->capac > 0) {
        char *rtn = fgets(header, 4, uptr->fileref);
        if((rtn != NULL) && strncmp(header, "IMD", 3)) {
            printf("I8272: Only IMD disk images are supported\n");
            i8272_info->drive[i].uptr = NULL;
            return SCPE_OPENERR;
        }
    } else {
        /* create a disk image file in IMD format. */
        if (diskCreate(uptr->fileref, "$Id: i8272.c 1999 2008-07-22 04:25:28Z hharte $") != SCPE_OK) {
            printf("I8272: Failed to create IMD disk.\n");
            i8272_info->drive[i].uptr = NULL;
            return SCPE_OPENERR;
        }
        uptr->capac = sim_fsize(uptr->fileref);
    }

    uptr->u3 = IMAGE_TYPE_IMD;

    if (uptr->flags & UNIT_I8272_VERBOSE) {
        printf("I8272%d: attached to '%s', type=%s, len=%d\n", i, cptr,
            uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",
            uptr->capac);
    }

    if(uptr->u3 == IMAGE_TYPE_IMD) {
        if (uptr->flags & UNIT_I8272_VERBOSE)
            printf("--------------------------------------------------------\n");
        i8272_info->drive[i].imd = diskOpen(uptr->fileref, uptr->flags & UNIT_I8272_VERBOSE);
        if (uptr->flags & UNIT_I8272_VERBOSE)
            printf("\n");
        if (i8272_info->drive[i].imd == NULL) {
            printf("I8272: IMD disk corrupt.\n");
            i8272_info->drive[i].uptr = NULL;
            return SCPE_OPENERR;
        }
        i8272_info->drive[i].ready = 1;
    } else {
        i8272_info->drive[i].imd = NULL;
    }

    return SCPE_OK;
}
Esempio n. 8
0
/* Attach routine */
static t_stat vfdhd_attach(UNIT *uptr, char *cptr)
{
    char header[4];
    t_stat r;
    unsigned int i = 0;

    r = attach_unit(uptr, cptr);                        /* attach unit                          */
    if ( r != SCPE_OK)                                  /* error?                               */
        return r;

    /* Determine length of this disk */
    uptr->capac = sim_fsize(uptr->fileref);

    for(i = 0; i < VFDHD_MAX_DRIVES; i++) {
        vfdhd_info->drive[i].uptr = &vfdhd_dev.units[i];
    }

    for(i = 0; i < VFDHD_MAX_DRIVES; i++) {
        if(vfdhd_dev.units[i].fileref == uptr->fileref) {
            break;
        }
    }

    if(uptr->capac > 0) {
        fgets(header, 4, uptr->fileref);
        if(!strcmp(header, "IMD")) {
            uptr->u3 = IMAGE_TYPE_IMD;
        } else if(!strcmp(header, "CPT")) {
            printf("CPT images not yet supported\n");
            uptr->u3 = IMAGE_TYPE_CPT;
            vfdhd_detach(uptr);
            return SCPE_OPENERR;
        } else {
            uptr->u3 = IMAGE_TYPE_DSK;
        }
    } else {
        /* creating file, must be DSK format. */
        uptr->u3 = IMAGE_TYPE_DSK;
    }

    if (uptr->flags & UNIT_VFDHD_VERBOSE)
        printf("VFDHD%d: attached to '%s', type=%s, len=%d\n", i, cptr,
            uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",
            uptr->capac);

    if(uptr->u3 == IMAGE_TYPE_IMD) {
        if(uptr->capac < 318000) {
            printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n");
            vfdhd_detach(uptr);
            return SCPE_OPENERR;
        }

        if (uptr->flags & UNIT_VFDHD_VERBOSE)
            printf("--------------------------------------------------------\n");
        vfdhd_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_VFDHD_VERBOSE));
        if (uptr->flags & UNIT_VFDHD_VERBOSE)
            printf("\n");
    } else {
        vfdhd_info->drive[i].imd = NULL;
    }

    if(i>0) { /* Floppy Disk, Unit 1-3 */
        vfdhd_info->drive[i].ntracks  = 77;     /* number of tracks */
        vfdhd_info->drive[i].nheads   = 2;      /* number of heads */
        vfdhd_info->drive[i].nspt     = 16;     /* number of sectors per track */
        vfdhd_info->drive[i].npre_len = 40;     /* preamble length */
        vfdhd_info->drive[i].sectsize = VFDHD_SECTOR_LEN;   /* sector size, not including pre/postamble */
    } else { /* Hard Disk, Unit 0 */
        if(hdSize == 10) {
            vfdhd_info->drive[i].ntracks  = 153;    /* number of tracks */
            vfdhd_info->drive[i].nheads   = 6;      /* number of heads */
            vfdhd_info->hdsk_type = 1;
            printf("10MB\n");
        } else if (hdSize == 5) {
            vfdhd_info->drive[i].ntracks  = 153;    /* number of tracks */
            vfdhd_info->drive[i].nheads   = 4;      /* number of heads */
            vfdhd_info->hdsk_type = 0;
            printf("5MB\n");
        } else {
            vfdhd_info->drive[i].ntracks  = 512;    /* number of tracks */
            vfdhd_info->drive[i].nheads   = 8;      /* number of heads */
            vfdhd_info->hdsk_type = 1;
            printf("32MB\n");
        }

        vfdhd_info->drive[i].nheads   = 4;      /* number of heads */
        vfdhd_info->drive[i].nspt     = 32;     /* number of sectors per track */
        vfdhd_info->drive[i].npre_len = 30;     /* preamble length */
        vfdhd_info->drive[i].sectsize = VFDHD_SECTOR_LEN;   /* sector size, not including pre/postamble */
        vfdhd_info->drive[i].ready = 1;
        vfdhd_info->drive[i].seek_complete = 1;
        vfdhd_info->drive[i].sync_lost = 1;     /* Active LOW */
    }

    vfdhd_info->motor_on = 1;
    return SCPE_OK;
}
Esempio n. 9
0
/*
 * Create an ImageDisk (IMD) file.  This function just creates the comment header, and allows
 * the user to enter a comment.  After the IMD is created, it must be formatted with a format
 * program on the simulated operating system, ie CP/M, CDOS, 86-DOS.
 *
 * If the IMD file already exists, the user will be given the option of overwriting it.
 */
t_stat diskCreate(FILE *fileref, const char *ctlr_comment)
{
    DISK_INFO *myDisk = NULL;
    char *comment;
    char *curptr;
    char *result;
    uint8 answer;
    int32 len, remaining;

    if(fileref == NULL) {
        return (SCPE_OPENERR);
    }

    if(sim_fsize(fileref) != 0) {
        sim_printf("SIM_IMD: Disk image already has data, do you want to overwrite it? ");
        answer = getchar();

        if((answer != 'y') && (answer != 'Y')) {
            return (SCPE_OPENERR);
        }
    }

    if((curptr = comment = (char *)calloc(1, MAX_COMMENT_LEN)) == 0) {
        sim_printf("Memory allocation failure.\n");
        return (SCPE_MEM);
    }

    sim_printf("SIM_IMD: Enter a comment for this disk.\n"
               "SIM_IMD: Terminate with a '.' on an otherwise blank line.\n");
    remaining = MAX_COMMENT_LEN;
    do {
        sim_printf("IMD> ");
        result = fgets(curptr, remaining - 3, stdin);
        if ((result == NULL) || (strcmp(curptr, ".\n") == 0)) {
            remaining = 0;
        } else {
            len = strlen(curptr) - 1;
            if (curptr[len] != '\n')
                len++;
            remaining -= len;
            curptr += len;
            *curptr++ = 0x0d;
            *curptr++ = 0x0a;
        }
    } while (remaining > 4);
    *curptr = 0x00;

    /* rewind to the beginning of the file. */
    rewind(fileref);

    /* Erase the contents of the IMD file in case we are overwriting an existing image. */
    if (sim_set_fsize(fileref, (t_addr)ftell (fileref)) == -1) {
        sim_printf("SIM_IMD: Error overwriting disk image.\n");
        return(SCPE_OPENERR);
    }

    fprintf(fileref, "IMD SIMH %s %s\n", __DATE__, __TIME__);
    fputs(comment, fileref);
    free(comment);
    fprintf(fileref, "\n\n$Id: sim_imd.c 1999 2008-07-22 04:25:28Z hharte $\n");
    fprintf(fileref, "%s\n", ctlr_comment);
    fputc(0x1A, fileref); /* EOF marker for IMD comment. */
    fflush(fileref);

    if((myDisk = diskOpen(fileref, 0)) == NULL) {
        sim_printf("SIM_IMD: Error opening disk for format.\n");
        return(SCPE_OPENERR);
    }

    if(diskFormat(myDisk) != SCPE_OK) {
        sim_printf("SIM_IMD: error formatting disk.\n");
    }

    return diskClose(&myDisk);
}
Esempio n. 10
0
/* Attach routine */
static t_stat hdsk_attach(UNIT *uptr, char *cptr) {
    t_stat r;
    uint32 i;
    char unitChar;

    r = attach_unit(uptr, cptr);                        /* attach unit                          */
    if ( r != SCPE_OK)                                  /* error?                               */
        return r;

    /* Step 1: Determine capacity of this disk                                                  */
    uptr -> capac = sim_fsize(uptr -> fileref);         /* the file length is a good candidate  */
    if (uptr -> capac == 0) {                           /* file does not exist or has length 0  */
        uptr -> capac = uptr -> HDSK_NUMBER_OF_TRACKS *
            uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE;
        if (uptr -> capac == 0)
            uptr -> capac = HDSK_CAPACITY;
    }                                                   /* post condition: uptr -> capac > 0    */
    assert(uptr -> capac);

    /* Step 2: Determine format based on disk capacity                                          */
    uptr -> HDSK_FORMAT_TYPE = -1;                      /* default to unknown format type       */
    for (i = 0; dpb[i].capac != 0; i++) {               /* find disk parameter block            */
        if (dpb[i].capac == uptr -> capac) {            /* found if correct capacity            */
            uptr -> HDSK_FORMAT_TYPE = i;
            break;
        }
    }

    /* Step 3: Set number of sectors per track and sector size                                  */
    if (uptr -> HDSK_FORMAT_TYPE == -1) {               /* Case 1: no disk parameter block found*/
        for (i = 0; i < hdsk_dev.numunits; i++)         /* find affected unit number            */
            if (&hdsk_unit[i] == uptr)
                break;                                  /* found                                */
        unitChar = '0' + i;
        uptr -> HDSK_FORMAT_TYPE = 0;
        printf("HDSK%c: WARNING: Unsupported disk capacity, assuming HDSK type with capacity %iKB.\n",
            unitChar, uptr -> capac / 1000);
        uptr -> flags |= UNIT_HDSK_WLK;
        printf("HDSK%c: WARNING: Forcing WRTLCK.\n", unitChar);
        /* check whether capacity corresponds to setting of tracks, sectors per track and sector size   */
        if (uptr -> capac != (uint32)(uptr -> HDSK_NUMBER_OF_TRACKS *
                uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE)) {
            printf("HDSK%c: WARNING: Fixing geometry.\n", unitChar);
            if (uptr -> HDSK_SECTORS_PER_TRACK == 0)
                uptr -> HDSK_SECTORS_PER_TRACK = 32;
            if (uptr -> HDSK_SECTOR_SIZE == 0)
                uptr -> HDSK_SECTOR_SIZE = 128;
        }
    }
    else {  /* Case 2: disk parameter block found                                               */
        uptr -> HDSK_SECTORS_PER_TRACK    = dpb[uptr -> HDSK_FORMAT_TYPE].spt >> dpb[uptr -> HDSK_FORMAT_TYPE].psh;
        uptr -> HDSK_SECTOR_SIZE          = (128 << dpb[uptr -> HDSK_FORMAT_TYPE].psh);
    }
    assert(uptr -> HDSK_SECTORS_PER_TRACK && uptr -> HDSK_SECTOR_SIZE);

    /* Step 4: Number of tracks is smallest number to accomodate capacity                       */
    uptr -> HDSK_NUMBER_OF_TRACKS = (uptr -> capac + uptr -> HDSK_SECTORS_PER_TRACK *
        uptr -> HDSK_SECTOR_SIZE - 1) / (uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE);
    assert( ( (t_addr) ((uptr -> HDSK_NUMBER_OF_TRACKS - 1) * uptr -> HDSK_SECTORS_PER_TRACK *
        uptr -> HDSK_SECTOR_SIZE) < uptr -> capac) &&
        (uptr -> capac <= (t_addr) (uptr -> HDSK_NUMBER_OF_TRACKS *
        uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE) ) );
    return SCPE_OK;
}
Esempio n. 11
0
/* Attach routine */
static t_stat hdsk_attach(UNIT *uptr, char *cptr) {
    int32 thisUnitIndex;
    char unitChar;
    const t_stat r = attach_unit(uptr, cptr);           /* attach unit                          */
    if (r != SCPE_OK)                                   /* error?                               */
        return r;
    
    assert(uptr != NULL);
    thisUnitIndex = find_unit_index(uptr);
    unitChar = '0' + thisUnitIndex;
    assert((0 <= thisUnitIndex) && (thisUnitIndex < HDSK_NUMBER));
    
    if (is_imd(uptr)) {
        if ((sim_fsize(uptr -> fileref) == 0) &&
            (diskCreate(uptr -> fileref, "$Id: SIMH hdsk.c $") != SCPE_OK)) {
            printf("HDSK%c (IMD): Failed to create IMD disk.\n", unitChar);
            detach_unit(uptr);
            return SCPE_OPENERR;
        }
        hdsk_imd[thisUnitIndex] = diskOpen(uptr -> fileref, sim_deb && (hdsk_dev.dctrl & VERBOSE_MSG));
        if (hdsk_imd[thisUnitIndex] == NULL)
            return SCPE_IOERR;
        verifyDiskInfo(*hdsk_imd[thisUnitIndex], '0' + thisUnitIndex);
        uptr -> HDSK_NUMBER_OF_TRACKS = hdsk_imd[thisUnitIndex] -> ntracks;
        uptr -> HDSK_SECTORS_PER_TRACK = hdsk_imd[thisUnitIndex] -> track[1][0].nsects;
        uptr -> HDSK_SECTOR_SIZE = hdsk_imd[thisUnitIndex] -> track[1][0].sectsize;
        uptr -> capac = ((uptr -> HDSK_NUMBER_OF_TRACKS) *
                         (uptr -> HDSK_SECTORS_PER_TRACK) *
                         (uptr -> HDSK_SECTOR_SIZE));
        assignFormat(uptr);
        if (uptr -> HDSK_FORMAT_TYPE == -1) {           /* Case 1: no disk parameter block found*/
            uptr -> HDSK_FORMAT_TYPE = 0;
            printf("HDSK%c (IMD): WARNING: Unsupported disk capacity, assuming HDSK type "
                   "with capacity %iKB.\n", unitChar, uptr -> capac / 1000);
            uptr -> flags |= UNIT_HDSK_WLK;
            printf("HDSK%c (IMD): WARNING: Forcing WRTLCK.\n", unitChar);
        }
        return SCPE_OK;
    }
    
    /* Step 1: Determine capacity of this disk														*/
    uptr -> capac = sim_fsize(uptr -> fileref);				/* the file length is a good indication */
    if (uptr -> capac == 0) {								/* file does not exist or has length 0  */
        uptr -> capac = (uptr -> HDSK_NUMBER_OF_TRACKS *
                         uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE);
        if (uptr -> capac == 0)
            uptr -> capac = HDSK_CAPACITY;
    }														/* post condition: uptr -> capac > 0	*/
    assert(uptr -> capac);
    
    /* Step 2: Determine format based on disk capacity												*/
    assignFormat(uptr);
    
    /* Step 3: Set number of sectors per track and sector size										*/
    if (uptr -> HDSK_FORMAT_TYPE == -1) {                 /* Case 1: no disk parameter block found	*/
        uptr -> HDSK_FORMAT_TYPE = 0;
        printf("HDSK%c: WARNING: Unsupported disk capacity, assuming HDSK type with capacity %iKB.\n",
               unitChar, uptr -> capac / 1000);
        uptr -> flags |= UNIT_HDSK_WLK;
        printf("HDSK%c: WARNING: Forcing WRTLCK.\n", unitChar);
        /* check whether capacity corresponds to setting of tracks, sectors per track and sector size	*/
        if (uptr -> capac != (uint32)(uptr -> HDSK_NUMBER_OF_TRACKS *
                                      uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE)) {
            printf("HDSK%c: WARNING: Fixing geometry.\n", unitChar);
            if (uptr -> HDSK_SECTORS_PER_TRACK == 0)
                uptr -> HDSK_SECTORS_PER_TRACK = 32;
            if (uptr -> HDSK_SECTOR_SIZE == 0)
                uptr -> HDSK_SECTOR_SIZE = 128;
        }
    }
    else {  /* Case 2: disk parameter block found														*/
        uptr -> HDSK_SECTORS_PER_TRACK  = dpb[uptr -> HDSK_FORMAT_TYPE].spt >> dpb[uptr -> HDSK_FORMAT_TYPE].psh;
        uptr -> HDSK_SECTOR_SIZE        = (128 << dpb[uptr -> HDSK_FORMAT_TYPE].psh);
    }
    assert((uptr -> HDSK_SECTORS_PER_TRACK) && (uptr -> HDSK_SECTOR_SIZE) && (uptr -> HDSK_FORMAT_TYPE >= 0));
    
    /* Step 4: Number of tracks is smallest number to accomodate capacity								*/
    uptr -> HDSK_NUMBER_OF_TRACKS = (uptr -> capac + uptr -> HDSK_SECTORS_PER_TRACK *
                                     uptr -> HDSK_SECTOR_SIZE - 1) / (uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE);
    assert( ( (t_addr) ((uptr -> HDSK_NUMBER_OF_TRACKS - 1) * uptr -> HDSK_SECTORS_PER_TRACK *
                        uptr -> HDSK_SECTOR_SIZE) < uptr -> capac) &&
           (uptr -> capac <= (t_addr) (uptr -> HDSK_NUMBER_OF_TRACKS *
                                       uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE) ) );
    
    return SCPE_OK;
}
Esempio n. 12
0
/* Attach routine */
t_stat wd179x_attach(UNIT *uptr, char *cptr)
{
    char header[4];
    t_stat r;
    int32 i = 0;

    r = attach_unit(uptr, cptr);    /* attach unit  */
    if ( r != SCPE_OK)              /* error?       */
        return r;

    /* Determine length of this disk */
    uptr->capac = sim_fsize(uptr->fileref);

    i = find_unit_index(uptr);

    if (i == -1) {
        return (SCPE_IERR);
    }

    DBG_PRINT(("Attach WD179X%d\n", i));
    wd179x_info->drive[i].uptr = uptr;

    /* Default to drive not ready */
    wd179x_info->drive[i].ready = 0;

    if(uptr->capac > 0) {
        char *rtn = fgets(header, 4, uptr->fileref);
        if ((rtn != NULL) && strncmp(header, "IMD", 3)) {
            printf("WD179X: Only IMD disk images are supported\n");
            wd179x_info->drive[i].uptr = NULL;
            return SCPE_OPENERR;
        }
    } else {
        /* create a disk image file in IMD format. */
        if (diskCreate(uptr->fileref, "$Id: wd179x.c 1999 2008-07-22 04:25:28Z hharte $") != SCPE_OK) {
            printf("WD179X: Failed to create IMD disk.\n");
            wd179x_info->drive[i].uptr = NULL;
            return SCPE_OPENERR;
        }
        uptr->capac = sim_fsize(uptr->fileref);
    }

    uptr->u3 = IMAGE_TYPE_IMD;

    if (uptr->flags & UNIT_WD179X_VERBOSE)
        printf("WD179X%d: attached to '%s', type=%s, len=%d\n", i, cptr,
            uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",
            uptr->capac);

    if(uptr->u3 == IMAGE_TYPE_IMD) {
        if (uptr->flags & UNIT_WD179X_VERBOSE)
            printf("--------------------------------------------------------\n");
        wd179x_info->drive[i].imd = diskOpen(uptr->fileref, uptr->flags & UNIT_WD179X_VERBOSE);
        if (uptr->flags & UNIT_WD179X_VERBOSE)
            printf("\n");
        if (wd179x_info->drive[i].imd == NULL) {
            printf("WD179X: IMD disk corrupt.\n");
            wd179x_info->drive[i].uptr = NULL;
            return SCPE_OPENERR;
        }

        /* Write-protect the unit if IMD think's it's writelocked. */
        if(imdIsWriteLocked(wd179x_info->drive[i].imd)) {
            uptr->flags |= UNIT_WD179X_WLK;
        }

        wd179x_info->drive[i].ready = 1;
    } else {
        wd179x_info->drive[i].imd = NULL;
    }

    wd179x_info->fdc_sec_len = 0; /* 128 byte sectors, fixme */
    wd179x_info->sel_drive = 0;

    return SCPE_OK;
}
Esempio n. 13
0
t_stat sim_tape_wrgap (UNIT *uptr, uint32 gaplen, uint32 bpi)
{
t_stat st;
t_mtrlnt meta, sbc, new_len, rec_size;
t_addr gap_pos = uptr->pos;
uint32 file_size, marker_count;
uint32 format = MT_GET_FMT (uptr);
uint32 gap_alloc = 0;                                   /* gap allocated from tape */
int32 gap_needed = (gaplen * bpi) / 10;                 /* gap remainder still needed */
const uint32 meta_size = sizeof (t_mtrlnt);             /* bytes per metadatum */
const uint32 min_rec_size = 2 + sizeof (t_mtrlnt) * 2;  /* smallest data record size */

MT_CLR_PNU (uptr);

if ((uptr->flags & UNIT_ATT) == 0)                      /* not attached? */
    return MTSE_UNATT;
if (format != MTUF_F_STD)                               /* not SIMH fmt? */
    return MTSE_FMT;
if (sim_tape_wrp (uptr))                                /* write protected? */
    return MTSE_WRP;

file_size = sim_fsize (uptr->fileref);                  /* get file size */
sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);         /* position tape */

/* Read tape records and allocate to gap until amount required is consumed.

   Read next metadatum from tape:
    - EOF or EOM: allocate remainder of bytes needed.
    - TMK or GAP: allocate sizeof(metadatum) bytes.
    - Reverse GAP: allocate sizeof(metadatum) / 2 bytes.
    - Data record: see below.

   Loop until bytes needed = 0.
*/

do {
    sim_fread (&meta, meta_size, 1, uptr->fileref);     /* read metadatum */

    if (ferror (uptr->fileref)) {                       /* read error? */
        uptr->pos = gap_pos;                            /* restore original position */
        MT_SET_PNU (uptr);                              /* position not updated */
        return sim_tape_ioerr (uptr);                   /* translate error */
        }
    else
        uptr->pos = uptr->pos + meta_size;              /* move tape over datum */

    if (feof (uptr->fileref) || (meta == MTR_EOM)) {    /* at eof or eom? */
        gap_alloc = gap_alloc + gap_needed;             /* allocate remainder */
        gap_needed = 0;
        }

    else if ((meta == MTR_GAP) || (meta == MTR_TMK)) {  /* gap or tape mark? */
        gap_alloc = gap_alloc + meta_size;              /* allocate marker space */
        gap_needed = gap_needed - meta_size;            /* reduce requirement */
        }

    else if (meta == MTR_FHGAP) {                       /* half gap? */
        uptr->pos = uptr->pos - meta_size / 2;          /* backup to resync */
        sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position tape */
        gap_alloc = gap_alloc + meta_size / 2;          /* allocate marker space */
        gap_needed = gap_needed - meta_size / 2;        /* reduce requirement */
        }

    else if (uptr->pos + 
             MTR_L (meta) + meta_size > file_size) {    /* rec len out of range? */
        gap_alloc = gap_alloc + gap_needed;             /* presume overwritten tape */
        gap_needed = 0;                                 /* allocate remainder */
        }

/* Allocate a data record:
    - Determine record size in bytes (including metadata)
    - If record size - bytes needed < smallest allowed record size,
      allocate entire record to gap, else allocate needed amount and
      truncate data record to reflect remainder.
*/
    else {                                              /* data record */
        sbc = MTR_L (meta);                             /* get record data length */
        rec_size = ((sbc + 1) & ~1) + meta_size * 2;    /* overall size in bytes */

        if (rec_size < gap_needed + min_rec_size) {         /* rec too small? */
            uptr->pos = uptr->pos - meta_size + rec_size;   /* position past record */
            sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* move tape */
            gap_alloc = gap_alloc + rec_size;               /* allocate record */
            gap_needed = gap_needed - rec_size;             /* reduce requirement */
            }

        else {                                              /* record size OK */
            uptr->pos = uptr->pos - meta_size + gap_needed; /* position to end of gap */
            new_len = MTR_F (meta) | (sbc - gap_needed);    /* truncate to new len */
            st = sim_tape_wrdata (uptr, new_len);           /* write new rec len */

            if (st != MTSE_OK) {                            /* write OK? */
                uptr->pos = gap_pos;                        /* restore orig pos */
                return st;                                  /* PNU was set by wrdata */
                }

            uptr->pos = uptr->pos + sbc - gap_needed;       /* position to end of data */
            st = sim_tape_wrdata (uptr, new_len);           /* write new rec len */

            if (st != MTSE_OK) {                            /* write OK? */
                uptr->pos = gap_pos;                        /* restore orig pos */
                return st;                                  /* PNU was set by wrdata */
                }

            gap_alloc = gap_alloc + gap_needed;             /* allocate remainder */
            gap_needed = 0;
            }
        }
    }
while (gap_needed > 0);

uptr->pos = gap_pos;                                    /* reposition to gap start */

if (gap_alloc & (meta_size - 1)) {                      /* gap size "odd?" */
    st = sim_tape_wrdata (uptr, MTR_FHGAP);             /* write half gap marker */
    if (st != MTSE_OK) {                                /* write OK? */
        uptr->pos = gap_pos;                            /* restore orig pos */
        return st;                                      /* PNU was set by wrdata */
        }
    uptr->pos = uptr->pos - meta_size / 2;              /* realign position */
    gap_alloc = gap_alloc - 2;                          /* decrease gap to write */
    }

marker_count = gap_alloc / meta_size;                   /* count of gap markers */

do {
    st = sim_tape_wrdata (uptr, MTR_GAP);               /* write gap markers */
    if (st != MTSE_OK) {                                /* write OK? */
        uptr->pos = gap_pos;                            /* restore orig pos */
        return st;                                      /* PNU was set by wrdata */
        }
    }
while (--marker_count > 0);

return MTSE_OK;
}