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

📄 initdisk.c

📁 开源DOS的C代码源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
}

void printCHS(char *title, struct CHS *chs)
{
  /* has no fixed size for head/sect: is often 1/1 in our context */
  printf("%s%4u-%u-%u", title, chs->Cylinder, chs->Head, chs->Sector);
}

/*
    reason for this modules existence:
    
    we have found a partition, and add them to the global 
    partition structure.

*/

/* Compute ceil(a/b) */
#define cdiv(a, b) (((a) + (b) - 1) / (b))

/* calculates FAT data:
   code adapted by Bart Oldeman from mkdosfs from the Linux dosfstools:
      Author:       Dave Hudson
      Updated by:   Roman Hodek
      Portions copyright 1992, 1993 Remy Card
      and 1991 Linus Torvalds
*/
VOID CalculateFATData(ddt * pddt, ULONG NumSectors, UBYTE FileSystem)
{
  UBYTE maxclustsize;
  ULONG fatdata;

  bpb *defbpb = &pddt->ddt_defbpb;

  /* FAT related items */
  defbpb->bpb_nfat = 2;
  defbpb->bpb_ndirent = (FileSystem == FAT32
                         || FileSystem == FAT32_LBA) ? 0 : 512;
  /* normal value of number of entries in root dir */
  defbpb->bpb_nreserved = (FileSystem == FAT32
                           || FileSystem == FAT32_LBA) ? 0x20 : 1;

  fatdata =
      NumSectors - cdiv(defbpb->bpb_ndirent * DIRENT_SIZE,
                        defbpb->bpb_nbyte) - defbpb->bpb_nreserved;
  maxclustsize = 128;
#ifdef DEBUG
  if (FileSystem != FAT12)
    DebugPrintf(("%ld sectors for FAT+data, starting with %d sectors/cluster\n", fatdata, defbpb->bpb_nsector));
#endif
  switch (FileSystem)
  {

    case FAT12:
    case FAT12_LBA:
    {
      unsigned fatdat, fatlength, clust, maxclust;
      /* in DOS, FAT12 defaults to 4096kb (8 sector) - clusters. */
      defbpb->bpb_nsector = 8;
      /* Force maximal fatdata=32696 sectors since with our only possible sector
         size (512 bytes) this is the maximum for 4k clusters.
         #clus*secperclus+#fats*fatlength= 4077 * 8 + 2 * 12 = 32640.
         max FAT12 size for FreeDOS = 16,728,064 bytes */
      fatdat = (unsigned)fatdata;
      if (fatdata > 32640)
        fatdat = 32640;
      /* The "+2*defbpb->bpb_nsector" is for the reserved first two FAT entries */
      fatlength = cdiv(fatdat + 2 * defbpb->bpb_nsector,
                       defbpb->bpb_nbyte * 2 * defbpb->bpb_nsector / 3 +
                       defbpb->bpb_nfat);
      /* Need to calculate number of clusters, since the unused parts of the
       * FATS and data area together could make up space for an additional,
       * not really present cluster. */
      clust =
          (fatdat - defbpb->bpb_nfat * fatlength) / defbpb->bpb_nsector;
      maxclust = (fatlength * 2 * defbpb->bpb_nbyte) / 3;
      if (maxclust > FAT12MAX)
        maxclust = FAT12MAX;
      DebugPrintf(("FAT12: #clu=%u, fatlength=%u, maxclu=%u, limit=%u\n",
                   clust, fatlength, maxclust, FAT12MAX));
      if (clust > maxclust - 2)
      {
        clust = maxclust - 2;
        DebugPrintf(("FAT12: too many clusters: setting to maxclu-2\n"));
      }
      defbpb->bpb_nfsect = fatlength;
      memcpy(pddt->ddt_fstype, MSDOS_FAT12_SIGN, 8);
      break;
    }
    case FAT16SMALL:
    case FAT16LARGE:
    case FAT16_LBA:
    {
      unsigned fatlength;
      unsigned long clust, maxclust;
      /* FAT16: start at 4 sectors per cluster */
      defbpb->bpb_nsector = 4;
      /* Force maximal fatdata=8387584 sectors (NumSectors=8387617)
         since with our only possible sectorsize (512 bytes) this is the
         maximum we can address with 64k clusters
         #clus*secperclus+#fats*fatlength=65517 * 128 + 2 * 256=8386688.
         max FAT16 size for FreeDOS = 4,293,984,256 bytes = 4GiB-983,040 */
      if (fatdata > 8386688ul)
        fatdata = 8386688ul;
      do
      {
        DebugPrintf(("Trying with %d sectors/cluster:\n",
                     defbpb->bpb_nsector));

        fatlength = (unsigned)cdiv(fatdata + 2 * defbpb->bpb_nsector,
                         (ULONG)defbpb->bpb_nbyte * defbpb->bpb_nsector / 2 +
                         defbpb->bpb_nfat);
        /* Need to calculate number of clusters, since the unused parts of the
         * FATS and data area together could make up space for an additional,
         * not really present cluster. */
        clust =
            (fatdata - defbpb->bpb_nfat * fatlength) / defbpb->bpb_nsector;
        maxclust = ((unsigned long)fatlength * defbpb->bpb_nbyte) / 2;
        if (maxclust > FAT16MAX)
          maxclust = FAT16MAX;
        DebugPrintf(("FAT16: #clu=%lu, fatlen=%u, maxclu=%lu, limit=%u\n",
                     clust, fatlength, maxclust, FAT_MAGIC16));
        if (clust > maxclust - 2)
        {
          DebugPrintf(("FAT16: too many clusters\n"));
          clust = 0;
        }
        else if (clust <= FAT_MAGIC)
        {
          /* The <= 4086 avoids that the filesystem will be misdetected as having a
           * 12 bit FAT. */
          DebugPrintf(("FAT16: would be misdetected as FAT12\n"));
          clust = 0;
        }
        if (clust)
          break;
        defbpb->bpb_nsector <<= 1;
      }
      while (defbpb->bpb_nsector && defbpb->bpb_nsector <= maxclustsize);
      defbpb->bpb_nfsect = fatlength;
      memcpy(pddt->ddt_fstype, MSDOS_FAT16_SIGN, 8);
      break;
    }
#ifdef WITHFAT32
    case FAT32:
    case FAT32_LBA:
    {
      unsigned long fatlength, clust, maxclust;

      /* For FAT32, use the cluster size table described in the FAT spec:
       * http://www.microsoft.com/hwdev/download/hardware/fatgen103.pdf
       */
      unsigned sz_gb = (unsigned)(NumSectors / 2097152UL);
      unsigned char nsector = 64; /* disks greater than 32 GB, 32K cluster */
      if (sz_gb <= 32)            /* disks up to 32 GB, 16K cluster */
        nsector = 32;
      if (sz_gb <= 16)            /* disks up to 16 GB, 8K cluster */
        nsector = 16;
      if (sz_gb <= 8)             /* disks up to 8 GB, 4K cluster */
        nsector = 8;
      if (NumSectors <= 532480UL)   /* disks up to 260 MB, 0.5K cluster */
        nsector = 1;
      defbpb->bpb_nsector = nsector;
      do
      {
        fatlength = cdiv(fatdata + 2 * defbpb->bpb_nsector,
                         (ULONG)defbpb->bpb_nbyte * defbpb->bpb_nsector / 4 +
                         defbpb->bpb_nfat);
        /* Need to calculate number of clusters, since the unused parts of the
         * FATS and data area together could make up space for an additional,
         * not really present cluster. */
        clust =
            (fatdata - defbpb->bpb_nfat * fatlength) / defbpb->bpb_nsector;
        maxclust = (fatlength * defbpb->bpb_nbyte) / 4;
        if (maxclust > FAT32MAX)
          maxclust = FAT32MAX;
        DebugPrintf(("FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
                     clust, fatlength, maxclust, FAT32MAX));
        if (clust > maxclust - 2)
        {
          clust = 0;
          DebugPrintf(("FAT32: too many clusters\n"));
        }
        if (clust)
          break;
        defbpb->bpb_nsector <<= 1;
      }
      while (defbpb->bpb_nsector && defbpb->bpb_nsector <= maxclustsize);
      defbpb->bpb_nfsect = 0;
      defbpb->bpb_xnfsect = fatlength;
      /* set up additional FAT32 fields */
      defbpb->bpb_xflags = 0;
      defbpb->bpb_xfsversion = 0;
      defbpb->bpb_xrootclst = 2;
      defbpb->bpb_xfsinfosec = 1;
      defbpb->bpb_xbackupsec = 6;
      memcpy(pddt->ddt_fstype, MSDOS_FAT32_SIGN, 8);
      break;
    }
#endif
  }
  pddt->ddt_fstype[8] = '\0';
}

STATIC void push_ddt(ddt *pddt)
{
  ddt FAR *fddt = DynAlloc("ddt", 1, sizeof(ddt));
  fmemcpy(fddt, pddt, sizeof(ddt));
  if (pddt->ddt_logdriveno != 0) {
    (fddt - 1)->ddt_next = fddt;
    if (pddt->ddt_driveno == 0 && pddt->ddt_logdriveno == 1)
      (fddt - 1)->ddt_descflags |= DF_CURLOG | DF_MULTLOG;
  }
}

void DosDefinePartition(struct DriveParamS *driveParam,
                        ULONG StartSector, struct PartTableEntry *pEntry,
                        int extendedPartNo, int PrimaryNum)
{
  ddt nddt;
  ddt *pddt = &nddt;
  struct CHS chs;

  if (nUnits >= NDEV)
  {
    printf("more Partitions detected then possible, max = %d\n", NDEV);
    return;                     /* we are done */
  }

  pddt->ddt_next = MK_FP(0, 0xffff);
  pddt->ddt_driveno = driveParam->driveno;
  pddt->ddt_logdriveno = nUnits;
  pddt->ddt_descflags = driveParam->descflags;
  /* Turn of LBA if not forced and the partition is within 1023 cyls and of the right type */
  /* the FileSystem type was internally converted to LBA_xxxx if a non-LBA partition
     above cylinder 1023 was found */
  if (!InitKernelConfig.ForceLBA && !ExtLBAForce && !IsLBAPartition(pEntry->FileSystem))
    pddt->ddt_descflags &= ~DF_LBA;
  pddt->ddt_ncyl = driveParam->chs.Cylinder;

#ifdef DEBUG
  if (pddt->ddt_descflags & DF_LBA)
    DebugPrintf(("LBA enabled for drive %c:\n", 'A' + nUnits));
#endif

  pddt->ddt_offset = StartSector;

  pddt->ddt_defbpb.bpb_nbyte = SEC_SIZE;
  pddt->ddt_defbpb.bpb_mdesc = 0xf8;
  pddt->ddt_defbpb.bpb_nheads = driveParam->chs.Head;
  pddt->ddt_defbpb.bpb_nsecs = driveParam->chs.Sector;
  pddt->ddt_defbpb.bpb_nsize = 0;
  pddt->ddt_defbpb.bpb_hidden = pEntry->RelSect;
  if (pEntry->NumSect > 0xffff)
    pddt->ddt_defbpb.bpb_huge = pEntry->NumSect;
  else
    pddt->ddt_defbpb.bpb_nsize = (UWORD) (pEntry->NumSect);

  /* sectors per cluster, sectors per FAT etc. */
  CalculateFATData(pddt, pEntry->NumSect, pEntry->FileSystem);

  pddt->ddt_serialno = 0x12345678l;
  /* drive inaccessible until bldbpb successful */
  pddt->ddt_descflags |= init_readdasd(pddt->ddt_driveno) | DF_NOACCESS;
  pddt->ddt_type = 5;
  memcpy(&pddt->ddt_bpb, &pddt->ddt_defbpb, sizeof(bpb));

  push_ddt(pddt);

  /* Alain whishes to keep this in later versions, too 
     Tom likes this too, so he made it configurable by SYS CONFIG ...
   */

  if (InitKernelConfig.InitDiskShowDriveAssignment)
  {
    char *ExtPri;
    int num;

    LBA_to_CHS(&chs, StartSector, driveParam);

    ExtPri = "Pri";
    num = PrimaryNum + 1;
    if (extendedPartNo)
    {
      ExtPri = "Ext";
      num = extendedPartNo;
    }
    printf("\r%c: HD%d, %s[%2d]", 'A' + nUnits,
           (driveParam->driveno & 0x7f) + 1, ExtPri, num);

    printCHS(", CHS= ", &chs);

    printf(", start=%6lu MB, size=%6lu MB\n",
           StartSector / 2048, pEntry->NumSect / 2048);
  }

  nUnits++;
}

/* Get the parameters of the hard disk */
STATIC int LBA_Get_Drive_Parameters(int drive, struct DriveParamS *driveParam)
{
  iregs regs;
  struct _bios_LBA_disk_parameterS lba_bios_parameters;

  ExtLBAForce = FALSE;

  memset(driveParam, 0, sizeof *driveParam);
  drive |= 0x80;

  /* for tests - disable LBA support,
     even if exists                    */
  if (!InitKernelConfig.GlobalEnableLBAsupport)
  {
    goto StandardBios;
  }
  /* check for LBA support */
  regs.b.x = 0x55aa;
  regs.a.b.h = 0x41;
  regs.d.b.l = drive;

  init_call_intr(0x13, &regs);

  if (regs.b.x != 0xaa55 || (regs.flags & 0x01))
  {
    goto StandardBios;
  }

  /* by ralph :
     if DAP cannot be used, don't use
     LBA
   */
  if ((regs.c.x & 1) == 0)
  {
    goto StandardBios;
  }

  /* drive supports LBA addressing */

  /* version 1.0, 2.0 have different verify */
  if (regs.a.x < 0x2100)
    LBA_WRITE_VERIFY = 0x4301;

  memset(&lba_bios_parameters, 0, sizeof(lba_bios_parameters));
  lba_bios_parameters.size = sizeof(lba_bios_parameters);

  regs.si = FP_OFF(&lba_bios_parameters);
  regs.ds = FP_SEG(&lba_bios_parameters);
  regs.a.b.h = 0x48;
  regs.d.b.l = drive;
  init_call_intr(0x13, &regs);

  /* error or DMA boundary errors not handled transparently */
  if (regs.flags & 0x01)

⌨️ 快捷键说明

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