STDMETHODIMP CDisk::lread(IGeometry *g, long lsect, VARIANT *var) { DSK_GEOMETRY geom; dsk_err_t err; HRESULT hr; g_to_dg(g, &geom); unsigned char *tmpbuf = (unsigned char *)dsk_malloc(geom.dg_secsize); if (!tmpbuf) return MapError(DSK_ERR_NOMEM); err = dsk_lread(m_driver, &geom, tmpbuf, lsect); hr = PutBuffer(tmpbuf, var, geom.dg_secsize, err); dsk_free(tmpbuf); return hr; }
LDPUBLIC32 dsk_err_t LDPUBLIC16 dsk_lcheck(DSK_DRIVER *self, const DSK_GEOMETRY *geom, const void *buf, dsk_lsect_t sector) { void *buf2; dsk_err_t e; if (!self || !geom || !buf || !self->dr_class) return DSK_ERR_BADPTR; buf2 = dsk_malloc(geom->dg_secsize); if (!buf2) return DSK_ERR_NOMEM; e = dsk_lread(self,geom,buf2,sector); if (e == 0 && memcmp(buf, buf2, geom->dg_secsize)) e = DSK_ERR_MISMATCH; dsk_free(buf2); return e; }
/* Probe the geometry of a disc. This will always use the boot sector. */ dsk_err_t dsk_defgetgeom(DSK_DRIVER *self, DSK_GEOMETRY *geom) { DSK_FORMAT secid; dsk_err_t e; unsigned char *secbuf; unsigned long dsksize; dsk_rate_t oldrate; if (!self || !geom || !self->dr_class) return DSK_ERR_BADPTR; memset(geom, 0, sizeof(*geom)); /* Switch to a minimal format */ e = dg_stdformat(geom, FMT_180K, NULL, NULL); if (e) return e; /* Allocate buffer for boot sector (512 bytes) */ secbuf = dsk_malloc(geom->dg_secsize); if (!secbuf) return DSK_ERR_NOMEM; /* Check for CPC6128 type discs. Also probe the data rate; if we get a * missing address mark, then the data rate is wrong. */ e = dg_stdformat(geom, FMT_180K, NULL, NULL); if (e) return e; e = dsk_lsecid(self, geom, 0, &secid); /* Check for HD discs */ if (e == DSK_ERR_NOADDR) { geom->dg_datarate = RATE_HD; e = dsk_lsecid(self, geom, 0, &secid); } /* Check for DD 5.25" disc in HD 5.25" drive */ if (e == DSK_ERR_NOADDR) { geom->dg_datarate = RATE_DD; e = dsk_lsecid(self, geom, 0, &secid); } /* Check for BBC micro DFS discs (FM encoded) */ if (e == DSK_ERR_NOADDR) { e = dg_stdformat(geom, FMT_BBC100, NULL, NULL); if (!e) e = dsk_lsecid(self, geom, 0, &secid); } if (!e) /* We could get the sector ID */ { if ((secid.fmt_sector & 0xF0) == 0x10 && secid.fmt_secsize == 512) /* Ampro 40 track double sided */ { dsk_free(secbuf); e = dg_stdformat(geom, FMT_AMPRO400D, NULL, NULL); if (!e) set_fixed_fs(self, FMT_AMPRO400D); return e; } if ((secid.fmt_sector & 0xC0) == 0x40 && secid.fmt_secsize == 512) /* CPC system */ { dsk_free(secbuf); e = dg_stdformat(geom, FMT_CPCSYS, NULL, NULL); if (!e) set_pcw_fs(self, geom, boot_cpcsys); return e; } if ((secid.fmt_sector & 0xC0) == 0xC0 && secid.fmt_secsize == 512) /* CPC data */ { dsk_free(secbuf); e = dg_stdformat(geom, FMT_CPCDATA, NULL, NULL); if (!e) set_pcw_fs(self, geom, boot_cpcdata); return e; } /* [v0.6.0] Handle discs with non-512 byte sectors */ if (secid.fmt_secsize == 256) { if (geom->dg_fm) /* BBC Micro FM floppy */ { unsigned int tot_sectors; e = dsk_lread(self, geom, secbuf, 1); tot_sectors = secbuf[7] + 256 * (secbuf[6] & 3); /* If disc is FM recorded but does not have 400 or 800 sectors, fail. */ if (e == DSK_ERR_OK && tot_sectors != 400 && tot_sectors != 800) e = DSK_ERR_BADFMT; geom->dg_cylinders = tot_sectors / (geom->dg_heads * geom->dg_sectors); dsk_free(secbuf); return e; } else /* MFM */ { e = dg_stdformat(geom, FMT_ACORN160, NULL, NULL); if (!e) e = dsk_lread(self, geom, secbuf, 0); if (e) { dsk_free(secbuf); return DSK_ERR_BADFMT; } /* Acorn ADFS discs have a size in sectors at 0xFC in the * first sector */ dsksize = secbuf[0xFC] + 256 * secbuf[0xFD] + 65536L * secbuf[0xFE]; dsk_free(secbuf); if (dsksize == 640) return dg_stdformat(geom, FMT_ACORN160, NULL, NULL); if (dsksize == 1280) return dg_stdformat(geom, FMT_ACORN320, NULL, NULL); if (dsksize == 2560) return dg_stdformat(geom, FMT_ACORN640, NULL, NULL); /* The DOS Plus boot floppy has 2720 here for * some reason */ if (dsksize == 2720) return dg_stdformat(geom, FMT_ACORN640, NULL, NULL); return DSK_ERR_BADFMT; } } if (secid.fmt_secsize == 1024) { dsk_rate_t rate; /* Ampro 80 track double sided */ if ((secid.fmt_sector & 0xF0) == 0x10) { dsk_free(secbuf); e = dg_stdformat(geom, FMT_AMPRO800, NULL, NULL); if (!e) set_fixed_fs(self, FMT_AMPRO800); return e; } /* Save the data rate, which we know to be correct */ rate = geom->dg_datarate; dsk_free(secbuf); /* Switch to a format with 1k sectors */ if (geom->dg_datarate == RATE_HD) e = dg_stdformat(geom, FMT_ACORN1600, NULL, NULL); else e = dg_stdformat(geom, FMT_ACORN800, NULL, NULL); if (e) return e; /* And restore it. */ geom->dg_datarate = rate; /* Allocate buffer for boot sector (1k bytes) */ secbuf = dsk_malloc(geom->dg_secsize); if (!secbuf) return DSK_ERR_NOMEM; e = dsk_lread(self, geom, secbuf, 0); if (!e) { dsksize = secbuf[0xFC] + 256 * secbuf[0xFD] + 65536L * secbuf[0xFE]; /* Check for 1600k-format */ if (geom->dg_datarate == RATE_HD) { /* XXX Need a better check for Acorn 1600k */ dsk_free(secbuf); return DSK_ERR_OK; } /* Check for D-format magic */ if (dsksize == 3200) { dsk_free(secbuf); return DSK_ERR_OK; } /* Check for E-format magic */ if (secbuf[4] == 10 && secbuf[5] == 5 && secbuf[6] == 2 && secbuf[7] == 2) { dsk_free(secbuf); return DSK_ERR_OK; } } /* Check for DOS Plus magic. DOS Plus has sectors * based at 1, not 0. */ geom->dg_secbase = 1; e = dsk_lread(self, geom, secbuf, 0); if (!e) { if (secbuf[0] == 0xFD && secbuf[1] == 0xFF && secbuf[2] == 0xFF) { dsk_free(secbuf); return DSK_ERR_OK; } } dsk_free(secbuf); return DSK_ERR_BADFMT; } /* Can't handle other discs with non-512 sector sizes. */ if ((secid.fmt_secsize != 512)) { dsk_free(secbuf); return DSK_ERR_BADFMT; } } /* If the driver couldn't do a READ ID call, then ignore it */ if (e == DSK_ERR_NOTIMPL) e = DSK_ERR_OK; /* Try to ID the disc from its boot sector */ if (!e) e = dsk_lread(self, geom, secbuf, 0); if (e) { dsk_free(secbuf); return e; } /* Save the data rate, because what we have is right, and what's * in the sector might not be. */ oldrate = geom->dg_datarate; /* We have the sector. Let's try to guess what it is */ e = dg_dosgeom(geom, secbuf); if (e == DSK_ERR_OK) { set_dos_fs(self, geom, secbuf + 11); } if (e == DSK_ERR_BADFMT) { /* If dg_pcwgeom succeeded, we have a CP/M filesystem with known parameters */ e = dg_pcwgeom(geom, secbuf); if (e == DSK_ERR_OK) set_pcw_fs(self, geom, secbuf); } if (e == DSK_ERR_BADFMT) { e = dg_aprigeom(geom, secbuf); if (e == DSK_ERR_OK) { set_dos_fs(self, geom, secbuf + 80); } } if (e == DSK_ERR_BADFMT) { e = dg_cpm86geom(geom, secbuf); if (e == DSK_ERR_OK) set_cpm86_fs(self, geom, secbuf); } /* Check for Oups Discovery 1 */ if (e == DSK_ERR_BADFMT) { e = dg_opusgeom(geom, secbuf); /* if (e == DSK_ERR_OK) set_opus_fs(self, geom, secbuf); */ } geom->dg_datarate = oldrate; dsk_free(secbuf); return e; }
int do_test(char *outfile, char *outtyp, char *outcomp, int forcehead) { DSK_PDRIVER outdr = NULL; dsk_err_t e; DSK_GEOMETRY dg, dg2; static DSK_FORMAT fmt[9] = { { 0, 0, 1, 512 }, { 0, 0, 3, 512 }, { 3, 1, 5, 512 }, { 0, 0, 7, 512 }, { 0, 0, 9, 512 }, { 0, 1, 2, 512 }, { 0, 0, 4, 512 }, { 2, 0, 6, 512 }, { 0, 0, 8, 512 }, }; static DSK_FORMAT fmt2[9] = { { 4, 0, 1, 512 }, { 4, 0, 3, 512 }, { 4, 0, 5, 512 }, { 4, 0, 7, 512 }, { 4, 0, 9, 512 }, { 4, 0, 2, 512 }, { 4, 0, 4, 512 }, { 4, 0, 6, 512 }, { 4, 0, 8, 512 }, }; DSK_FORMAT secid, *pfmt; char *comment; unsigned char status; dsk_psect_t count, n; char *optname; int value; dsk_reportfunc_set(report, report_end); dg_stdformat(&dg, FMT_180K, NULL, NULL); if (t80) dg.dg_cylinders = 80; printf("Checking dsk_creat\n"); e = dsk_creat(&outdr, outfile, outtyp, outcomp); CHECKERR("dsk_creat") else { dsk_set_option(outdr, "REMOTE:TESTING", 1); printf("Checking set_comment\n"); e = dsk_set_comment(outdr, "Example comment"); CHECKERR3("dsk_set_comment"); printf("Checking pformat\n"); e = dsk_pformat(outdr, &dg, 0, 0, fmt, 0xE5); CHECKERR("dsk_pformat") printf("Checking apform\n"); e = dsk_apform(outdr, &dg, 1, 0, 0xF6); CHECKERR("dsk_apform") printf("Checking lformat\n"); e = dsk_lformat(outdr, &dg, 2, fmt2, 0xD4); CHECKERR("dsk_pformat") printf("Checking ptrackids\n"); e = dsk_ptrackids(outdr, &dg, 0, 0, &count, &pfmt); CHECKERR("dsk_ptrackids") else { dsk_psect_t n; printf("Cyl Head Sec Size\n"); printf("-----------------\n"); for (n = 0; n < count; n++) { printf("%3d %3d %3d %4d\n", pfmt[n].fmt_cylinder, pfmt[n].fmt_head, pfmt[n].fmt_sector, (int)pfmt[n].fmt_secsize); } printf("-----------------\n"); dsk_free(pfmt); } memset(secbuf, 0, sizeof(secbuf)); memcpy(secbuf, spec180, sizeof(spec180)); printf("Checking dsk_lwrite\n"); e = dsk_lwrite(outdr, &dg, secbuf, 0); CHECKERR("dsk_lwrite") strcpy((char *)secbuf, "Cyl=3 Head=1 Sec=5"); printf("Checking dsk_xwrite\n"); e = dsk_xwrite(outdr, &dg, secbuf, 0, 0, 3, 1, 5, 512, 0); CHECKERR("dsk_xwrite") printf("Checking dsk_psecid\n"); e = dsk_psecid(outdr, &dg, 1, 0, &secid); CHECKERR("dsk_psecid") else { printf("%3d %3d %3d %4d\n", secid.fmt_cylinder, secid.fmt_head, secid.fmt_sector, (int)secid.fmt_secsize); if (secid.fmt_cylinder != 1 || secid.fmt_head != 0 || secid.fmt_secsize != 512) { ++failures; printf("-- mismatch!\n"); } } } if (outdr) { dsk_close(&outdr); CHECKERR("dsk_close") } printf("Checking dsk_open\n"); e = dsk_open(&outdr, outfile, outtyp, outcomp); CHECKERR("dsk_open") else { dsk_set_option(outdr, "REMOTE:TESTING", 1); printf("Checking dsk_getgeom\n"); e = dsk_getgeom(outdr, &dg2); if (t80 && dg2.dg_cylinders == 40) dg2.dg_cylinders = 80; CHECKERR("dsk_getgeom") else if (memcmp(&dg, &dg2, sizeof(dg))) { ++failures; printf("-- mismatch!\n"); printf("Cyls: %3d %3d\n", dg.dg_cylinders, dg2.dg_cylinders); printf("Heads: %3d %3d\n", dg.dg_heads, dg2.dg_heads); printf("Secs: %3d %3d\n", dg.dg_sectors, dg2.dg_sectors); } printf("Checking dsk_lread\n"); e = dsk_lread(outdr, &dg, secbuf, 0); CHECKERR("dsk_lread") else if (memcmp(secbuf, spec180, sizeof(spec180))) { ++failures; printf("-- mismatch!\n"); } printf("Checking dsk_xread\n"); e = dsk_xread(outdr, &dg, secbuf, 0, 0, 3, 1, 5, 512, NULL); CHECKERR("dsk_xread") else if (strcmp((char *)secbuf, "Cyl=3 Head=1 Sec=5")) { ++failures; printf("-- mismatch!\n"); } printf("Checking dsk_lseek\n"); e = dsk_lseek(outdr, &dg, 1); CHECKERR("dsk_lseek") printf("Checking dsk_drive_status\n"); e = dsk_drive_status(outdr, &dg, 0, &status); CHECKERR("dsk_drive_status") else printf("-- status=0x%02x\n", status); printf("Checking dsk_tread\n"); e = dsk_ptread(outdr, &dg, trkbuf, 1, 0); CHECKERR("dsk_ptread") else { for (n = 0; n < 4608; n++) if (trkbuf[n] != 0xF6) { printf("-- mismatch!\n"); ++failures; break; } } printf("Checking dsk_xtread\n"); e = dsk_xtread(outdr, &dg, trkbuf, 2, 0, 4, 0); CHECKERR("dsk_xtread") else { for (n = 0; n < 4608; n++) if (trkbuf[n] != 0xD4) { printf("-- mismatch!\n"); ++failures; break; } } printf("Checking dsk_option_enum\n"); e = dsk_option_enum(outdr, 0, &optname); CHECKERR("dsk_option_enum") else { printf("-- first option is %s\n", optname); } if (!optname) optname = "dummy"; printf("Checking dsk_get_option(%s)\n", optname); e = dsk_get_option(outdr, optname, &value); CHECKERR2("dsk_get_option") else { printf("-- value=%d\n", value); } printf("Checking dsk_set_option(example, 2)\n"); e = dsk_set_option(outdr, "example", 2); CHECKERR2("dsk_set_option") printf("Checking dsk_rtread\n"); e = dsk_rtread(outdr, &dg, trkbuf, 0, 0, 0); CHECKERR3("dsk_rtread") printf("Checking dsk_get_comment\n"); e = dsk_get_comment(outdr, &comment); CHECKERR3("dsk_get_comment") else if (comment) printf("-- comment=%s\n", comment); } if (outdr) { dsk_close(&outdr); CHECKERR("dsk_close") } printf("\n"); printf("Failed calls (failure important): %2d\n", failures); printf("Failed calls (failure unimportant): %2d\n", warnings); printf("Unimplemented functions: %2d\n", unimpl); printf("Unimplemented functions over RPC: %2d\n", rpcunimp); return failures; }