⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsk.c

📁 开源DOS的C代码源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
STATIC WORD getbpb(ddt * pddt)
{
  ULONG count;
  bpb *pbpbarray = &pddt->ddt_bpb;
  unsigned secs_per_cyl;
  WORD ret;

  /* pddt->ddt_descflags |= DF_NOACCESS; 
   * disabled for now - problems with FORMAT ?? */

  /* set drive to not accessible and changed */
  if (diskchange(pddt) != M_NOT_CHANGED)
    pddt->ddt_descflags |= DF_DISKCHANGE;

  ret = RWzero(pddt, LBA_READ);
  if (ret != 0)
    return (dskerr(ret));

  pbpbarray->bpb_nbyte = getword(&DiskTransferBuffer[BT_BPB]);

  if (DiskTransferBuffer[0x1fe] != 0x55
      || DiskTransferBuffer[0x1ff] != 0xaa || pbpbarray->bpb_nbyte != 512)
  {
    /* copy default bpb to be sure that there is no bogus data */
    memcpy(pbpbarray, &pddt->ddt_defbpb, sizeof(bpb));
    return S_DONE;
  }

  pddt->ddt_descflags &= ~DF_NOACCESS;  /* set drive to accessible */

/*TE ~ 200 bytes*/

  memcpy(pbpbarray, &DiskTransferBuffer[BT_BPB], sizeof(bpb));

  /*?? */
  /*  2b is fat16 volume label. if memcmp, then offset 0x36.
     if (fstrncmp((BYTE *) & DiskTransferBuffer[0x36], "FAT16",5) == 0  ||
     fstrncmp((BYTE *) & DiskTransferBuffer[0x36], "FAT12",5) == 0) {
     TE: I'm not sure, what the _real_ decision point is, however MSDN
     'A_BF_BPB_SectorsPerFAT
     The number of sectors per FAT.
     Note: This member will always be zero in a FAT32 BPB.
     Use the values from A_BF_BPB_BigSectorsPerFat...
  */
  {
    struct FS_info *fs = (struct FS_info *)&DiskTransferBuffer[0x27];
#ifdef WITHFAT32
    if (pbpbarray->bpb_nfsect == 0)
    {
      /* FAT32 boot sector */
      fs = (struct FS_info *)&DiskTransferBuffer[0x43];
    }
#endif
    pddt->ddt_serialno = getlong(&fs->serialno);
    memcpy(pddt->ddt_volume, fs->volume, sizeof fs->volume);
    memcpy(pddt->ddt_fstype, fs->fstype, sizeof fs->fstype);
  }

#ifdef DSK_DEBUG
  printf("BPB_NBYTE     = %04x\n", pbpbarray->bpb_nbyte);
  printf("BPB_NSECTOR   = %02x\n", pbpbarray->bpb_nsector);
  printf("BPB_NRESERVED = %04x\n", pbpbarray->bpb_nreserved);
  printf("BPB_NFAT      = %02x\n", pbpbarray->bpb_nfat);
  printf("BPB_NDIRENT   = %04x\n", pbpbarray->bpb_ndirent);
  printf("BPB_NSIZE     = %04x\n", pbpbarray->bpb_nsize);
  printf("BPB_MDESC     = %02x\n", pbpbarray->bpb_mdesc);
  printf("BPB_NFSECT    = %04x\n", pbpbarray->bpb_nfsect);
#endif

  count =
      pbpbarray->bpb_nsize == 0 ?
      pbpbarray->bpb_huge : pbpbarray->bpb_nsize;
  secs_per_cyl = pbpbarray->bpb_nheads * pbpbarray->bpb_nsecs;

  if (secs_per_cyl == 0)
  {
    tmark(pddt);
    return failure(E_FAILURE);
  }
  /* this field is problematic for partitions > 65535 cylinders,
     in general > 512 GiB. However: we are not using it ourselves. */
  pddt->ddt_ncyl = (UWORD)((count + (secs_per_cyl - 1)) / secs_per_cyl);

  tmark(pddt);

#ifdef DSK_DEBUG
  printf("BPB_NSECS     = %04x\n", pbpbarray->bpb_nsecs);
  printf("BPB_NHEADS    = %04x\n", pbpbarray->bpb_nheads);
  printf("BPB_HIDDEN    = %08lx\n", pbpbarray->bpb_hidden);
  printf("BPB_HUGE      = %08lx\n", pbpbarray->bpb_huge);
#endif

  return 0;
}

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 IoctlQueblk(rqptr rp, ddt * pddt)
{
  UNREFERENCED_PARAMETER(pddt);

#ifdef WITHFAT32
  if (rp->r_cat == 8 || rp->r_cat == 0x48)
#else
  if (rp->r_cat == 8)
#endif
  {
    switch (rp->r_fun)
    {
    case 0x46:
    case 0x47:
    case 0x60:
    case 0x66:
    case 0x67:
      return S_DONE;
    }
  }
  return failure(E_CMD);
}

STATIC COUNT Genblockio(ddt * pddt, UWORD mode, WORD head, WORD track,
                 WORD sector, WORD count, VOID FAR * buffer)
{
  UWORD transferred;

  /* apparently sector is ZERO, not ONE based !!! */
  return LBA_Transfer(pddt, mode, buffer,
                      ((ULONG) track * pddt->ddt_bpb.bpb_nheads + head) *
                      (ULONG) pddt->ddt_bpb.bpb_nsecs +
                      pddt->ddt_offset + sector, count, &transferred);
}

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 */
      {
        struct gblkrw FAR *rw = rp->r_rw;
        ret = Genblockio(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);

        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 */
      {
        struct gblkrw FAR *rw = rp->r_rw;
        ret = Genblockio(pddt, LBA_READ, rw->gbrw_head, rw->gbrw_cyl,
                         rw->gbrw_sector, rw->gbrw_nsecs, rw->gbrw_buffer);
        if (ret != 0)
          return dskerr(ret);
      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -