STATIC WORD mediachk(rqptr rp, ddt * pddt) { /* check floppy status */ if (pddt->ddt_descflags & DF_REFORMAT) { pddt->ddt_descflags &= ~DF_REFORMAT; rp->r_mcretcode = M_CHANGED; } else if (pddt->ddt_descflags & DF_DISKCHANGE) { pddt->ddt_descflags &= ~DF_DISKCHANGE; rp->r_mcretcode = M_DONT_KNOW; } else { rp->r_mcretcode = diskchange(pddt); if (rp->r_mcretcode == M_DONT_KNOW) { /* don't know but can check serial number ... */ ULONG serialno = pddt->ddt_serialno; COUNT result = getbpb(pddt); if (result != 0) return (result); if (serialno != pddt->ddt_serialno) rp->r_mcretcode = M_CHANGED; } } return S_DONE; }
STATIC WORD bldbpb(rqptr rp, ddt * pddt) { WORD result; if ((result = getbpb(pddt)) != 0) return result; rp->r_bpptr = &pddt->ddt_bpb; return S_DONE; }
STATIC WORD Genblkdev(rqptr rp, ddt * pddt) { int ret; unsigned descflags = pddt->ddt_descflags; #ifdef WITHFAT32 int extended = 0; if (rp->r_cat == 0x48) extended = 1; else #endif if (rp->r_cat != 8) return failure(E_CMD); switch (rp->r_fun) { case 0x40: /* set device parameters */ { struct gblkio FAR *gblp = rp->r_io; bpb *pbpb; pddt->ddt_type = gblp->gbio_devtype; pddt->ddt_descflags = (descflags & ~3) | (gblp->gbio_devattrib & 3) | (DF_DPCHANGED | DF_REFORMAT); pddt->ddt_ncyl = gblp->gbio_ncyl; /* use default dpb or current bpb? */ pbpb = (gblp->gbio_spcfunbit & 0x01) == 0 ? &pddt->ddt_defbpb : &pddt->ddt_bpb; #ifdef WITHFAT32 fmemcpy(pbpb, &gblp->gbio_bpb, extended ? sizeof(gblp->gbio_bpb) : BPB_SIZEOF); #else fmemcpy(pbpb, &gblp->gbio_bpb, sizeof(gblp->gbio_bpb)); #endif /*pbpb->bpb_nsector = gblp->gbio_nsecs; */ break; } case 0x41: /* write track - CHS is absolute not relative to partition start */ { struct gblkrw FAR *rw = rp->r_rw; ret = GenblockioAbs(pddt, LBA_WRITE, rw->gbrw_head, rw->gbrw_cyl, rw->gbrw_sector, rw->gbrw_nsecs, rw->gbrw_buffer); if (ret != 0) return dskerr(ret); } break; case 0x42: /* format/verify track */ { struct gblkfv FAR *fv = rp->r_fv; COUNT tracks; struct thst { UBYTE track, head, sector, type; } *addrfield, afentry; pddt->ddt_descflags &= ~DF_DPCHANGED; if (hd(descflags)) { /* XXX no low-level formatting for hard disks implemented */ fv->gbfv_spcfunbit = 1; /* "not supported by bios" */ return S_DONE; } if (descflags & DF_DPCHANGED) { /* first try newer setmediatype function */ ret = fl_setmediatype(pddt->ddt_driveno, pddt->ddt_ncyl, pddt->ddt_bpb.bpb_nsecs); if (ret == 0xc) { /* specified tracks, sectors/track not allowed for drive */ fv->gbfv_spcfunbit = 2; return dskerr(ret); } else if (ret == 0x80) { fv->gbfv_spcfunbit = 3; /* no disk in drive */ return dskerr(ret); } else if (ret != 0) /* otherwise, setdisktype */ { unsigned char type; unsigned tracks, secs; if ((fv->gbfv_spcfunbit & 1) && (ret = fl_read(pddt->ddt_driveno, 0, 0, 1, 1, DiskTransferBuffer)) != 0) { fv->gbfv_spcfunbit = 3; /* no disk in drive */ return dskerr(ret); } /* type 1: 320/360K disk in 360K drive */ /* type 2: 320/360K disk in 1.2M drive */ tracks = pddt->ddt_ncyl; secs = pddt->ddt_bpb.bpb_nsecs; type = pddt->ddt_type + 1; if (!(tracks == 40 && (secs == 9 || secs == 8) && type < 3)) { /* type 3: 1.2M disk in 1.2M drive */ /* type 4: 720kb disk in 1.44M or 720kb drive */ type++; if (type == 9) /* 1.44M drive */ type = 4; if (!(tracks == 80 && ((secs == 15 && type == 3) || (secs == 9 && type == 4)))) { /* specified tracks, sectors/track not allowed for drive */ fv->gbfv_spcfunbit = 2; return dskerr(0xc); } } fl_setdisktype(pddt->ddt_driveno, type); } } if (fv->gbfv_spcfunbit & 1) return S_DONE; afentry.type = 2; /* 512 byte sectors */ afentry.track = fv->gbfv_cyl; afentry.head = fv->gbfv_head; for (tracks = fv->gbfv_spcfunbit & 2 ? fv->gbfv_ntracks : 1; tracks > 0; tracks--) { addrfield = (struct thst *)DiskTransferBuffer; if (afentry.track > pddt->ddt_ncyl) return failure(E_FAILURE); for (afentry.sector = 1; afentry.sector <= pddt->ddt_bpb.bpb_nsecs; afentry.sector++) memcpy(addrfield++, &afentry, sizeof(afentry)); ret = Genblockio(pddt, LBA_FORMAT, afentry.head, afentry.track, 0, pddt->ddt_bpb.bpb_nsecs, DiskTransferBuffer); if (ret != 0) return dskerr(ret); } afentry.head++; if (afentry.head >= pddt->ddt_bpb.bpb_nheads) { afentry.head = 0; afentry.track++; } } /* fall through to verify */ case 0x62: /* verify track */ { struct gblkfv FAR *fv = rp->r_fv; ret = Genblockio(pddt, LBA_VERIFY, fv->gbfv_head, fv->gbfv_cyl, 0, (fv->gbfv_spcfunbit ? fv->gbfv_ntracks * pddt->ddt_defbpb.bpb_nsecs : pddt->ddt_defbpb.bpb_nsecs), DiskTransferBuffer); if (ret != 0) return dskerr(ret); fv->gbfv_spcfunbit = 0; /* success */ } break; case 0x46: /* set volume serial number */ { struct Gioc_media FAR *gioc = rp->r_gioc; struct FS_info *fs; ret = getbpb(pddt); if (ret != 0) return (ret); /* return error if media lacks extended BPB with serial # */ { register BYTE extended_BPB_signature = DiskTransferBuffer[(pddt->ddt_bpb.bpb_nfsect != 0 ? 0x26 : 0x42)]; if ((extended_BPB_signature != 0x29) || (extended_BPB_signature != 0x28)) return failure(E_MEDIA); } /* otherwise, store serial # in extended BPB */ fs = (struct FS_info *)&DiskTransferBuffer [(pddt->ddt_bpb.bpb_nfsect != 0 ? 0x27 : 0x43)]; fs->serialno = gioc->ioc_serialno; pddt->ddt_serialno = fs->serialno; ret = RWzero(pddt, LBA_WRITE); if (ret != 0) return (dskerr(ret)); } break; case 0x47: /* set access flag */ { struct Access_info FAR *ai = rp->r_ai; pddt->ddt_descflags = (descflags & ~DF_NOACCESS) | (ai->AI_Flag ? 0 : DF_NOACCESS); } break; case 0x60: /* get device parameters */ { struct gblkio FAR *gblp = rp->r_io; bpb *pbpb; gblp->gbio_devtype = pddt->ddt_type; gblp->gbio_devattrib = descflags & 3; /* 360 kb disk in 1.2 MB drive */ gblp->gbio_media = (pddt->ddt_type == 1) && (pddt->ddt_ncyl == 40); gblp->gbio_ncyl = pddt->ddt_ncyl; /* use default dpb or current bpb? */ pbpb = (gblp->gbio_spcfunbit & 0x01) == 0 ? &pddt->ddt_defbpb : &pddt->ddt_bpb; #ifdef WITHFAT32 fmemcpy(&gblp->gbio_bpb, pbpb, extended ? sizeof(gblp->gbio_bpb) : BPB_SIZEOF); #else fmemcpy(&gblp->gbio_bpb, pbpb, sizeof(gblp->gbio_bpb)); #endif /*gblp->gbio_nsecs = pbpb->bpb_nsector; */ break; } case 0x61: /* read track - CHS is absolute on disk not relative to start of partition */ { struct gblkrw FAR *rw = rp->r_rw; ret = GenblockioAbs(pddt, LBA_READ, rw->gbrw_head, rw->gbrw_cyl, rw->gbrw_sector, rw->gbrw_nsecs, rw->gbrw_buffer); if (ret != 0) return dskerr(ret); } break; case 0x66: /* get volume serial number */ { struct Gioc_media FAR *gioc = rp->r_gioc; ret = getbpb(pddt); if (ret != 0) return (ret); /* Note: getbpb() will initialize extended BPB fields with default values */ gioc->ioc_serialno = pddt->ddt_serialno; fmemcpy(gioc->ioc_volume, pddt->ddt_volume, 11); fmemcpy(gioc->ioc_fstype, pddt->ddt_fstype, 8); } break; case 0x67: /* get access flag */ { struct Access_info FAR *ai = rp->r_ai; ai->AI_Flag = descflags & DF_NOACCESS ? 0 : 1; /* bit 9 */ } break; default: return failure(E_CMD); } return S_DONE; }
static LONG bios_7(WORD drive) { return getbpb(drive); }