static int config_geom(Stream_t *Stream, struct device *dev, struct device *orig_dev, int media, struct bootsector *boot) { if(check_geom(dev, media, boot)) return 1; set_geom(boot,dev); return 0; }
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_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 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 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; }
/* 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; }
dsk_err_t linux_secid(DSK_DRIVER *self, const DSK_GEOMETRY *geom, dsk_pcyl_t cylinder, dsk_phead_t head, DSK_FORMAT *result) { struct floppy_raw_cmd raw_cmd; LINUX_DSK_DRIVER *lxself; unsigned char mask = 0xFF; dsk_err_t err; if (!self || !geom || !result) 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; if (geom->dg_fm) mask &= ~0x40; if (geom->dg_nomulti) mask &= ~0x80; /* [v0.8.3] It was necessary to add this check correctly to detect 100k * FM-recorded discs in a 5.25" drive */ err = check_geom(lxself, geom); if (err) return err; init_raw_cmd(&raw_cmd); raw_cmd.flags = 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.cmd[raw_cmd.cmd_count++] = FD_READID & mask; raw_cmd.cmd[raw_cmd.cmd_count++] = encode_head(self, head); 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); result->fmt_cylinder = raw_cmd.reply[3]; result->fmt_head = raw_cmd.reply[4]; result->fmt_sector = raw_cmd.reply[5]; result->fmt_secsize = 128 << raw_cmd.reply[6]; lxself->lx_cylinder = cylinder; return DSK_ERR_OK; }
dsk_err_t ntwdm_secid(DSK_DRIVER *self, const DSK_GEOMETRY *geom, dsk_pcyl_t cylinder, dsk_phead_t head, DSK_FORMAT *result) { NTWDM_DSK_DRIVER *ntself; FD_READ_ID_PARAMS rip; FD_CMD_RESULT res; dsk_err_t err; if (!self || !geom || !result) 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; 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; } rip.flags = geom->dg_fm ? 0 : FD_OPTION_MFM; rip.head = encode_head(self, head); if (!DeviceIoControl(ntself->nt_hdisk, IOCTL_FDCMD_READ_ID, &rip, sizeof(rip), &res, sizeof(res), &dwRet, NULL)) return xlt_error(GetLastError()); result->fmt_cylinder = res.cyl; result->fmt_head = res.head; result->fmt_sector = res.sector; result->fmt_secsize = 128 << res.size; return DSK_ERR_OK; }
Stream_t *XdfOpen(struct device *dev, char *name, int mode, char *errmsg, struct xdf_info *info) { Xdf_t *This; off_t begin, end; struct bootsector *boot; int type; if(dev && (!SHOULD_USE_XDF(dev) || check_geom(dev, 0, 0))) return NULL; This = New(Xdf_t); if (!This) return NULL; This->Class = &XdfClass; This->sector_size = 512; This->stretch = 0; precmd(dev); This->fd = open(name, mode | dev->mode | O_EXCL | O_NDELAY); if(This->fd < 0) { #ifdef HAVE_SNPRINTF snprintf(errmsg,199,"xdf floppy: open: \"%s\"", strerror(errno)); #else sprintf(errmsg,"xdf floppy: open: \"%s\"", strerror(errno)); #endif goto exit_0; } closeExec(This->fd); This->drive = GET_DRIVE(This->fd); if(This->drive < 0) goto exit_1; /* allocate buffer */ This->buffer = (char *) malloc(96 * 512); if (!This->buffer) goto exit_1; This->current_track = -1; This->track_map = (TrackMap_t *) calloc(96, sizeof(TrackMap_t)); if(!This->track_map) goto exit_2; /* lock the device on writes */ if (lock_dev(This->fd, mode == O_RDWR, dev)) { #ifdef HAVE_SNPRINTF snprintf(errmsg,199,"xdf floppy: device \"%s\" busy:", dev->name); #else sprintf(errmsg,"xdf floppy: device \"%s\" busy:", dev->name); #endif goto exit_3; } /* Before reading the boot sector, assume dummy values suitable * for reading at least the boot sector */ This->track_size = 11; This->track0_size = 6; This->rate = 0; This->FatSize = 9; This->RootDirSize = 1; decompose(This, 0, 512, &begin, &end, 0); if (load_data(This, 0, 1, 1) < 0 ) { This->rate = 0x43; if(load_data(This, 0, 1, 1) < 0) goto exit_3; } boot = (struct bootsector *) This->buffer; This->FatSize = WORD(fatlen); This->RootDirSize = WORD(dirents)/16; This->track_size = WORD(nsect); for(type=0; type < NUMBER(xdf_table); type++) { if(xdf_table[type].track_size == This->track_size) { This->map = xdf_table[type].map; This->track0_size = xdf_table[type].track0_size; This->rootskip = xdf_table[type].rootskip; break; } } if(type == NUMBER(xdf_table)) goto exit_3; if(info) { info->RootDirSize = This->RootDirSize; info->FatSize = This->FatSize; info->BadSectors = 5; } decompose(This, 0, 512, &begin, &end, 1); This->refs = 1; This->Next = 0; This->Buffer = 0; if(dev) set_geom(boot, dev); return (Stream_t *) This; exit_3: Free(This->track_map); exit_2: Free(This->buffer); exit_1: close(This->fd); exit_0: Free(This); return NULL; }