Exemple #1
0
t_stat ssem_load_dmp (FILE *fi)
{
C[1] = 0;
if (sim_fread(A, sizeof(int32), 1, fi) != 1 ||
    sim_fread(C, sizeof(uint32), 1, fi) != 1 ||
    sim_fread(S, sizeof(uint32), MEMSIZE, fi) != MEMSIZE) {
    return SCPE_IOERR;
    }
return SCPE_OK;
}
Exemple #2
0
int32 dsk12(const int32 port, const int32 io, const int32 data) {
    int32 i, rtn;
    UNIT *uptr;

    if (current_disk >= NUM_OF_DSK) {
        if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK12 < warnLevelDSK)) {
            warnDSK12++;
            sim_debug(VERBOSE_MSG, &dsk_dev,
                      "DSK%i: " ADDRESS_FORMAT
                      " Attempt of %s 0x0a on unattached disk - ignored.\n",
                      current_disk, PCX, selectInOut(io));
        }
        return 0;
    }

    /* now current_disk < NUM_OF_DSK */
    in9_count = 0;
    uptr = dsk_dev.units + current_disk;
    if (io == 0) {
        if (current_byte[current_disk] >= DSK_SECTSIZE) {
            /* physically read the sector */
            sim_debug(READ_MSG, &dsk_dev,
                      "DSK%i: " ADDRESS_FORMAT " IN 0x0a (READ) D%d T%d S%d\n",
                      current_disk, PCX, current_disk,
                      current_track[current_disk], current_sector[current_disk]);
            for (i = 0; i < DSK_SECTSIZE; i++)
                dskbuf[i] = 0;
            if (dskseek(uptr)) {
                if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK12 < warnLevelDSK)) {
                    warnDSK12++;
                    sim_debug(VERBOSE_MSG, &dsk_dev,
                              "DSK%i: " ADDRESS_FORMAT " fseek error D%d T%d S%d\n",
                              current_disk, PCX, current_disk,
                              current_track[current_disk], current_sector[current_disk]);
                }
            }
            rtn = sim_fread(dskbuf, 1, DSK_SECTSIZE, uptr -> fileref);
            if (rtn != DSK_SECTSIZE) {
                if ((dsk_dev.dctrl & VERBOSE_MSG) && (warnDSK12 < warnLevelDSK)) {
                    warnDSK12++;
                    sim_debug(VERBOSE_MSG, &dsk_dev,
                              "DSK%i: " ADDRESS_FORMAT " sim_fread error D%d T%d S%d\n",
                              current_disk, PCX, current_disk,
                              current_track[current_disk], current_sector[current_disk]);
                }
            }
            current_byte[current_disk] = 0;
        }
        return dskbuf[current_byte[current_disk]++] & 0xff;
    }
    else {
        if (current_byte[current_disk] >= DSK_SECTSIZE)
            writebuf();     /* from above we have that current_disk < NUM_OF_DSK */
        else {
            dirty = TRUE;   /* this guarantees for the next call to writebuf that current_disk < NUM_OF_DSK */
            dskbuf[current_byte[current_disk]++] = data & 0xff;
        }
        return 0;   /* ignored since OUT */
    }
}
Exemple #3
0
/*
 * Initiate a compare operation on a disk.
 */
static enum dpio_status DPDiskIOCompare(UNIT *uptr)
{
  struct dpio_unit *iou = (struct dpio_unit *)uptr->up7;
  uint16 numcy = ((uptr->flags & UNIT_854) != 0) ? DP_854CY : DP_853CY;
  uint32 lba = DPLBA(iou);
  int i;

  if (iou->cylinder >= numcy)
    return DPIO_ADDRERR;

  /*
   * Report any error in the underlying container infrastructure as an
   * address error.
   */
  if (sim_fseeko(uptr->fileref, lba * DP_NUMBY, SEEK_SET) ||
      (sim_fread(iou->buf, sizeof(uint16), DP_NUMWD, uptr->fileref) != DP_NUMWD))
    return DPIO_ADDRERR;

  for (i = 0; i < DP_NUMWD; i++) {
    if (iou->buf[i] != LoadFromMem(iou->CWA))
      return DPIO_MISMATCH;

    iou->CWA++;
    if (iou->CWA == iou->LWA) {
      DPDiskIOIncSector(iou);
      return DPIO_DONE;
    }
  }
  DPDiskIOIncSector(iou);
  return DPIO_MORE;
}
Exemple #4
0
t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max)
{
uint32 f = MT_GET_FMT (uptr);
t_mtrlnt i, tbc, rbc;
t_addr opos;
t_stat st;

opos = uptr->pos;                                       /* old position */
if (st = sim_tape_rdlntf (uptr, &tbc))                  /* read rec lnt */
    return st;
*bc = rbc = MTR_L (tbc);                                /* strip error flag */
if (rbc > max) {                                        /* rec out of range? */
    MT_SET_PNU (uptr);
    uptr->pos = opos;
    return MTSE_INVRL;
    }
i = sim_fread (buf, sizeof (uint8), rbc, uptr->fileref);/* read record */
if (ferror (uptr->fileref)) {                           /* error? */
    MT_SET_PNU (uptr);
    uptr->pos = opos;
    return sim_tape_ioerr (uptr);
    }
for ( ; i < rbc; i++)                                   /* fill with 0's */
    buf[i] = 0;
if (f == MTUF_F_P7B)                                    /* p7b? strip SOR */
    buf[0] = buf[0] & P7B_DPAR;
return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
}
Exemple #5
0
int32 fdcdrv(int32 io, int32 data)
{
    static long pos;
    char buf[128];

    if (io) {                           /* write to DC-4 drive register */
        if (dsk_dev.dctrl & DEBUG_write)
            printf("\nfdcdrv: Drive selected %d cur_dsk=%d", data & 0x03, cur_dsk);
        if (cur_dsk == (data & 0x03)) 
            return 0;                   /* already selected */
        cur_dsk = data & 0x03;          /* only 2 drive select bits */
        if (dsk_dev.dctrl & DEBUG_write)
            printf("\nfdcdrv: Drive set to %d", cur_dsk);
        if ((dsk_unit[cur_dsk].flags & UNIT_ENABLE) == 0) {
            dsk_unit[cur_dsk].u3 |= WRPROT; /* set 1797 WPROT */
            if (dsk_dev.dctrl & DEBUG_write)
                printf("\nfdcdrv: Drive write protected");
        } else {
            dsk_unit[cur_dsk].u3 &= ~WRPROT; /* set 1797 not WPROT */
            if (dsk_dev.dctrl & DEBUG_write)
                printf("\nfdcdrv: Drive NOT write protected");
        }
        pos = 0x200;                    /* Read in SIR */
        if (dsk_dev.dctrl & DEBUG_read)
            printf("\nfdcdrv: Read pos = %ld ($%04X)", pos, (unsigned int) pos);
        sim_fseek(dsk_unit[cur_dsk].fileref, pos, 0); /* seek to offset */
        sim_fread(dsk_unit[cur_dsk].filebuf, SECSIZ, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
        dsk_unit[cur_dsk].u3 |= BUSY | DRQ; /* set DRQ & BUSY */
        dsk_unit[cur_dsk].pos = 0;      /* clear counter */
        spt = *(uint8 *)(dsk_unit[cur_dsk].filebuf + MAXSEC) & 0xFF;
        heds = 0;
        cpd = *(uint8 *)(dsk_unit[cur_dsk].filebuf + MAXCYL) & 0xFF;
        trksiz = spt * SECSIZ;
        dsksiz = trksiz * cpd;
        if (dsk_dev.dctrl & DEBUG_read)
            printf("\nfdcdrv: spt=%d heds=%d cpd=%d trksiz=%d dsksiz=%d flags=%08X u3=%08X",
                spt, heds, cpd, trksiz, dsksiz, dsk_unit[cur_dsk].flags, dsk_unit[cur_dsk].u3);
        return 0;
    } else {                            /* read from DC-4 drive register */
        if (dsk_dev.dctrl & DEBUG_read)
            printf("\nfdcdrv: Drive read as %02X", intrq);
        return intrq;
    }
}
Exemple #6
0
uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map)
{
t_addr tpos;
t_tpclnt bc;
uint32 i, objc;

if ((uptr == NULL) || (uptr->fileref == NULL))
    return 0;
for (objc = 0, tpos = 0;; ) {
    sim_fseek (uptr->fileref, tpos, SEEK_SET);
    i = sim_fread (&bc, sizeof (t_tpclnt), 1, uptr->fileref);
    if (i == 0)
        break;
    if (map)
        map[objc] = tpos;
    objc++;
    tpos = tpos + ((bc + 1) & ~1) + sizeof (t_tpclnt);
    }
if (map) map[objc] = tpos;
return objc;
}
Exemple #7
0
/* Read a sector from an IMD image. */
t_stat sectRead(DISK_INFO *myDisk,
             uint32 Cyl,
             uint32 Head,
             uint32 Sector,
             uint8 *buf,
             uint32 buflen,
             uint32 *flags,
             uint32 *readlen)
{
    uint32 sectorFileOffset;
    uint8 sectRecordType;
    uint8 start_sect;
    *readlen = 0;
    *flags = 0;

    /* Check parameters */
    if(myDisk == NULL) {
        *flags |= IMD_DISK_IO_ERROR_GENERAL;
        return(SCPE_IOERR);
    }

    if(sectSeek(myDisk, Cyl, Head) != SCPE_OK) {
        *flags |= IMD_DISK_IO_ERROR_GENERAL;
        return(SCPE_IOERR);
    }

    if(Sector > myDisk->track[Cyl][Head].nsects) {
        sim_debug(myDisk->debugmask, myDisk->device, "%s: invalid sector\n", __FUNCTION__);
        *flags |= IMD_DISK_IO_ERROR_GENERAL;
        return(SCPE_IOERR);
    }

    if(buflen < myDisk->track[Cyl][Head].sectsize) {
        sim_printf("%s: Reading C:%d/H:%d/S:%d, len=%d: user buffer too short, need %d\n", __FUNCTION__, Cyl, Head, Sector, buflen, myDisk->track[Cyl][Head].sectsize);
        *flags |= IMD_DISK_IO_ERROR_GENERAL;
        return(SCPE_IOERR);
    }

    start_sect = myDisk->track[Cyl][Head].start_sector;

    sectorFileOffset = myDisk->track[Cyl][Head].sectorOffsetMap[Sector-start_sect];

    sim_debug(myDisk->debugmask, myDisk->device, "Reading C:%d/H:%d/S:%d, len=%d, offset=0x%08x\n", Cyl, Head, Sector, buflen, sectorFileOffset);

    sim_fseek(myDisk->file, sectorFileOffset-1, SEEK_SET);

    sectRecordType = fgetc(myDisk->file);
    switch(sectRecordType) {
        case SECT_RECORD_UNAVAILABLE:   /* Data could not be read from the original media */
            *flags |= IMD_DISK_IO_ERROR_GENERAL;
            break;
        case SECT_RECORD_NORM_ERR:      /* Normal Data with read error */
        case SECT_RECORD_NORM_DAM_ERR:  /* Normal Data with deleted address mark with read error */
            *flags |= IMD_DISK_IO_ERROR_CRC;
        case SECT_RECORD_NORM:          /* Normal Data */
        case SECT_RECORD_NORM_DAM:      /* Normal Data with deleted address mark */

/*          sim_debug(myDisk->debugmask, myDisk->device, "Uncompressed Data\n"); */
            if (sim_fread(buf, 1, myDisk->track[Cyl][Head].sectsize, myDisk->file) != myDisk->track[Cyl][Head].sectsize) {
                sim_printf("SIM_IMD[%s]: sim_fread error for SECT_RECORD_NORM_DAM.\n", __FUNCTION__);
            }
            *readlen = myDisk->track[Cyl][Head].sectsize;
            break;
        case SECT_RECORD_NORM_COMP_ERR: /* Compressed Normal Data */
        case SECT_RECORD_NORM_DAM_COMP_ERR: /* Compressed Normal Data with deleted address mark */
            *flags |= IMD_DISK_IO_ERROR_CRC;
        case SECT_RECORD_NORM_COMP:     /* Compressed Normal Data */
        case SECT_RECORD_NORM_DAM_COMP: /* Compressed Normal Data with deleted address mark */
/*          sim_debug(myDisk->debugmask, myDisk->device, "Compressed Data\n"); */
            memset(buf, fgetc(myDisk->file), myDisk->track[Cyl][Head].sectsize);
            *readlen = myDisk->track[Cyl][Head].sectsize;
            *flags |= IMD_DISK_IO_COMPRESSED;
            break;
        default:
            sim_printf("ERROR: unrecognized sector record type %d\n", sectRecordType);
            break;
    }

    /* Set flags for deleted address mark. */
    switch(sectRecordType) {
        case SECT_RECORD_NORM_DAM:      /* Normal Data with deleted address mark */
        case SECT_RECORD_NORM_DAM_ERR:  /* Normal Data with deleted address mark with read error */
        case SECT_RECORD_NORM_DAM_COMP: /* Compressed Normal Data with deleted address mark */
        case SECT_RECORD_NORM_DAM_COMP_ERR: /* Compressed Normal Data with deleted address mark */
            *flags |= IMD_DISK_IO_DELETED_ADDR_MARK;
        default:
            break;
    }

    return(SCPE_OK);
}
Exemple #8
0
/* Parse an IMD image.  This sets up sim_imd to be able to do sector read/write and
 * track write.
 */
static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose)
{
    uint8 comment[256];
    uint8 sectorMap[256];
    uint8 sectorHeadMap[256];
    uint8 sectorCylMap[256];
    uint32 sectorSize, sectorHeadwithFlags, sectRecordType;
    uint32 i;
    uint8 start_sect;

    uint32 TotalSectorCount = 0;
    IMD_HEADER imd;

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

    memset(myDisk->track, 0, (sizeof(TRACK_INFO)*MAX_CYL*MAX_HEAD));

    if (commentParse(myDisk, comment, sizeof(comment)) != SCPE_OK) {
        return (SCPE_OPENERR);
    }

    if(isVerbose)
        sim_printf("%s\n", comment);

    myDisk->nsides = 1;
    myDisk->ntracks = 0;
    myDisk->flags = 0;      /* Make sure all flags are clear. */

    if(feof(myDisk->file)) {
        sim_printf("SIM_IMD: Disk image is blank, it must be formatted.\n");
        return (SCPE_OPENERR);
    }

    do {
        sim_debug(myDisk->debugmask, myDisk->device, "start of track %d at file offset %ld\n", myDisk->ntracks, ftell(myDisk->file));

        sim_fread(&imd, 1, 5, myDisk->file);
        if (feof(myDisk->file))
            break;
        sectorSize = 128 << imd.sectsize;
        sectorHeadwithFlags = imd.head; /*AGN save the head and flags */
        imd.head &= 1 ; /*AGN mask out flag bits to head 0 or 1 */

        sim_debug(myDisk->debugmask, myDisk->device, "Track %d:\n", myDisk->ntracks);
        sim_debug(myDisk->debugmask, myDisk->device, "\tMode=%d, Cyl=%d, Head=%d(%d), #sectors=%d, sectsize=%d (%d bytes)\n", imd.mode, imd.cyl, sectorHeadwithFlags, imd.head, imd.nsects, imd.sectsize, sectorSize);

        if (!headerOk(imd)) {
            sim_printf("SIM_IMD: Corrupt header.\n");
            return (SCPE_OPENERR);
        }

        if((imd.head + 1) > myDisk->nsides) {
            myDisk->nsides = imd.head + 1;
        }

        myDisk->track[imd.cyl][imd.head].mode = imd.mode;
        myDisk->track[imd.cyl][imd.head].nsects = imd.nsects;
        myDisk->track[imd.cyl][imd.head].sectsize = sectorSize;

        if (sim_fread(sectorMap, 1, imd.nsects, myDisk->file) != imd.nsects) {
            sim_printf("SIM_IMD: Corrupt file [Sector Map].\n");
            return (SCPE_OPENERR);
        }
        myDisk->track[imd.cyl][imd.head].start_sector = imd.nsects;
        sim_debug(myDisk->debugmask, myDisk->device, "\tSector Map: ");
        for(i=0;i<imd.nsects;i++) {
            sim_debug(myDisk->debugmask, myDisk->device, "%d ", sectorMap[i]);
            if(sectorMap[i] < myDisk->track[imd.cyl][imd.head].start_sector) {
                myDisk->track[imd.cyl][imd.head].start_sector = sectorMap[i];
            }
        }
        sim_debug(myDisk->debugmask, myDisk->device, ", Start Sector=%d", myDisk->track[imd.cyl][imd.head].start_sector);

        if(sectorHeadwithFlags & IMD_FLAG_SECT_HEAD_MAP) {
            if (sim_fread(sectorHeadMap, 1, imd.nsects, myDisk->file) != imd.nsects) {
                sim_printf("SIM_IMD: Corrupt file [Sector Head Map].\n");
                return (SCPE_OPENERR);
            }
            sim_debug(myDisk->debugmask, myDisk->device, "\tSector Head Map: ");
            for(i=0;i<imd.nsects;i++) {
                sim_debug(myDisk->debugmask, myDisk->device, "%d ", sectorHeadMap[i]);
            }
            sim_debug(myDisk->debugmask, myDisk->device, "\n");
        } else {
            /* Default Head is physical head for each sector */
            for(i=0;i<imd.nsects;i++) {
                sectorHeadMap[i] = imd.head;
            };
        }

        if(sectorHeadwithFlags & IMD_FLAG_SECT_CYL_MAP) {
            if (sim_fread(sectorCylMap, 1, imd.nsects, myDisk->file) != imd.nsects) {
                sim_printf("SIM_IMD: Corrupt file [Sector Cyl Map].\n");
                return (SCPE_OPENERR);
            }
            sim_debug(myDisk->debugmask, myDisk->device, "\tSector Cyl Map: ");
            for(i=0;i<imd.nsects;i++) {
                sim_debug(myDisk->debugmask, myDisk->device, "%d ", sectorCylMap[i]);
            }
            sim_debug(myDisk->debugmask, myDisk->device, "\n");
        } else {
            /* Default Cyl Map is physical cylinder for each sector */
            for(i=0;i<imd.nsects;i++) {
                sectorCylMap[i] = imd.cyl;
            }
        }

        sim_debug(myDisk->debugmask, myDisk->device, "\nSector data at offset 0x%08lx\n", ftell(myDisk->file));

        /* Build the table with location 0 being the start sector. */
        start_sect = myDisk->track[imd.cyl][imd.head].start_sector;

        /* Now read each sector */
        for(i=0;i<imd.nsects;i++) {
            TotalSectorCount++;
            sim_debug(myDisk->debugmask, myDisk->device, "Sector Phys: %d/Logical: %d: %d bytes: ", i, sectorMap[i], sectorSize);
            sectRecordType = fgetc(myDisk->file);
            /* AGN Logical head mapping */
            myDisk->track[imd.cyl][imd.head].logicalHead[i] = sectorHeadMap[i];
            /* AGN Logical cylinder mapping */
            myDisk->track[imd.cyl][imd.head].logicalCyl[i] = sectorCylMap[i];
            switch(sectRecordType) {
                case SECT_RECORD_UNAVAILABLE:   /* Data could not be read from the original media */
                    if (sectorMap[i]-start_sect < MAX_SPT)
                        myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = 0xBADBAD;
                    else {
                        sim_printf("SIM_IMD: ERROR: Illegal sector offset %d\n", sectorMap[i]-start_sect);
                        return (SCPE_OPENERR);
                    }
                    break;
                case SECT_RECORD_NORM:          /* Normal Data */
                case SECT_RECORD_NORM_DAM:      /* Normal Data with deleted address mark */
                case SECT_RECORD_NORM_ERR:      /* Normal Data with read error */
                case SECT_RECORD_NORM_DAM_ERR:  /* Normal Data with deleted address mark with read error */
/*                  sim_debug(myDisk->debugmask, myDisk->device, "Uncompressed Data\n"); */
                    if (sectorMap[i]-start_sect < MAX_SPT) {
                        myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file);
                        sim_fseek(myDisk->file, sectorSize, SEEK_CUR);
                    }
                    else {
                        sim_printf("SIM_IMD: ERROR: Illegal sector offset %d\n", sectorMap[i]-start_sect);
                        return (SCPE_OPENERR);
                    }
                    break;
                case SECT_RECORD_NORM_COMP:     /* Compressed Normal Data */
                case SECT_RECORD_NORM_DAM_COMP: /* Compressed Normal Data with deleted address mark */
                case SECT_RECORD_NORM_COMP_ERR: /* Compressed Normal Data */
                case SECT_RECORD_NORM_DAM_COMP_ERR: /* Compressed Normal Data with deleted address mark */
                    if (sectorMap[i]-start_sect < MAX_SPT) {
                        myDisk->track[imd.cyl][imd.head].sectorOffsetMap[sectorMap[i]-start_sect] = ftell(myDisk->file);
                        myDisk->flags |= FD_FLAG_WRITELOCK; /* Write-protect the disk if any sectors are compressed. */
                        if (1) {
                            uint8 cdata = fgetc(myDisk->file);

                            sim_debug(myDisk->debugmask, myDisk->device, "Compressed Data = 0x%02x\n", cdata);
                            }
                    }
                    else {
                        sim_printf("SIM_IMD: ERROR: Illegal sector offset %d\n", sectorMap[i]-start_sect);
                        return (SCPE_OPENERR);
                    }
                    break;
                default:
                    sim_printf("SIM_IMD: ERROR: unrecognized sector record type %d\n", sectRecordType);
                    return (SCPE_OPENERR);
                    break;
            }
            sim_debug(myDisk->debugmask, myDisk->device, "\n");
        }

        myDisk->ntracks++;
    } while (!feof(myDisk->file));

    sim_debug(myDisk->debugmask, myDisk->device, "Processed %d sectors\n", TotalSectorCount);

    for(i=0;i<myDisk->ntracks;i++) {
        uint8 j;
        sim_debug(myDisk->verbosedebugmask, myDisk->device, "Track %02d: ", i);
        for(j=0;j<imd.nsects;j++) {
            sim_debug(myDisk->verbosedebugmask, myDisk->device, "0x%06x ", myDisk->track[i][0].sectorOffsetMap[j]);
        }
        sim_debug(myDisk->verbosedebugmask, myDisk->device, "\n");
    }
    if(myDisk->flags & FD_FLAG_WRITELOCK) {
        sim_printf("Disk write-protected because the image contains compressed sectors. Use IMDU to uncompress.\n");
    }

    return SCPE_OK;
}
Exemple #9
0
int32 fdccmd(int32 io, int32 data)
{
	static int32 val = 0, val1 = NOTRDY, i;
    static long pos;
    UNIT *uptr;
 
	if ((dsk_unit[cur_dsk].flags & UNIT_ATT) == 0) { /* not attached */
		cur_flg[cur_dsk] |= NOTRDY;		/* set not ready flag */
		printf("Drive %d is not attached\n\r", cur_dsk);
		return 0;
	} else {
		cur_flg[cur_dsk] &= ~NOTRDY;	/* clear not ready flag */
	}	
	uptr = dsk_dev.units + cur_dsk;		/* get virtual drive address */
	if (io) {							/* write command to fdc */
		switch(data) {
			case 0x8C:					/* read command */
			case 0x9C:
#if DEBUG > 0
				printf("Read of disk %d, track %d, sector %d\n\r", 
					cur_dsk, cur_trk[cur_dsk], cur_sec[cur_dsk]);
#endif
				pos = TRAK_SIZE * cur_trk[cur_dsk]; /* calculate file offset */
				pos += SECT_SIZE * (cur_sec[cur_dsk] - 1);
#if DEBUG > 0
				printf("Read pos = %ld ($%04X)\n\r", pos, pos);
#endif
				sim_fseek(uptr -> fileref, pos, 0); /* seek to offset */
				sim_fread(dskbuf, 256, 1, uptr -> fileref); /* read in buffer */
				cur_flg[cur_dsk] |= BUSY | DRQ;	/* set DRQ & BUSY */
				i = cur_byt[cur_dsk] = 0;	/* clear counter */
				break;
			case 0xAC:					/* write command */
#if DEBUG > 0
				printf("Write of disk %d, track %d, sector %d\n\r", 
					cur_dsk, cur_trk[cur_dsk], cur_sec[cur_dsk]);
#endif
				if (cur_flg[cur_dsk] & WRPROT) {		
					printf("Drive %d is write-protected\n\r", cur_dsk);
				} else {
					pos = TRAK_SIZE * cur_trk[cur_dsk]; /* calculate file offset */
					pos += SECT_SIZE * (cur_sec[cur_dsk] - 1);
#if DEBUG > 1
					printf("Write pos = %ld ($%04X)\n\r", pos, pos);
#endif
					sim_fseek(uptr -> fileref, pos, 0); /* seek to offset */
					dptr = uptr;			/* save pointer for actual write */
					cur_flg[cur_dsk] |= BUSY | DRQ;/* set DRQ & BUSY */
					i = cur_byt[cur_dsk] = 0;	/* clear counter */
				}
				break;
			case 0x18:					/* seek command */
			case 0x1B:
				cur_trk[cur_dsk] = fdcbyte;	/* set track */
				cur_flg[cur_dsk] &= ~(BUSY | DRQ);	/* clear flags */
#if DEBUG > 0
				printf("Seek of disk %d, track %d\n\r", cur_dsk, fdcbyte);
#endif
				break;
			case 0x0B:					/* restore command */
				cur_trk[cur_dsk] = 0;	/* home the drive */
				cur_flg[cur_dsk] &= ~(BUSY | DRQ);	/* clear flags */
#if DEBUG > 0
				printf("Drive %d homed\n\r", cur_dsk);
#endif
				break;
			default:
				printf("Unknown FDC command %02XH\n\r", data);
		}
	} else {							/* read status from fdc */
		val = cur_flg[cur_dsk];			/* set return value */
		if (val1 == 0 && val == 0x03)	/* delay BUSY going high */
			val = 0x02;					/* set DRQ first */
		if (val != val1) {				/* now allow BUSY after on read */
			val1 = val;
#if DEBUG > 0
			printf("Drive %d status=%02X\n\r", cur_dsk, cur_flg[cur_dsk]);
#endif
		}
    }
	return val;
}
Exemple #10
0
#ifdef USE_VGI
if (rtn != MFDC_SECTOR_LEN)
#else
                            rtn = sim_fread(sdata.u.data, 1, 256, (pDrive->uptr)->fileref);
Exemple #11
0
t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc)
{
uint8 c;
t_bool all_eof;
uint32 f = MT_GET_FMT (uptr);
t_mtrlnt sbc;
t_tpclnt tpcbc;

MT_CLR_PNU (uptr);
if ((uptr->flags & UNIT_ATT) == 0)                      /* not attached? */
    return MTSE_UNATT;
sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);         /* set tape pos */
switch (f) {                                            /* switch on fmt */

    case MTUF_F_STD: case MTUF_F_E11:
        do {
            sim_fread (bc, sizeof (t_mtrlnt), 1, uptr->fileref);    /* read rec lnt */
            sbc = MTR_L (*bc);                          /* save rec lnt */
            if (ferror (uptr->fileref)) {               /* error? */
                MT_SET_PNU (uptr);                      /* pos not upd */
                return sim_tape_ioerr (uptr);
                }
            if (feof (uptr->fileref) || (*bc == MTR_EOM)) {     /* eof or eom? */
                MT_SET_PNU (uptr);                      /* pos not upd */
                return MTSE_EOM;
                }
            uptr->pos = uptr->pos + sizeof (t_mtrlnt);  /* spc over rec lnt */
            if (*bc == MTR_TMK)                         /* tape mark? */
                return MTSE_TMK;
            if (*bc == MTR_FHGAP) {                     /* half gap? */
                uptr->pos = uptr->pos + sizeof (t_mtrlnt) / 2;  /* half space fwd */
                sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* resync */
                }
            else if (*bc != MTR_GAP)
                uptr->pos = uptr->pos + sizeof (t_mtrlnt) +     /* spc over record */
                    ((f == MTUF_F_STD)? ((sbc + 1) & ~1): sbc);
            }
        while ((*bc == MTR_GAP) || (*bc == MTR_FHGAP));
        break;

    case MTUF_F_TPC:
        sim_fread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref);
        *bc = tpcbc;                                    /* save rec lnt */
        if (ferror (uptr->fileref)) {                   /* error? */
            MT_SET_PNU (uptr);                          /* pos not upd */
            return sim_tape_ioerr (uptr);
            }
        if (feof (uptr->fileref)) {                     /* eof? */
            MT_SET_PNU (uptr);                          /* pos not upd */
            return MTSE_EOM;
            }
        uptr->pos = uptr->pos + sizeof (t_tpclnt);      /* spc over reclnt */
        if (tpcbc == TPC_TMK)                           /* tape mark? */
            return MTSE_TMK;
        uptr->pos = uptr->pos + ((tpcbc + 1) & ~1);     /* spc over record */
        break;

    case MTUF_F_P7B:
        for (sbc = 0, all_eof = 1; ; sbc++) {           /* loop thru record */
            sim_fread (&c, sizeof (uint8), 1, uptr->fileref);
            if (ferror (uptr->fileref)) {               /* error? */
                MT_SET_PNU (uptr);                      /* pos not upd */
                return sim_tape_ioerr (uptr);
                }
            if (feof (uptr->fileref)) {                 /* eof? */
                if (sbc == 0)                           /* no data? eom */
                    return MTSE_EOM;
                break;                                  /* treat like eor */
                }
            if ((sbc != 0) && (c & P7B_SOR))            /* next record? */
                break;
            if ((c & P7B_DPAR) != P7B_EOF)
                all_eof = 0;
            }
        *bc = sbc;                                      /* save rec lnt */
        sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for read */
        uptr->pos = uptr->pos + sbc;                    /* spc over record */
        if (all_eof)                                    /* tape mark? */
            return MTSE_TMK;
        break;

    default:
        return MTSE_FMT;
        }

return MTSE_OK;
}
Exemple #12
0
static uint8 MFDC_Read(const uint32 Addr)
{
    uint8 cData;
    MFDC_DRIVE_INFO *pDrive;
    int32 rtn;

    cData = 0x00;

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

    switch(Addr & 0x3) {
        case 0:
            if(mfdc_info->read_in_progress == FALSE) {
                pDrive->sector_wait_count++;
                if(pDrive->sector_wait_count > 10) {
                    pDrive->sector++;
                    pDrive->sector &= 0x0F;     /* Max of 16 sectors */
                    mfdc_info->wr_latch = 0;    /* on new sector, disable the write latch */
                    DBG_PRINT(("Head over sector %d" NLP, pDrive->sector));
                    pDrive->sector_wait_count = 0;
                }
            }

            cData = (pDrive->sector) & 0xF;  /* [3:0] current sector */
            cData |= (JUMPER_W10 << 4);
            cData |= ((~JUMPER_W9) & 1) << 5;
            cData |= (0 << 6);      /* Sector Interrupt Flag, reset by RESET command or Interrupt Disable */
            cData |= (1 << 7);      /* Sector Flag */
            mfdc_info->xfr_flag = 1;    /* Drive has data */
            mfdc_info->datacount = 0;
            sim_debug(STATUS_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " RD Sector Register = 0x%02x\n", PCX, cData);
            break;
        case 1:
            cData  = (mfdc_info->sel_drive & 0x3);  /* [1:0] selected drive */
            cData |= (!mfdc_info->selected << 2);   /* [2] drive is selected */
            cData |= (pDrive->track == 0) ? 0x08 : 0; /* [3] TK0 */
            pDrive->wp = ((pDrive->uptr)->flags & UNIT_MFDC_WLK) ? 1 : 0;
            cData |= (pDrive->wp << 4); /* [4] Write Protect */
            cData |= (pDrive->ready << 5); /* [5] Drive Ready */
            cData |= (0 << 6); /* [6] PINTE from S-100 Bus */
            cData |= (mfdc_info->xfr_flag << 7); /* [7] Transfer Flag */

            sim_debug(STATUS_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " RD Status = 0x%02x\n", PCX, cData);
            break;
        case 2:
        case 3:
            if(mfdc_info->datacount == 0) {
                unsigned int i, checksum;
                unsigned long sec_offset;
                uint32 flags;
                uint32 readlen;

                /* Clear out unused portion of sector. */
                memset(&sdata.u.unused[0], 0x00, 10);

                sdata.u.sync = 0xFF;
                sdata.u.header[0] = pDrive->track;
                sdata.u.header[1] = pDrive->sector;

                sim_debug(RD_DATA_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " RD Data T:%d S:[%d]\n", PCX, pDrive->track, pDrive->sector);

#ifdef USE_VGI
                sec_offset = (pDrive->track * MFDC_SECTOR_LEN * 16) + \
                             (pDrive->sector * MFDC_SECTOR_LEN);
#else
                sec_offset = (pDrive->track * 4096) + \
                             (pDrive->sector * 256);
#endif /* USE_VGI */

                if (!(pDrive->uptr->flags & UNIT_ATT)) {
                    if (pDrive->uptr->flags & UNIT_MFDC_VERBOSE)
                        printf("MFDC: " ADDRESS_FORMAT " MDSK%i not attached." NLP, PCX,
                            mfdc_info->sel_drive);
                    return 0x00;
                }

                switch((pDrive->uptr)->u3)
                {
                    case IMAGE_TYPE_IMD:
                        if(pDrive->imd == NULL) {
                            printf(".imd is NULL!" NLP);
                        }
/*                      printf("%s: Read: imd=%p" NLP, __FUNCTION__, pDrive->imd); */
                        sectRead(pDrive->imd,
                            pDrive->track,
                            mfdc_info->head,
                            pDrive->sector,
                            sdata.u.data,
                            256,
                            &flags,
                            &readlen);
                        break;
                    case IMAGE_TYPE_DSK:
                        if(pDrive->uptr->fileref == NULL) {
                            printf(".fileref is NULL!" NLP);
                        } else {
                            sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
#ifdef USE_VGI
                            rtn = sim_fread(sdata.raw, 1, MFDC_SECTOR_LEN, (pDrive->uptr)->fileref);
                            if (rtn != MFDC_SECTOR_LEN)
#else
                            rtn = sim_fread(sdata.u.data, 1, 256, (pDrive->uptr)->fileref);
                            if (rtn != 256)
#endif /* USE_VGI */
                                printf("%s: sim_fread error. Result = %d." NLP, __FUNCTION__, rtn);
                        }
                        break;
                    case IMAGE_TYPE_CPT:
                        printf("%s: CPT Format not supported" NLP, __FUNCTION__);
                        break;
                    default:
                        printf("%s: Unknown image Format" NLP, __FUNCTION__);
                        break;
                }

/*              printf("%d/%d @%04x Len=%04x" NLP, sdata.u.header[0], sdata.u.header[1], sdata.u.header[9]<<8|sdata.u.header[8], sdata.u.header[11]<<8|sdata.u.header[10]); */

                adc(0,0); /* clear Carry bit */
                checksum = 0;

                /* Checksum everything except the sync byte */
                for(i=1;i<269;i++) {
                    checksum = adc(checksum, sdata.raw[i]);
                }

                sdata.u.checksum = checksum & 0xFF;
/*              DBG_PRINT(("Checksum=%x" NLP, sdata.u.checksum)); */
                mfdc_info->read_in_progress = TRUE;
            }

            cData = sdata.raw[mfdc_info->datacount];

            mfdc_info->datacount++;
            if(mfdc_info->datacount == 270) {
                sim_debug(RD_DATA_MSG, &mfdc_dev, "MFDC: " ADDRESS_FORMAT " Read sector [%d] complete\n", PCX, pDrive->sector);
                mfdc_info->read_in_progress = FALSE;
            }

/*          DBG_PRINT(("MFDC: " ADDRESS_FORMAT " RD Data Sector %d[%03d]: 0x%02x" NLP, PCX, pDrive->sector, mfdc_info->datacount, cData)); */
            break;
    }

    return (cData);
}
Exemple #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;
}
Exemple #14
0
t_stat sim_tape_rdlntr (UNIT *uptr, t_mtrlnt *bc)
{
uint8 c;
t_bool all_eof;
uint32 f = MT_GET_FMT (uptr);
t_addr ppos;
t_mtrlnt sbc;
t_tpclnt tpcbc;

MT_CLR_PNU (uptr);
if ((uptr->flags & UNIT_ATT) == 0)                      /* not attached? */
    return MTSE_UNATT;
if (sim_tape_bot (uptr))                                /* at BOT? */
    return MTSE_BOT;
switch (f) {                                            /* switch on fmt */

    case MTUF_F_STD: case MTUF_F_E11:
        do {
            sim_fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
            sim_fread (bc, sizeof (t_mtrlnt), 1, uptr->fileref);    /* read rec lnt */
            sbc = MTR_L (*bc);
            if (ferror (uptr->fileref))                 /* error? */
                return sim_tape_ioerr (uptr);
            if (feof (uptr->fileref))                   /* eof? */
                return MTSE_EOM;
            uptr->pos = uptr->pos - sizeof (t_mtrlnt);  /* spc over rec lnt */
            if (*bc == MTR_EOM)                         /* eom? */
                return MTSE_EOM;
            if (*bc == MTR_TMK)                         /* tape mark? */
                return MTSE_TMK;
            if ((*bc & MTR_M_RHGAP) == MTR_RHGAP) {     /* half gap? */
                uptr->pos = uptr->pos + sizeof (t_mtrlnt) / 2;  /* half space rev */
                sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* resync */
                }
            else if (*bc != MTR_GAP) {
                uptr->pos = uptr->pos - sizeof (t_mtrlnt) - /* spc over record */
                    ((f == MTUF_F_STD)? ((sbc + 1) & ~1): sbc);
                sim_fseek (uptr->fileref, uptr->pos + sizeof (t_mtrlnt), SEEK_SET);
                }
            else if (sim_tape_bot (uptr))               /* backed into BOT? */
                return MTSE_BOT;
        }
        while ((*bc == MTR_GAP) || (*bc == MTR_RHGAP));
        break;

    case MTUF_F_TPC:
        ppos = sim_tape_tpc_fnd (uptr, (t_addr *) uptr->filebuf); /* find prev rec */
        sim_fseek (uptr->fileref, ppos, SEEK_SET);      /* position */
        sim_fread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref);
        *bc = tpcbc;                                    /* save rec lnt */
        if (ferror (uptr->fileref))                     /* error? */
            return sim_tape_ioerr (uptr);
        if (feof (uptr->fileref))                       /* eof? */
            return MTSE_EOM;
        uptr->pos = ppos;                               /* spc over record */
        if (*bc == MTR_TMK)                             /* tape mark? */
            return MTSE_TMK;
        sim_fseek (uptr->fileref, uptr->pos + sizeof (t_tpclnt), SEEK_SET);
        break;

    case MTUF_F_P7B:
        for (sbc = 1, all_eof = 1; (t_addr) sbc <= uptr->pos ; sbc++) {
            sim_fseek (uptr->fileref, uptr->pos - sbc, SEEK_SET);
            sim_fread (&c, sizeof (uint8), 1, uptr->fileref);
            if (ferror (uptr->fileref))                 /* error? */
                return sim_tape_ioerr (uptr);
            if (feof (uptr->fileref))                   /* eof? */
                return MTSE_EOM;
            if ((c & P7B_DPAR) != P7B_EOF)
                all_eof = 0;
            if (c & P7B_SOR)                            /* start of record? */
                break;
            }
        uptr->pos = uptr->pos - sbc;                    /* update position */
        *bc = sbc;                                      /* save rec lnt */
        sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for read */
        if (all_eof)                                    /* tape mark? */
            return MTSE_TMK;
        break;

    default:
        return MTSE_FMT;
        }

return MTSE_OK;
}
Exemple #15
0
static uint8 MDSAD_Read(const uint32 Addr)
{
    uint8 cData;
    uint8 ds;
    MDSAD_DRIVE_INFO *pDrive;
    int32 rtn;

    cData = 0x00;

    pDrive = &mdsad_info->drive[mdsad_info->orders.ds];

    switch( (Addr & 0x300) >> 8 ) {
        case MDSAD_READ_ROM:
            cData = mdsad_rom[Addr & 0xFF];
            break;
        case MDSAD_WRITE_DATA:
        {
            if(mdsad_info->datacount == 0) {
                sim_debug(WR_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                          " WRITE Start:  Drive: %d, Track=%d, Head=%d, Sector=%d\n",
                          PCX, mdsad_info->orders.ds, pDrive->track,
                          mdsad_info->orders.ss, pDrive->sector);

                sec_offset = calculate_mdsad_sec_offset(pDrive->track,
                    mdsad_info->orders.ss,
                    pDrive->sector);

            }

            DBG_PRINT(("MDSAD: " ADDRESS_FORMAT
                " WRITE-DATA[offset:%06x+%03x]=%02x" NLP,
                PCX, sec_offset, mdsad_info->datacount, Addr & 0xFF));
            mdsad_info->datacount++;
            if(mdsad_info->datacount < MDSAD_RAW_LEN)
                sdata.raw[mdsad_info->datacount] = Addr & 0xFF;

            if(mdsad_info->datacount == (MDSAD_RAW_LEN - 1)) {
                sim_debug(WR_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                          " Write Complete\n", PCX);

                if ((pDrive->uptr == NULL) || (pDrive->uptr->fileref == NULL)) {
                    sim_debug(WR_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " Drive: %d not attached - write ignored.\n", PCX, mdsad_info->orders.ds);
                    return 0x00;
                }
                if(mdsad_dev.dctrl & WR_DATA_DETAIL_MSG)
                    showdata(FALSE);
                switch((pDrive->uptr)->u3)
                {
                    case IMAGE_TYPE_DSK:
                        if(pDrive->uptr->fileref == NULL) {
                            printf(".fileref is NULL!" NLP);
                        } else {
                            sim_fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);
                            sim_fwrite(sdata.u.data, 1, MDSAD_SECTOR_LEN,
                                (pDrive->uptr)->fileref);
                        }
                        break;
                    case IMAGE_TYPE_CPT:
                        printf("%s: CPT Format not supported" NLP, __FUNCTION__);
                        break;
                    default:
                        printf("%s: Unknown image Format" NLP, __FUNCTION__);
                        break;
                }
            }
            break;
        }
        case MDSAD_CTLR_ORDERS:
            mdsad_info->orders.dd = (Addr & 0x80) >> 7;
            mdsad_info->orders.ss = (Addr & 0x40) >> 6;
            mdsad_info->orders.dp = (Addr & 0x20) >> 5;
            mdsad_info->orders.st = (Addr & 0x10) >> 4;
            mdsad_info->orders.ds = (Addr & 0x0F);

            ds = mdsad_info->orders.ds;
            switch(mdsad_info->orders.ds) {
                case 0:
                case 1:
                    mdsad_info->orders.ds = 0;
                    break;
                case 2:
                    mdsad_info->orders.ds = 1;
                    break;
                case 4:
                    mdsad_info->orders.ds = 2;
                    break;
                case 8:
                    mdsad_info->orders.ds = 3;
                    break;
            }

            if(mdsad_info->orders.ds != (mdsad_info->orders.ds & 0x03)) {
                sim_debug(ERROR_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                          " Controller Orders update drive %x\n", PCX, mdsad_info->orders.ds);
                mdsad_info->orders.ds &= 0x03;
            }
            sim_debug(ORDERS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                      " Controller Orders: Drive=%x[%x], DD=%d, SS=%d, DP=%d, ST=%d\n",
                      PCX, mdsad_info->orders.ds, ds, mdsad_info->orders.dd,
                      mdsad_info->orders.ss, mdsad_info->orders.dp, mdsad_info->orders.st);

            /* use latest selected drive */
            pDrive = &mdsad_info->drive[mdsad_info->orders.ds];

            if(mdsad_info->orders.st == 1) {
                if(mdsad_info->orders.dp == 0) {
                    sim_debug(SEEK_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " Step out: Track=%d%s\n", PCX, pDrive->track,
                              pDrive->track == 0 ? "[Warn: already at 0]" : "");
                    if(pDrive->track > 0) /* anything to do? */
                        pDrive->track--;
                } else {
                    sim_debug(SEEK_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " Step  in: Track=%d%s\n", PCX, pDrive->track,
                              pDrive->track == (MDSAD_TRACKS - 1) ? "[Warn: already at highest track]" : "");
                    if(pDrive->track < (MDSAD_TRACKS - 1)) /* anything to do? */
                        pDrive->track++;
                }
            }
            /* always update t0 */
            mdsad_info->b_status.t0 = (pDrive->track == 0);
            break;
        case MDSAD_CTLR_COMMAND:
/*          sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT " DM=%x\n", PCX, (Addr & 0xF0) >> 4); */
            switch(Addr & 0x0F) {
                case MDSAD_CMD_MOTORS_ON:
                    sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " CMD=Motors On\n", PCX);
                    mdsad_info->com_status.mo = 1;      /* Turn motors on */
                    break;

                case MDSAD_CMD_NOP:
                    pDrive->sector_wait_count++;
                    switch(pDrive->sector_wait_count) {
                        case 10:
                        {
                            mdsad_info->com_status.sf = 1;
                            mdsad_info->a_status.wi = 0;
                            mdsad_info->a_status.re = 0;
                            mdsad_info->a_status.bd = 0;
                            pDrive->sector_wait_count = 0;
                            pDrive->sector++;
                            if(pDrive->sector >= MDSAD_SECTORS_PER_TRACK) {
                                pDrive->sector = 0;
                                mdsad_info->com_status.ix = 1;
                            } else {
                                mdsad_info->com_status.ix = 0;
                            }
                            break;
                        }
                        case 2:
                            mdsad_info->a_status.wi = 1;
                            break;
                        case 3:
                            mdsad_info->a_status.re = 1;
                            mdsad_info->a_status.bd = 1;
                            break;
                        default:
                            break;
                    }
                    break;
                case MDSAD_CMD_RESET_SF:
                    sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " CMD=Reset Sector Flag\n", PCX);
                    mdsad_info->com_status.sf = 0;
                    mdsad_info->datacount = 0;
                    break;
                case MDSAD_CMD_INTR_DIS:
                    sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " CMD=Disarm Interrupt\n", PCX);
                    mdsad_info->int_enable = 0;
                    break;
                case MDSAD_CMD_INTR_ARM:
                    sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " CMD=Arm Interrupt\n", PCX);
                    mdsad_info->int_enable = 1;
                    break;
                case MDSAD_CMD_SET_BODY:
                    sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " CMD=Set Body (Diagnostic)\n", PCX);
                    break;
                case MDSAD_CMD_BEGIN_WR:
                    sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " CMD=Begin Write\n", PCX);
                    break;
                case MDSAD_CMD_RESET:
                    sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " CMD=Reset Controller\n", PCX);
                    mdsad_info->com_status.mo = 0;  /* Turn motors off */
                    break;
                default:
                    sim_debug(CMD_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " Unsupported CMD=0x%x\n", PCX, Addr & 0x0F);
                    break;
            }

            /* Always Double-Density for now... */
            mdsad_info->com_status.dd = 1;

            cData  = (mdsad_info->com_status.sf & 1) << 7;
            cData |= (mdsad_info->com_status.ix & 1) << 6;
            cData |= (mdsad_info->com_status.dd & 1) << 5;
            cData |= (mdsad_info->com_status.mo & 1) << 4;

            mdsad_info->c_status.sc = pDrive->sector;

            switch( (Addr & 0xF0) >> 4) {
                case MDSAD_A_STATUS:    /* A-STATUS */
                    cData |= (mdsad_info->a_status.wi & 1) << 3;
                    cData |= (mdsad_info->a_status.re & 1) << 2;
                    cData |= (mdsad_info->a_status.sp & 1) << 1;
                    cData |= (mdsad_info->a_status.bd & 1);
                    sim_debug(STATUS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " A-Status = <%s %s %s %s %s %s %s %s>\n",
                              PCX,
                              cData & MDSAD_A_SF ? "SF" : "  ",
                              cData & MDSAD_A_IX ? "IX" : "  ",
                              cData & MDSAD_A_DD ? "DD" : "  ",
                              cData & MDSAD_A_MO ? "MO" : "  ",
                              cData & MDSAD_A_WI ? "WI" : "  ",
                              cData & MDSAD_A_RE ? "RE" : "  ",
                              cData & MDSAD_A_SP ? "SP" : "  ",
                              cData & MDSAD_A_BD ? "BD" : "  ");
                    break;
                case MDSAD_B_STATUS:    /* B-STATUS */
                    cData |= (mdsad_info->b_status.wr & 1) << 3;
                    cData |= (mdsad_info->b_status.sp & 1) << 2;
                    cData |= (mdsad_info->b_status.wp & 1) << 1;
                    cData |= (mdsad_info->b_status.t0 & 1);
                    sim_debug(STATUS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " B-Status = <%s %s %s %s %s %s %s %s>\n",
                              PCX,
                              cData & MDSAD_B_SF ? "SF" : "  ",
                              cData & MDSAD_B_IX ? "IX" : "  ",
                              cData & MDSAD_B_DD ? "DD" : "  ",
                              cData & MDSAD_B_MO ? "MO" : "  ",
                              cData & MDSAD_B_WR ? "WR" : "  ",
                              cData & MDSAD_B_SP ? "SP" : "  ",
                              cData & MDSAD_B_WP ? "WP" : "  ",
                              cData & MDSAD_B_T0 ? "T0" : "  ");
                    break;
                case MDSAD_C_STATUS:    /* C-STATUS */
                    cData |= (mdsad_info->c_status.sc & 0xF);
                    sim_debug(STATUS_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                              " C-Status = <%s %s %s %s %i>\n",
                              PCX,
                              cData & MDSAD_C_SF ? "SF" : "  ",
                              cData & MDSAD_C_IX ? "IX" : "  ",
                              cData & MDSAD_C_DD ? "DD" : "  ",
                              cData & MDSAD_C_MO ? "MO" : "  ",
                              cData & MDSAD_C_SC);
                    break;
                case MDSAD_READ_DATA:   /* READ DATA */
                {
                    if(mdsad_info->datacount == 0) {
                        sim_debug(RD_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                                  " READ Start:  Drive: %d, Track=%d, Head=%d, Sector=%d\n",
                                  PCX,
                                  mdsad_info->orders.ds,
                                  pDrive->track,
                                  mdsad_info->orders.ss,
                                  pDrive->sector);

                            checksum = 0;

                            sec_offset = calculate_mdsad_sec_offset(pDrive->track,
                                mdsad_info->orders.ss,
                                pDrive->sector);

                            if ((pDrive->uptr == NULL) ||
                                    (pDrive->uptr->fileref == NULL)) {
                                sim_debug(RD_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                                          " Drive: %d not attached - read ignored.\n",
                                          PCX, mdsad_info->orders.ds);
                                return 0xe5;
                            }

                            switch((pDrive->uptr)->u3)
                            {
                                case IMAGE_TYPE_DSK:
                                    if(pDrive->uptr->fileref == NULL) {
                                        printf(".fileref is NULL!" NLP);
                                    } else {
                                        sim_fseek((pDrive->uptr)->fileref,
                                            sec_offset, SEEK_SET);
                                        rtn = sim_fread(&sdata.u.data[0], 1, MDSAD_SECTOR_LEN,
                                            (pDrive->uptr)->fileref);
                                        if (rtn != MDSAD_SECTOR_LEN) {
                                            sim_debug(ERROR_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                                                      " READ: sim_fread error.\n", PCX);
                                        }
                                    }
                                    break;
                                case IMAGE_TYPE_CPT:
                                    printf("%s: CPT Format not supported"
                                        NLP, __FUNCTION__);
                                    break;
                                default:
                                    printf("%s: Unknown image Format"
                                        NLP, __FUNCTION__);
                                    break;
                            }
                            if(mdsad_dev.dctrl & RD_DATA_DETAIL_MSG)
                                showdata(TRUE);
                    }

                    if(mdsad_info->datacount < MDSAD_SECTOR_LEN) {
                        cData = sdata.u.data[mdsad_info->datacount];

                        /* Exclusive OR */
                        checksum ^= cData;
                        /* Rotate Left Circular */
                        checksum = ((checksum << 1) | ((checksum & 0x80) != 0)) & 0xff;

                        DBG_PRINT(("MDSAD: " ADDRESS_FORMAT
                            " READ-DATA[offset:%06x+%03x]=%02x" NLP,
                            PCX, sec_offset, mdsad_info->datacount, cData));
                    } else { /* checksum */
                        cData = checksum;
                        sim_debug(RD_DATA_MSG, &mdsad_dev, "MDSAD: " ADDRESS_FORMAT
                                  " READ-DATA: Checksum is: 0x%02x\n",
                                  PCX, cData);
                    }

                    mdsad_info->datacount++;
                    break;
                }
                default:
                    DBG_PRINT(("MDSAD: " ADDRESS_FORMAT
                        " Invalid DM=%x" NLP, PCX, Addr & 0xF));
                    break;
            }

            break;
    }
    return (cData);
}
Exemple #16
0
static uint8 DISK3_Write(const uint32 Addr, uint8 cData)
{
    uint32 next_link;
    uint8 result = DISK3_STATUS_COMPLETE;
    uint8 i;
    uint8 cmd;

    DISK3_DRIVE_INFO *pDrive;

    for(i = 0; i < DISK3_IOPB_LEN; i++) {
        disk3_info->iopb[i] = GetByteDMA(disk3_info->link_addr + i);
    }

    cmd = disk3_info->iopb[DISK3_IOPB_CMD];
    disk3_info->sel_drive = disk3_info->iopb[DISK3_IOPB_DRIVE] & 0x03;

    disk3_info->dma_addr = disk3_info->iopb[0x0A];
    disk3_info->dma_addr |= disk3_info->iopb[0x0B] << 8;
    disk3_info->dma_addr |= disk3_info->iopb[0x0C] << 16;

    next_link  = disk3_info->iopb[DISK3_IOPB_LINK+0];
    next_link |= disk3_info->iopb[DISK3_IOPB_LINK+1] << 8;
    next_link |= disk3_info->iopb[DISK3_IOPB_LINK+2] << 16;

    sim_debug(VERBOSE_MSG, &disk3_dev, "DISK3[%d]: LINK=0x%05x, NEXT=0x%05x, CMD=%x, %s DMA@0x%05x\n",
              disk3_info->sel_drive,
              disk3_info->link_addr,
              next_link,
              disk3_info->iopb[DISK3_IOPB_CMD] & DISK3_CMD_MASK,
              (disk3_info->iopb[DISK3_IOPB_CMD] & DISK3_REQUEST_IRQ) ? "IRQ" : "POLL",
              disk3_info->dma_addr);

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

    if(pDrive->ready) {

        /* Perform command */
        switch(cmd & DISK3_CMD_MASK) {
            case DISK3_CODE_NOOP:
                sim_debug(VERBOSE_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                          " NOOP\n", disk3_info->sel_drive, PCX);
                break;
            case DISK3_CODE_VERSION:
                break;
            case DISK3_CODE_GLOBAL:
                sim_debug(CMD_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                          " GLOBAL\n", disk3_info->sel_drive, PCX);

                disk3_info->mode = disk3_info->iopb[DISK3_IOPB_ARG1];
                disk3_info->retries = disk3_info->iopb[DISK3_IOPB_ARG2];
                disk3_info->ndrives = disk3_info->iopb[DISK3_IOPB_ARG3];

                sim_debug(SPECIFY_MSG, &disk3_dev, "        Mode: 0x%02x\n", disk3_info->mode);
                sim_debug(SPECIFY_MSG, &disk3_dev, "   # Retries: 0x%02x\n", disk3_info->retries);
                sim_debug(SPECIFY_MSG, &disk3_dev, "    # Drives: 0x%02x\n", disk3_info->ndrives);

                if(disk3_info->mode == DISK3_MODE_ABS) {
                    sim_debug(ERROR_MSG, &disk3_dev, "DISK3: Absolute addressing not supported.\n");
                }

                break;
            case DISK3_CODE_SPECIFY:
                {
                    uint8 specify_data[22];
                    sim_debug(CMD_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                              " SPECIFY\n", disk3_info->sel_drive, PCX);

                    for(i = 0; i < 22; i++) {
                        specify_data[i] = GetByteDMA(disk3_info->dma_addr + i);
                    }

                    pDrive->sectsize = specify_data[4] | (specify_data[5] << 8);
                    pDrive->nsectors = specify_data[6] | (specify_data[7] << 8);
                    pDrive->nheads = specify_data[8] | (specify_data[9] << 8);
                    pDrive->ntracks = specify_data[10] | (specify_data[11] << 8);
                    pDrive->res_tracks = specify_data[18] | (specify_data[19] << 8);

                    sim_debug(SPECIFY_MSG, &disk3_dev, "    Sectsize: %d\n", pDrive->sectsize);
                    sim_debug(SPECIFY_MSG, &disk3_dev, "     Sectors: %d\n", pDrive->nsectors);
                    sim_debug(SPECIFY_MSG, &disk3_dev, "       Heads: %d\n", pDrive->nheads);
                    sim_debug(SPECIFY_MSG, &disk3_dev, "      Tracks: %d\n", pDrive->ntracks);
                    sim_debug(SPECIFY_MSG, &disk3_dev, "    Reserved: %d\n", pDrive->res_tracks);
                    break;
                }
            case DISK3_CODE_HOME:
                pDrive->track = 0;
                sim_debug(SEEK_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                          " HOME\n", disk3_info->sel_drive, PCX);
                break;
            case DISK3_CODE_SEEK:
                pDrive->track = disk3_info->iopb[DISK3_IOPB_ARG1];
                pDrive->track |= (disk3_info->iopb[DISK3_IOPB_ARG2] << 8);

                if(pDrive->track > pDrive->ntracks) {
                    sim_debug(ERROR_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                              " SEEK ERROR %d not found\n", disk3_info->sel_drive, PCX, pDrive->track);
                    pDrive->track = pDrive->ntracks - 1;
                    result = DISK3_STATUS_TIMEOUT;
                } else {
                    sim_debug(SEEK_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                              " SEEK %d\n", disk3_info->sel_drive, PCX, pDrive->track);
                }
                break;
            case DISK3_CODE_READ_HDR:
            {
                sim_debug(CMD_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                          " READ HEADER: %d\n", pDrive->track, PCX, pDrive->track >> 8);
                PutByteDMA(disk3_info->dma_addr + 0, pDrive->track & 0xFF);
                PutByteDMA(disk3_info->dma_addr + 1, (pDrive->track >> 8) & 0xFF);
                PutByteDMA(disk3_info->dma_addr + 2, 0);
                PutByteDMA(disk3_info->dma_addr + 3, 1);

                break;
            }
            case DISK3_CODE_READWRITE:
            {
                uint32 track_len;
                uint32 xfr_len;
                uint32 file_offset;
                uint32 xfr_count = 0;
                uint8 *dataBuffer;
                size_t rtn;

                if(disk3_info->mode == DISK3_MODE_ABS) {
                    sim_debug(ERROR_MSG, &disk3_dev, "DISK3: Absolute addressing not supported.\n");
                    break;
                }

                pDrive->cur_sect = disk3_info->iopb[DISK3_IOPB_ARG2] | (disk3_info->iopb[DISK3_IOPB_ARG3] << 8);
                pDrive->cur_track = disk3_info->iopb[DISK3_IOPB_ARG4] | (disk3_info->iopb[DISK3_IOPB_ARG5] << 8);
                pDrive->xfr_nsects = disk3_info->iopb[DISK3_IOPB_ARG6] | (disk3_info->iopb[DISK3_IOPB_ARG7] << 8);

                track_len = pDrive->nsectors * pDrive->sectsize;

                file_offset = (pDrive->cur_track * track_len); /* Calculate offset based on current track */
                file_offset += pDrive->cur_sect * pDrive->sectsize;

                xfr_len = pDrive->xfr_nsects * pDrive->sectsize;

                dataBuffer = malloc(xfr_len);

                sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET);

                if(disk3_info->iopb[DISK3_IOPB_ARG1] == 1) { /* Read */
                    rtn = sim_fread(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref);

                    sim_debug(RD_DATA_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                              "  READ @0x%05x T:%04d/S:%04d/#:%d %s\n",
                              disk3_info->sel_drive,
                              PCX,
                              disk3_info->dma_addr,
                              pDrive->cur_track,
                              pDrive->cur_sect,
                              pDrive->xfr_nsects,
                              rtn == (size_t)xfr_len ? "OK" : "NOK" );


                    /* Perform DMA Transfer */
                    for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) {
                        PutByteDMA(disk3_info->dma_addr + xfr_count, dataBuffer[xfr_count]);
                    }
                } else { /* Write */
                    sim_debug(WR_DATA_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                              " WRITE @0x%05x T:%04d/S:%04d/#:%d\n", disk3_info->sel_drive, PCX, disk3_info->dma_addr, pDrive->cur_track, pDrive->cur_sect, pDrive->xfr_nsects );

                    /* Perform DMA Transfer */
                    for(xfr_count = 0;xfr_count < xfr_len; xfr_count++) {
                        dataBuffer[xfr_count] = GetByteDMA(disk3_info->dma_addr + xfr_count);
                    }

                    sim_fwrite(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref);
                }

                free(dataBuffer);
                /* Update Track/Sector in IOPB */
                pDrive->cur_sect += pDrive->xfr_nsects;
                if(pDrive->cur_sect >= pDrive->nsectors) {
                    pDrive->cur_sect = pDrive->cur_sect % pDrive->nsectors;
                    pDrive->cur_track++;
                }
                disk3_info->iopb[DISK3_IOPB_ARG2] = pDrive->cur_sect & 0xFF;
                disk3_info->iopb[DISK3_IOPB_ARG3] = (pDrive->cur_sect >> 8) & 0xFF;
                disk3_info->iopb[DISK3_IOPB_ARG4] = pDrive->cur_track & 0xFF;
                disk3_info->iopb[DISK3_IOPB_ARG5] = (pDrive->cur_track >> 8) & 0xFF;
                disk3_info->iopb[DISK3_IOPB_ARG6] = 0;
                disk3_info->iopb[DISK3_IOPB_ARG7] = 0;

                /* Update the DATA field in the IOPB */
                disk3_info->dma_addr += xfr_len;
                disk3_info->iopb[DISK3_IOPB_DATA+0] = disk3_info->dma_addr & 0xFF;
                disk3_info->iopb[DISK3_IOPB_DATA+1] = (disk3_info->dma_addr >> 8) & 0xFF;
                disk3_info->iopb[DISK3_IOPB_DATA+2] = (disk3_info->dma_addr >> 16) & 0xFF;

                break;
                }
            case DISK3_CODE_FORMAT:
            {
                uint32 data_len;
                uint32 file_offset;
                uint8 *fmtBuffer;

                data_len = pDrive->nsectors * pDrive->sectsize;

                sim_debug(WR_DATA_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                          " FORMAT T:%d/H:%d/Fill=0x%02x/Len=%d\n",
                          disk3_info->sel_drive,
                          PCX,
                          pDrive->track,
                          disk3_info->iopb[DISK3_IOPB_ARG3],
                          disk3_info->iopb[DISK3_IOPB_ARG2],
                          data_len);

                file_offset = (pDrive->track * (pDrive->nheads) * data_len); /* Calculate offset based on current track */
                file_offset += (disk3_info->iopb[DISK3_IOPB_ARG3] * data_len);

                fmtBuffer = malloc(data_len);
                memset(fmtBuffer, disk3_info->iopb[DISK3_IOPB_ARG2], data_len);

                sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET);
                sim_fwrite(fmtBuffer, 1, data_len, (pDrive->uptr)->fileref);

                free(fmtBuffer);

                break;
            }
            case DISK3_CODE_SET_MAP:
                break;
            case DISK3_CODE_RELOCATE:
            case DISK3_CODE_FORMAT_BAD:
            case DISK3_CODE_STATUS:
            case DISK3_CODE_SELECT:
            case DISK3_CODE_EXAMINE:
            case DISK3_CODE_MODIFY:
            default:
                sim_debug(ERROR_MSG, &disk3_dev, "DISK3[%d]: " ADDRESS_FORMAT
                          " CMD=%x Unsupported\n",
                          disk3_info->sel_drive,
                          PCX,
                          cmd & DISK3_CMD_MASK);
                break;
        }
    } else { /* Drive not ready */
Exemple #17
0
int32 fdccmd(int32 io, int32 data)
{
    static int32 val = 0, val1 = NOTRDY;
    static long pos;
 
    if ((dsk_unit[cur_dsk].flags & UNIT_ATT) == 0) { /* not attached */
        dsk_unit[cur_dsk].u3 |= NOTRDY; /* set not ready flag */
        if (dsk_dev.dctrl & DEBUG_flow)
            printf("\nfdccmd: Drive %d is not attached", cur_dsk);
        return 0;
    } else {
        dsk_unit[cur_dsk].u3 &= ~NOTRDY; /* clear not ready flag */
    }
    if (io) {                           /* write command to fdc */
        switch(data) {
            case 0x8C:                  /* read command */
            case 0x9C:
                if (dsk_dev.dctrl & DEBUG_read)
                    printf("\nfdccmd: Read of disk %d, track %d, sector %d", 
                        cur_dsk, dsk_unit[cur_dsk].u4, dsk_unit[cur_dsk].u5);
                pos = trksiz * dsk_unit[cur_dsk].u4; /* calculate file offset */
                pos += SECSIZ * (dsk_unit[cur_dsk].u5 - 1);
                if (dsk_dev.dctrl & DEBUG_read)
                    printf("\nfdccmd: Read pos = %ld ($%08X)", pos, (unsigned int) pos);
                sim_fseek(dsk_unit[cur_dsk].fileref, pos, 0); /* seek to offset */
                sim_fread(dsk_unit[cur_dsk].filebuf, SECSIZ, 1, dsk_unit[cur_dsk].fileref); /* read in buffer */
                dsk_unit[cur_dsk].u3 |= BUSY | DRQ; /* set DRQ & BUSY */
                dsk_unit[cur_dsk].pos = 0; /* clear counter */
                break;
            case 0xAC:                  /* write command */
                if (dsk_dev.dctrl & DEBUG_write)
                    printf("\nfdccmd: Write of disk %d, track %d, sector %d",
                        cur_dsk, dsk_unit[cur_dsk].u4, dsk_unit[cur_dsk].u5);
                if (dsk_unit[cur_dsk].u3 & WRPROT) {	
                    printf("\nfdccmd: Drive %d is write-protected", cur_dsk);
                } else {
                    pos = trksiz * dsk_unit[cur_dsk].u4; /* calculate file offset */
                    pos += SECSIZ * (dsk_unit[cur_dsk].u5 - 1);
                    if (dsk_dev.dctrl & DEBUG_write)
                        printf("\nfdccmd: Write pos = %ld ($%08X)", pos, (unsigned int) pos);
                    sim_fseek(dsk_unit[cur_dsk].fileref, pos, 0); /* seek to offset */
                    wrt_flag = 1;           /* set write flag */
                    dsk_unit[cur_dsk].u3 |= BUSY | DRQ;/* set DRQ & BUSY */
                    dsk_unit[cur_dsk].pos = 0; /* clear counter */
                }
                break;
            case 0x18:                  /* seek command */
            case 0x1B:
                dsk_unit[cur_dsk].u4 = fdcbyte; /* set track */
                dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
                if (dsk_dev.dctrl & DEBUG_flow)
                    printf("\nfdccmd: Seek of disk %d, track %d", cur_dsk, fdcbyte);
                break;
            case 0x0B:                  /* restore command */
                dsk_unit[cur_dsk].u4 = 0;   /* home the drive */
                dsk_unit[cur_dsk].u3 &= ~(BUSY | DRQ); /* clear flags */
                if (dsk_dev.dctrl & DEBUG_flow)
                    printf("\nfdccmd: Drive %d homed", cur_dsk);
                break;
            case 0xF0:                  /* write track command */
                if (dsk_dev.dctrl & DEBUG_write)
                    printf("\nfdccmd: Write track command for drive %d", cur_dsk);
                break;
            default:
                printf("Unknown FDC command %02XH\n\r", data);
        }
    } else {                            /* read status from fdc */
        val = dsk_unit[cur_dsk].u3;     /* set return value */
        /* either print below will force the val to 0x43 forever.  timing problem in
        the 6800 disk driver software? */
//        if (dsk_dev.dctrl & DEBUG_flow)
//            printf("\nfdccmd: Exit Drive %d status=%02X", cur_dsk, val);
//            printf("\n%02X", val); //even this short fails it!
        if (val1 == 0 && ((val & (BUSY + DRQ)) == (BUSY + DRQ)))   /* delay BUSY going high */
            val &= ~BUSY;
        if (val != val1)                /* now allow BUSY after one read */
            val1 = val;
        if (dsk_dev.dctrl & DEBUG_flow)
            printf("\nfdccmd: Exit Drive %d status=%02X", cur_dsk, val);
    }
    return val;
}