dsk_err_t linux_format(DSK_DRIVER *self, DSK_GEOMETRY *geom, dsk_pcyl_t cylinder, dsk_phead_t head, const DSK_FORMAT *format, unsigned char filler) { struct floppy_raw_cmd raw_cmd; LINUX_DSK_DRIVER *lxself; int n; dsk_err_t err; unsigned char *buf; unsigned char mask = 0xFF; if (!self || !geom || !format) return DSK_ERR_BADPTR; if (self->dr_class != &dc_linux) return DSK_ERR_BADPTR; lxself = (LINUX_DSK_DRIVER *)self; if (lxself->lx_fd < 0) return DSK_ERR_NOTRDY; err = check_geom(lxself, geom); if (err) return err; if (geom->dg_fm) mask &= ~0x40; if (geom->dg_nomulti) mask &= ~0x80; buf = dsk_malloc(geom->dg_sectors * 4); if (!buf) return DSK_ERR_NOMEM; for (n = 0; n < geom->dg_sectors; n++) { buf[n*4] = format[n].fmt_cylinder; buf[n*4+1] = format[n].fmt_head; buf[n*4+2] = format[n].fmt_sector; buf[n*4+3] = dsk_get_psh(format[n].fmt_secsize); } init_raw_cmd(&raw_cmd); raw_cmd.flags = FD_RAW_WRITE | FD_RAW_INTR; if (cylinder != lxself->lx_cylinder) raw_cmd.flags |= FD_RAW_NEED_SEEK; raw_cmd.track = cylinder; if (lxself->lx_doublestep) raw_cmd.track *= 2; raw_cmd.rate = get_rate(geom); raw_cmd.length= 4 * geom->dg_sectors; raw_cmd.data = buf; raw_cmd.cmd[raw_cmd.cmd_count++] = FD_FORMAT & mask; raw_cmd.cmd[raw_cmd.cmd_count++] = encode_head(self, head); raw_cmd.cmd[raw_cmd.cmd_count++] = dsk_get_psh(geom->dg_secsize); raw_cmd.cmd[raw_cmd.cmd_count++] = geom->dg_sectors; raw_cmd.cmd[raw_cmd.cmd_count++] = geom->dg_fmtgap; raw_cmd.cmd[raw_cmd.cmd_count++] = filler; if (ioctl(lxself->lx_fd, FDRAWCMD, &raw_cmd) < 0) return DSK_ERR_SYSERR; memcpy(lxself->lx_status, raw_cmd.reply, 4); if (raw_cmd.reply[0] & 0x40) return xlt_error(raw_cmd.reply); lxself->lx_cylinder = cylinder; return DSK_ERR_OK; }
dsk_err_t ntwdm_format(DSK_DRIVER *self, DSK_GEOMETRY *geom, dsk_pcyl_t cylinder, dsk_phead_t head, const DSK_FORMAT *format, unsigned char filler) { NTWDM_DSK_DRIVER *ntself; unsigned u, fsize; dsk_err_t err; FD_FORMAT_PARAMS *pfp; FD_ID_HEADER *ph; if (!self || !geom || !format) return DSK_ERR_BADPTR; if (self->dr_class != &dc_ntwdm) return DSK_ERR_BADPTR; ntself = (NTWDM_DSK_DRIVER *)self; if (ntself->nt_hdisk == INVALID_HANDLE_VALUE) return DSK_ERR_NOTRDY; err = check_geom(ntself, geom); if (err) return err; fsize = sizeof(FD_FORMAT_PARAMS) + geom->dg_sectors * sizeof(FD_ID_HEADER); pfp = (FD_FORMAT_PARAMS *)dsk_malloc(fsize); if (!pfp) return DSK_ERR_NOMEM; pfp->flags = geom->dg_fm ? 0 : FD_OPTION_MFM; pfp->phead = encode_head(self, head); pfp->size = dsk_get_psh(geom->dg_secsize); pfp->sectors = geom->dg_sectors; pfp->gap = geom->dg_fmtgap; pfp->fill = filler; ph = (FD_ID_HEADER *)(pfp+1); for (u = 0; u < geom->dg_sectors; u++) { ph[u].cyl = format[u].fmt_cylinder; ph[u].head = format[u].fmt_head; ph[u].sector = format[u].fmt_sector; ph[u].size = dsk_get_psh(format[u].fmt_secsize); } if (cylinder != ntself->nt_cylinder) { UCHAR cyl = ntself->nt_doublestep ? cylinder*2 : cylinder; if (!DeviceIoControl(ntself->nt_hdisk, IOCTL_FDCMD_SEEK, &cyl, sizeof(cyl), NULL, 0, &dwRet, NULL)) return xlt_error(GetLastError()); ntself->nt_cylinder = cylinder; } if (!DeviceIoControl(ntself->nt_hdisk, IOCTL_FDCMD_FORMAT_TRACK, pfp, fsize, NULL, 0, &dwRet, NULL)) return xlt_error(GetLastError()); return DSK_ERR_OK; }
STDMETHODIMP CDisk::ltrkid(IGeometry *g, long track, short *count, VARIANT *buffer) { DSK_GEOMETRY geom; DSK_FORMAT *fmt; unsigned char *buf; dsk_err_t err; dsk_psect_t n, acount = 0; HRESULT hr; g_to_dg(g, &geom); err = dsk_ltrackids(m_driver, &geom, track, &acount, &fmt); if (acount) { if (count) *count = acount; buf = new unsigned char[4 * acount]; for (n = 0; n < acount; n++) { buf[n*4 ] = fmt[n].fmt_cylinder; buf[n*4+1] = fmt[n].fmt_head; buf[n*4+2] = fmt[n].fmt_sector; buf[n*4+3] = dsk_get_psh(fmt[n].fmt_secsize); } hr = PutBuffer(buf, buffer, 4 * acount, err); delete buf; return hr; } return MapError(err); }
dsk_err_t ntwdm_xwrite(DSK_DRIVER *self, const DSK_GEOMETRY *geom, const void *buf, dsk_pcyl_t cylinder, dsk_phead_t head, dsk_pcyl_t cyl_expected, dsk_phead_t head_expected, dsk_psect_t sector, size_t sector_size, int deleted) { NTWDM_DSK_DRIVER *ntself; FD_READ_WRITE_PARAMS rwp; LPVOID iobuffer; dsk_err_t err; DWORD dwIoCode; if (!self || !geom || !buf) return DSK_ERR_BADPTR; if (self->dr_class != &dc_ntwdm) return DSK_ERR_BADPTR; ntself = (NTWDM_DSK_DRIVER *)self; if (ntself->nt_hdisk == INVALID_HANDLE_VALUE) return DSK_ERR_NOTRDY; err = check_geom(ntself, geom); if (err) return err; rwp.flags = 0; if (!geom->dg_noskip) rwp.flags |= FD_OPTION_SKIP; /* Skip deleted data */ if (!geom->dg_fm) rwp.flags |= FD_OPTION_MFM; /* MFM recording mode */ if (!geom->dg_nomulti) rwp.flags |= FD_OPTION_MULTI_TRACK; /* Enable multitrack */ rwp.phead = encode_head(self, head); rwp.cyl = cyl_expected; rwp.head = head_expected; rwp.sector = sector; rwp.size = dsk_get_psh(sector_size); /* [JCE] v1.1.5 */ rwp.eot = sector+1; rwp.gap = geom->dg_rwgap; rwp.datalen = (sector_size < 255) ? sector_size : 0xFF; if (cylinder != ntself->nt_cylinder) { UCHAR cyl = ntself->nt_doublestep ? cylinder*2 : cylinder; if (!DeviceIoControl(ntself->nt_hdisk, IOCTL_FDCMD_SEEK, &cyl, sizeof(cyl), NULL, 0, &dwRet, NULL)) return xlt_error(GetLastError()); ntself->nt_cylinder = cylinder; } /* v1.1.11: Use passed sector size, not geometry sector size */ iobuffer = VirtualAlloc(NULL, sector_size, MEM_COMMIT, PAGE_READWRITE); if (!iobuffer) return DSK_ERR_NOMEM; memcpy(iobuffer, buf, sector_size); dwIoCode = deleted ? IOCTL_FDCMD_WRITE_DELETED_DATA : IOCTL_FDCMD_WRITE_DATA; if (!DeviceIoControl(ntself->nt_hdisk, dwIoCode, &rwp, sizeof(rwp), iobuffer, sector_size, &dwRet, NULL)) err = xlt_error(GetLastError()); VirtualFree(iobuffer, 0, MEM_RELEASE); return err; }
dsk_err_t linux_xread(DSK_DRIVER *self, const DSK_GEOMETRY *geom, void *buf, dsk_pcyl_t cylinder, dsk_phead_t head, dsk_pcyl_t cyl_expected, dsk_phead_t head_expected, dsk_psect_t sector, size_t sector_size, int *deleted) { struct floppy_raw_cmd raw_cmd; LINUX_DSK_DRIVER *lxself; dsk_err_t err; unsigned char mask = 0xFF; if (!self || !geom || !buf) return DSK_ERR_BADPTR; if (self->dr_class != &dc_linux) return DSK_ERR_BADPTR; lxself = (LINUX_DSK_DRIVER *)self; if (lxself->lx_fd < 0) return DSK_ERR_NOTRDY; err = check_geom(lxself, geom); if (err) return err; if (geom->dg_noskip) mask &= ~0x20; /* Don't skip deleted data */ if (geom->dg_fm) mask &= ~0x40; /* FM recording mode */ if (geom->dg_nomulti) mask &= ~0x80; /* Disable multitrack */ init_raw_cmd(&raw_cmd); raw_cmd.flags = FD_RAW_READ | FD_RAW_INTR; if (cylinder != lxself->lx_cylinder) raw_cmd.flags |= FD_RAW_NEED_SEEK; raw_cmd.track = cylinder; if (lxself->lx_doublestep) raw_cmd.track *= 2; raw_cmd.rate = get_rate(geom); raw_cmd.length= sector_size; raw_cmd.data = buf; if (deleted && (*deleted)) raw_cmd.cmd[raw_cmd.cmd_count++] = 0xEC & mask; else raw_cmd.cmd[raw_cmd.cmd_count++] = FD_READ & mask; raw_cmd.cmd[raw_cmd.cmd_count++] = encode_head(self, head); raw_cmd.cmd[raw_cmd.cmd_count++] = cyl_expected; raw_cmd.cmd[raw_cmd.cmd_count++] = head_expected; raw_cmd.cmd[raw_cmd.cmd_count++] = sector; raw_cmd.cmd[raw_cmd.cmd_count++] = dsk_get_psh(sector_size); raw_cmd.cmd[raw_cmd.cmd_count++] = sector; raw_cmd.cmd[raw_cmd.cmd_count++] = geom->dg_rwgap; raw_cmd.cmd[raw_cmd.cmd_count++] = (sector_size < 255) ? sector_size : 0xFF; if (ioctl(lxself->lx_fd, FDRAWCMD, &raw_cmd) < 0) return DSK_ERR_SYSERR; memcpy(lxself->lx_status, raw_cmd.reply, 4); if (raw_cmd.reply[0] & 0x40) return xlt_error(raw_cmd.reply); if (deleted) deleted[0] = (raw_cmd.reply[2] & 0x40) ? 1 : 0; lxself->lx_cylinder = cylinder; return DSK_ERR_OK; }
dsk_err_t win16_format(DSK_DRIVER *self, DSK_GEOMETRY *geom, dsk_pcyl_t cylinder, dsk_phead_t head, const DSK_FORMAT *format, unsigned char filler) { WIN16_DSK_DRIVER *w16self; union REGS reg; struct SREGS sreg; dsk_err_t err; unsigned char *trkbuf; unsigned int n, tries; unsigned char old_dpt[11]; if (!format || !self || !geom || self->dr_class != &dc_win16) return DSK_ERR_BADPTR; w16self = (WIN16_DSK_DRIVER *)self; if (w16self->w16_readonly) return DSK_ERR_RDONLY; trkbuf = dsk_malloc(4 * geom->dg_sectors); if (!trkbuf) return DSK_ERR_NOMEM; err = win16_checkgeom(w16self, geom, old_dpt, filler); if (err) { dsk_free(trkbuf); return err; } for (n = 0; n < geom->dg_sectors; n++) { trkbuf[4*n ] = (unsigned char)format[n].fmt_cylinder; trkbuf[4*n+1] = (unsigned char)format[n].fmt_head; trkbuf[4*n+2] = (unsigned char)format[n].fmt_sector; trkbuf[4*n+3] = dsk_get_psh(format[n].fmt_secsize); } for (tries = 0; tries < 3; tries++) { reg.h.ah = 0x05; reg.h.al = geom->dg_sectors; reg.x.bx = FP_OFF(trkbuf); reg.h.ch = cylinder; reg.h.cl = 0; reg.h.dh = head; reg.h.dl = w16self->w16_unit - 1; reg.x.cflag = 1; int86x(0x13, ®, ®, &sreg); if (!reg.x.cflag) break; } dsk_free(trkbuf); set_dpt(old_dpt); if ( reg.x.cflag ) return translate_int13_error(reg.h.ah); return DSK_ERR_OK; }
STDMETHODIMP CDisk::lsecid(IGeometry *g, long track, VARIANT *buffer) { DSK_GEOMETRY geom; DSK_FORMAT fmt; unsigned char buf[4]; dsk_err_t err; g_to_dg(g, &geom); err = dsk_lsecid(m_driver, &geom, track, &fmt); buf[0] = fmt.fmt_cylinder; buf[1] = fmt.fmt_head; buf[2] = fmt.fmt_sector; buf[3] = dsk_get_psh(fmt.fmt_secsize); return PutBuffer(buf, buffer, 4, err); }
static int win16_checkgeom(WIN16_DSK_DRIVER *w16self, const DSK_GEOMETRY *geom, unsigned char *old_dpt, unsigned char filler) { unsigned char new_dpt[11]; /* If get_dpt() fails, we're on Windows NT 5.x and can't change the geometry */ if (!get_dpt(old_dpt)) return DSK_ERR_OK; get_dpt(new_dpt); new_dpt[3] = dsk_get_psh(geom->dg_secsize); /* Bytes / sector */ new_dpt[4] = geom->dg_sectors; /* Sectors / track */ new_dpt[5] = geom->dg_rwgap; /* Read/write gap */ new_dpt[6] = (new_dpt[3]) ? 0xFF : 0x80; /* Data length */ new_dpt[7] = geom->dg_fmtgap; /* Format gap */ new_dpt[8] = filler; /* Format filler byte */ set_dpt(new_dpt); return DSK_ERR_OK; }
/* Read a track (FDC765 READ TRACK command) */ dsk_err_t linux_xtread(DSK_DRIVER *self, const DSK_GEOMETRY *geom, void *buf, dsk_pcyl_t cylinder, dsk_phead_t head, dsk_pcyl_t cyl_expected, dsk_phead_t head_expected) { struct floppy_raw_cmd raw_cmd; LINUX_DSK_DRIVER *lxself; dsk_err_t err; unsigned char mask = 0xFF; if (!self || !geom || !buf) return DSK_ERR_BADPTR; if (self->dr_class != &dc_linux) return DSK_ERR_BADPTR; lxself = (LINUX_DSK_DRIVER *)self; if (lxself->lx_fd < 0) return DSK_ERR_NOTRDY; err = check_geom(lxself, geom); if (err) return err; if (geom->dg_fm) mask &= ~0x40; if (geom->dg_nomulti) mask &= ~0x80; init_raw_cmd(&raw_cmd); raw_cmd.flags = FD_RAW_READ | FD_RAW_INTR; if (cylinder != lxself->lx_cylinder) raw_cmd.flags |= FD_RAW_NEED_SEEK; raw_cmd.track = cylinder; if (lxself->lx_doublestep) raw_cmd.track *= 2; raw_cmd.rate = get_rate(geom); raw_cmd.length= geom->dg_secsize * geom->dg_sectors; raw_cmd.data = buf; /* fdreg.h doesn't define the Read Track command, but here it is */ raw_cmd.cmd[raw_cmd.cmd_count++] = 0x62 & mask; raw_cmd.cmd[raw_cmd.cmd_count++] = encode_head(self, head); raw_cmd.cmd[raw_cmd.cmd_count++] = cyl_expected; raw_cmd.cmd[raw_cmd.cmd_count++] = head_expected; raw_cmd.cmd[raw_cmd.cmd_count++] = geom->dg_secbase; raw_cmd.cmd[raw_cmd.cmd_count++] = dsk_get_psh(geom->dg_secsize); raw_cmd.cmd[raw_cmd.cmd_count++] = geom->dg_secbase + geom->dg_sectors; raw_cmd.cmd[raw_cmd.cmd_count++] = geom->dg_rwgap; raw_cmd.cmd[raw_cmd.cmd_count++] = 0xFF; if (ioctl(lxself->lx_fd, FDRAWCMD, &raw_cmd) < 0) return DSK_ERR_SYSERR; memcpy(lxself->lx_status, raw_cmd.reply, 4); if (raw_cmd.reply[0] & 0x40) return xlt_error(raw_cmd.reply); lxself->lx_cylinder = cylinder; return DSK_ERR_OK; }
/* Read a track (FDC765 READ TRACK command) */ dsk_err_t ntwdm_xtread(DSK_DRIVER *self, const DSK_GEOMETRY *geom, void *buf, dsk_pcyl_t cylinder, dsk_phead_t head, dsk_pcyl_t cyl_expected, dsk_phead_t head_expected) { NTWDM_DSK_DRIVER *ntself; FD_READ_WRITE_PARAMS rwp; LPVOID iobuffer; DWORD tracksize; dsk_err_t err; if (!self || !geom || !buf) return DSK_ERR_BADPTR; if (self->dr_class != &dc_ntwdm) return DSK_ERR_BADPTR; ntself = (NTWDM_DSK_DRIVER *)self; if (ntself->nt_hdisk == INVALID_HANDLE_VALUE) return DSK_ERR_NOTRDY; err = check_geom(ntself, geom); if (err) return err; rwp.flags = 0; if (!geom->dg_fm) rwp.flags |= FD_OPTION_MFM; /* MFM recording mode */ if (!geom->dg_nomulti) rwp.flags |= FD_OPTION_MULTI_TRACK; /* Enable multitrack */ rwp.phead = encode_head(self, head); rwp.cyl = cyl_expected; rwp.head = head_expected; rwp.sector = geom->dg_secbase; rwp.size = dsk_get_psh(geom->dg_secsize); rwp.eot = geom->dg_secbase + geom->dg_sectors; rwp.gap = geom->dg_rwgap; rwp.datalen = 0xFF; tracksize = rwp.size * geom->dg_sectors; iobuffer = VirtualAlloc(NULL, tracksize, MEM_COMMIT, PAGE_READWRITE); if (!iobuffer) return DSK_ERR_NOMEM; if (!DeviceIoControl(ntself->nt_hdisk, IOCTL_FDCMD_READ_TRACK, &rwp, sizeof(rwp), iobuffer, geom->dg_secsize, &dwRet, NULL)) err = xlt_error(GetLastError()); memcpy(buf, iobuffer, geom->dg_secsize); VirtualFree(iobuffer, 0, MEM_RELEASE); return err; }
/* Format a track on a DSK. Can grow the DSK file. */ dsk_err_t ldbsdisk_format(DSK_DRIVER *pdriver, DSK_GEOMETRY *geom, dsk_pcyl_t cylinder, dsk_phead_t head, const DSK_FORMAT *format, unsigned char filler) { dsk_err_t err; LDBSDISK_DSK_DRIVER *self; dsk_psect_t sector; if (!format || !geom || !pdriver) return DSK_ERR_BADPTR; DC_CHECK(pdriver) self = (LDBSDISK_DSK_DRIVER *)pdriver; if (self->ld_readonly) return DSK_ERR_RDONLY; err = ldbsdisk_select_track(self, cylinder, head); if (err) return err; err = ldbsdisk_wipe_track(self); if (err) return err; /* The track's sectors have been removed. All that remains is * its header (empty). Create a new header that will replace it. */ self->ld_cur_track = ldbs_trackhead_alloc(geom->dg_sectors); if (!self->ld_cur_track) { return DSK_ERR_NOMEM; } self->ld_cur_cyl = cylinder; self->ld_cur_head = head; /* Populate the track header */ switch (geom->dg_datarate) { case RATE_SD: self->ld_cur_track->datarate = 1; break; case RATE_DD: self->ld_cur_track->datarate = 1; break; case RATE_HD: self->ld_cur_track->datarate = 2; break; case RATE_ED: self->ld_cur_track->datarate = 3; break; } switch (geom->dg_fm & RECMODE_MASK) { case RECMODE_FM: self->ld_cur_track->recmode = 1; break; case RECMODE_MFM: self->ld_cur_track->recmode = 2; break; } self->ld_cur_track->gap3 = geom->dg_fmtgap; self->ld_cur_track->filler = filler; self->ld_cur_track->dirty = 1; /* Write the sectors. Since they are all blank we don't actually * need to send them to the file */ for (sector = 0; sector < geom->dg_sectors; sector++) { LDBS_SECTOR_ENTRY *secent = &self->ld_cur_track->sector[sector]; secent->id_cyl = format[sector].fmt_cylinder; secent->id_head = format[sector].fmt_head; secent->id_sec = format[sector].fmt_sector; secent->id_psh = dsk_get_psh(format[sector].fmt_secsize); secent->st1 = 0; secent->st2 = 0; secent->copies = 0; secent->trail = 0; secent->offset = 0; /* XXX Can probably calculate a */ secent->filler = filler;/* default value for 'offset' */ } /* Write the track header */ err = ldbsdisk_flush_cur_track(self); if (err) return err; /* Populate bits of the DPB that the standard geometry probe * does not */ self->ld_dpb.spt = geom->dg_sectors * (geom->dg_secsize / 128); self->ld_dpb.psh = dsk_get_psh(geom->dg_secsize); self->ld_dpb.phm = (1 << self->ld_dpb.psh) - 1; err = ldbs_put_geometry(self->ld_store, geom); return err; }
STDMETHODIMP CLibrary::get_psh(long sectorsize, short *shift) { shift[0] = dsk_get_psh(sectorsize); return S_OK; }