DSK.C
上传用户:dcs7469208
上传日期:2010-01-02
资源大小:443k
文件大小:19k
源码类别:

操作系统开发

开发平台:

DOS

  1. /****************************************************************/
  2. /* */
  3. /*       dsk.c */
  4. /* */
  5. /* Copyright (c) 1995 */
  6. /* Pasquale J. Villani */
  7. /* All Rights Reserved */
  8. /* */
  9. /* This file is part of DOS-C. */
  10. /* */
  11. /* DOS-C is free software; you can redistribute it and/or */
  12. /* modify it under the terms of the GNU General Public License */
  13. /* as published by the Free Software Foundation; either version */
  14. /* 2, or (at your option) any later version. */
  15. /* */
  16. /* DOS-C is distributed in the hope that it will be useful, but */
  17. /* WITHOUT ANY WARRANTY; without even the implied warranty of */
  18. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See */
  19. /* the GNU General Public License for more details. */
  20. /* */
  21. /* You should have received a copy of the GNU General Public */
  22. /* License along with DOS-C; see the file COPYING.  If not, */
  23. /* write to the Free Software Foundation, 675 Mass Ave, */
  24. /* Cambridge, MA 02139, USA. */
  25. /****************************************************************/
  26. #include "../../hdr/portab.h"
  27. #include "globals.h"
  28. /* $Logfile:   C:/dos-c/src/kernel/dsk.c_v  $ */
  29. #ifdef VERSION_STRINGS
  30. static BYTE *dskRcsId = "$Header:   C:/dos-c/src/kernel/dsk.c_v   1.6   04 Jan 1998 23:15:16   patv  $";
  31. #endif
  32. /* $Log:   C:/dos-c/src/kernel/dsk.c_v  $
  33.  * 
  34.  *    Rev 1.6   04 Jan 1998 23:15:16   patv
  35.  * Changed Log for strip utility
  36.  * 
  37.  *    Rev 1.5   10 Jan 1997  5:41:48   patv
  38.  * Modified for extended partition support
  39.  *
  40.  *    Rev 1.4   29 May 1996 21:03:32   patv
  41.  * bug fixes for v0.91a
  42.  *
  43.  *    Rev 1.3   19 Feb 1996  3:21:36   patv
  44.  * Added NLS, int2f and config.sys processing
  45.  *
  46.  *    Rev 1.2   01 Sep 1995 17:54:18   patv
  47.  * First GPL release.
  48.  *
  49.  *    Rev 1.1   30 Jul 1995 20:52:00   patv
  50.  * Eliminated version strings in ipl
  51.  *
  52.  *    Rev 1.0   02 Jul 1995  8:32:42   patv
  53.  * Initial revision.
  54.  */
  55. /* $EndLog$ */
  56. #ifdef PROTO
  57. BOOL fl_reset(VOID);
  58. COUNT fl_rd_status(WORD);
  59. COUNT fl_read(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
  60. COUNT fl_write(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
  61. BOOL fl_verify(WORD, WORD, WORD, WORD, WORD, BYTE FAR *);
  62. BOOL fl_format(WORD, BYTE FAR *);
  63. #else
  64. BOOL fl_reset();
  65. COUNT fl_rd_status();
  66. COUNT fl_read();
  67. COUNT fl_write();
  68. BOOL fl_verify();
  69. BOOL fl_format();
  70. #endif
  71. #define NDEV 8 /* only one for demo */
  72. #define SEC_SIZE 512 /* size of sector in bytes */
  73. #define N_RETRY 5 /* number of retries permitted */
  74. #define NENTRY 25 /* total size of dispatch table */
  75. union
  76. {
  77. BYTE bytes[2 * SEC_SIZE];
  78. boot boot_sector;
  79. } buffer;
  80. static struct media_info
  81. {
  82. ULONG mi_size; /* physical sector count */
  83. UWORD mi_heads; /* number of heads (sides) */
  84. UWORD mi_cyls; /* number of cyl/drive */
  85. UWORD mi_sectors; /* number of sectors/cyl */
  86. ULONG mi_offset; /* relative partition offset */
  87.         BYTE    mi_drive;               /* BIOS drive number            */
  88.         COUNT   mi_partidx;             /* Index to partition array     */
  89. };
  90. static struct media_info miarray[NDEV]; /* Internal media info structs  */
  91. static bpb bpbarray[NDEV];              /* BIOS parameter blocks        */
  92. static bpb *bpbptrs[NDEV];              /* pointers to bpbs             */
  93. #define N_PART 4                        /* number of partitions per
  94.                                            table partition              */
  95. static WORD head, track, sector, ret;   /* globals for blockio          */
  96. static WORD count;
  97. static COUNT nUnits;                    /* number of returned units     */
  98. static COUNT nPartitions;               /* number of DOS partitions     */
  99. #define PARTOFF 0x1be
  100. static struct
  101. {
  102.         BYTE    peDrive;                /* BIOS drive number            */
  103. BYTE peBootable;
  104. BYTE peBeginHead;
  105. BYTE peBeginSector;
  106. UWORD peBeginCylinder;
  107. BYTE peFileSystem;
  108. BYTE peEndHead;
  109. BYTE peEndSector;
  110. UWORD peEndCylinder;
  111. LONG peStartSector;
  112. LONG peSectors;
  113.         LONG    peAbsStart;             /* Absolute sector start        */
  114. } dos_partition[NDEV - 2];
  115. #ifdef PROTO
  116. WORD init(rqptr), mediachk(rqptr), bldbpb(rqptr), blockio(rqptr), blk_error(rqptr);
  117. COUNT ltop(WORD *, WORD *, WORD *, COUNT, COUNT, LONG, byteptr);
  118. WORD dskerr(COUNT);
  119. COUNT processtable(COUNT ptDrive, BYTE ptHead, UWORD ptCylinder, BYTE ptSector, LONG ptAccuOff);
  120. #else
  121. WORD init(), mediachk(), bldbpb(), blockio(), blk_error();
  122. WORD dskerr();
  123. COUNT processtable();
  124. #endif
  125. /* */
  126. /* the function dispatch table */
  127. /* */
  128. #ifdef PROTO
  129. static WORD (*dispatch[NENTRY]) (rqptr) =
  130. #else
  131. static WORD (*dispatch[NENTRY]) () =
  132. #endif
  133. {
  134. init, /* Initialize */
  135. mediachk, /* Media Check */
  136. bldbpb, /* Build BPB */
  137. blk_error, /* Ioctl In */
  138. blockio, /* Input (Read) */
  139. blk_error, /* Non-destructive Read */
  140. blk_error, /* Input Status */
  141. blk_error, /* Input Flush */
  142. blockio, /* Output (Write) */
  143. blockio, /* Output with verify */
  144. blk_error, /* Output Status */
  145. blk_error, /* Output Flush */
  146. blk_error, /* Ioctl Out */
  147. blk_error, /* Device Open */
  148. blk_error, /* Device Close */
  149. blk_error, /* Removable Media */
  150. blk_error, /* Output till busy */
  151. blk_error, /* undefined */
  152. blk_error, /* undefined */
  153. blk_error, /* Generic Ioctl */
  154. blk_error, /* undefined */
  155. blk_error, /* undefined */
  156. blk_error, /* undefined */
  157. blk_error, /* Get Logical Device */
  158. blk_error /* Set Logical Device */
  159. };
  160. #define SIZEOF_PARTENT 16
  161. #define FAT12 0x01
  162. #define FAT16SMALL 0x04
  163. #define EXTENDED 0x05
  164. #define FAT16LARGE 0x06
  165. #define hd(x) ((x) & 0x80)
  166. COUNT
  167. processtable (COUNT ptDrive, BYTE ptHead, UWORD ptCylinder,
  168.               BYTE ptSector, LONG ptAccuOff)
  169. {
  170.         struct                          /* Temporary partition table    */
  171.         {
  172.          BYTE peBootable;
  173.         BYTE peBeginHead;
  174.                 BYTE peBeginSector;
  175.                 UWORD   peBeginCylinder;
  176.         BYTE peFileSystem;
  177.         BYTE peEndHead;
  178.                 BYTE peEndSector;
  179.         UWORD peEndCylinder;
  180.         LONG peStartSector;
  181.         LONG peSectors;
  182.         } temp_part[N_PART];
  183. REG retry = N_RETRY;
  184.         UBYTE packed_byte, pb1;
  185.         COUNT Part;
  186.         /* Read partition table                         */
  187. do
  188. {
  189. ret = fl_read ((WORD)ptDrive, (WORD)ptHead, (WORD)ptCylinder,
  190.                                (WORD)ptSector, (WORD)1, (byteptr)&buffer);
  191. } while (ret != 0 && --retry > 0);
  192. if(ret != 0)
  193. return FALSE;
  194.         /* Read each partition into temporary array     */
  195.         for (Part = 0; Part < N_PART; Part++)
  196.         {
  197.         REG BYTE *p =
  198.                     (BYTE *)&buffer.bytes[PARTOFF + (Part * SIZEOF_PARTENT)];
  199.                 getbyte((VOID *)p, &temp_part[Part].peBootable);
  200.         ++p;
  201.         getbyte((VOID *)p, &temp_part[Part].peBeginHead);
  202.         ++p;
  203.         getbyte((VOID *)p, &packed_byte);
  204.         temp_part[Part].peBeginSector = packed_byte & 0x3f;
  205.         ++p;
  206.         getbyte((VOID *)p, &pb1);
  207.         ++p;
  208.         temp_part[Part].peBeginCylinder = pb1 + ((UWORD)(0xc0 & packed_byte) << 2);
  209.         getbyte((VOID *)p, &temp_part[Part].peFileSystem);
  210.         ++p;
  211.         getbyte((VOID *)p, &temp_part[Part].peEndHead);
  212.         ++p;
  213.         getbyte((VOID *)p, &packed_byte);
  214.         temp_part[Part].peEndSector = packed_byte & 0x3f;
  215.         ++p;
  216.         getbyte((VOID *)p, &pb1);
  217.         ++p;
  218.         temp_part[Part].peEndCylinder = pb1 + ((UWORD)(0xc0 & packed_byte) << 2);
  219.         getlong((VOID *)p, &temp_part[Part].peStartSector);
  220.         p += sizeof(LONG);
  221.         getlong((VOID *)p, &temp_part[Part].peSectors);
  222.         };
  223.         /* Walk through the table, add DOS partitions to global
  224.            array and process extended partitions         */
  225.         for (Part = 0; Part < N_PART && nUnits < NDEV; Part++)
  226.         {
  227.                 if (temp_part[Part].peFileSystem == FAT12 ||
  228.                     temp_part[Part].peFileSystem == FAT16SMALL ||
  229.                     temp_part[Part].peFileSystem == FAT16LARGE)
  230.                 {
  231.                         miarray[nUnits].mi_offset =
  232.                                temp_part[Part].peStartSector + ptAccuOff;
  233.                         miarray[nUnits].mi_drive = ptDrive;
  234.                         miarray[nUnits].mi_partidx = nPartitions;
  235.                         nUnits++;
  236.                         dos_partition[nPartitions].peDrive = ptDrive;
  237.                         dos_partition[nPartitions].peBootable =
  238.                                temp_part[Part].peBootable;
  239.                         dos_partition[nPartitions].peBeginHead =
  240.                                temp_part[Part].peBeginHead;
  241.                         dos_partition[nPartitions].peBeginSector =
  242.                                temp_part[Part].peBeginSector;
  243.                         dos_partition[nPartitions].peBeginCylinder =
  244.                                temp_part[Part].peBeginCylinder;
  245.                         dos_partition[nPartitions].peFileSystem =
  246.                                temp_part[Part].peFileSystem;
  247.                         dos_partition[nPartitions].peEndHead =
  248.                                temp_part[Part].peEndHead;
  249.                         dos_partition[nPartitions].peEndSector =
  250.                                temp_part[Part].peEndSector;
  251.                         dos_partition[nPartitions].peEndCylinder =
  252.                                temp_part[Part].peEndCylinder;
  253.                         dos_partition[nPartitions].peStartSector =
  254.                                temp_part[Part].peStartSector;
  255.                         dos_partition[nPartitions].peSectors =
  256.                                temp_part[Part].peSectors;
  257.                         dos_partition[nPartitions].peAbsStart =
  258.                                temp_part[Part].peStartSector + ptAccuOff;
  259.                         nPartitions++;
  260.                 }
  261.                 else if (temp_part[Part].peFileSystem == EXTENDED)
  262.                 {
  263.                         /* call again to process extended part table */
  264.                         processtable (ptDrive,
  265.                                       temp_part[Part].peBeginHead,
  266.                                       temp_part[Part].peBeginCylinder,
  267.                                       temp_part[Part].peBeginSector,
  268.                                       temp_part[Part].peStartSector + ptAccuOff);
  269.                 };
  270.         };
  271.         return TRUE;
  272. }
  273. COUNT
  274. blk_driver (rqptr rp)
  275. {
  276. if(rp -> r_unit >= nUnits && rp-> r_command != C_INIT)
  277. return failure(E_UNIT);
  278. if(rp -> r_command > NENTRY)
  279. {
  280. return failure(E_FAILURE); /* general failure */
  281. }
  282. else
  283. return ((*dispatch[rp -> r_command])(rp));
  284. }
  285. static WORD
  286. init (rqptr rp)
  287. {
  288. COUNT HardDrive, Unit;
  289. /* Reset the drives */
  290. fl_reset();
  291.         /* Initial number of disk units                                 */
  292. nUnits = 2;
  293.         /* Initial number of DOS partitions                             */
  294.         nPartitions = 0;
  295.         /* Setup media info and BPBs arrays                             */
  296.         for (Unit = 0; Unit < NDEV; Unit++)
  297.         {
  298.                 miarray[Unit].mi_size = 720l;
  299.                 miarray[Unit].mi_heads = 2;
  300.                 miarray[Unit].mi_cyls = 40;
  301.                 miarray[Unit].mi_sectors = 9;
  302.                 miarray[Unit].mi_offset = 0l;
  303.                 miarray[Unit].mi_drive = Unit;
  304.                 bpbarray[Unit].bpb_nbyte = SEC_SIZE;
  305.                 bpbarray[Unit].bpb_nsector = 2;
  306.                 bpbarray[Unit].bpb_nreserved = 1;
  307.                 bpbarray[Unit].bpb_nfat = 2;
  308.                 bpbarray[Unit].bpb_ndirent = 112;
  309.                 bpbarray[Unit].bpb_nsize = 720l;
  310.                 bpbarray[Unit].bpb_mdesc = 0xfd;
  311.                 bpbarray[Unit].bpb_nfsect = 2;
  312.                 bpbptrs[Unit] = &bpbarray[Unit];
  313.         };
  314. for(HardDrive = 0; HardDrive <= 0; HardDrive++) /* only one hard drive for now */
  315. {
  316.                 /* Process primary partition table                      */
  317.                 if (!processtable ((HardDrive | 0x80), 0, 0l, 1, 0l))
  318.                    /* Exit if no hard drive                             */
  319.                    break;
  320.         };
  321. rp -> r_nunits = nUnits;
  322. rp -> r_bpbptr = bpbptrs;
  323.         rp -> r_endaddr = device_end();
  324. return S_DONE;
  325. }
  326. static WORD
  327. mediachk (rqptr rp)
  328. {
  329. if(hd(miarray[rp -> r_unit].mi_drive))
  330. rp -> r_mcretcode = M_NOT_CHANGED;
  331. else
  332. rp -> r_mcretcode = tdelay((LONG)37) ? M_DONT_KNOW : M_NOT_CHANGED;
  333. return S_DONE;
  334. }
  335. static WORD
  336. bldbpb (rqptr rp)
  337. {
  338. REG retry = N_RETRY;
  339. ULONG count;
  340. byteptr trans;
  341. WORD local_word;
  342. if(hd(miarray[rp -> r_unit].mi_drive))
  343. {
  344.                 COUNT partidx = miarray[rp -> r_unit].mi_partidx;
  345. head = dos_partition[partidx].peBeginHead;
  346. sector = dos_partition[partidx].peBeginSector;
  347. track = dos_partition[partidx].peBeginCylinder;
  348. }
  349. else
  350. {
  351. head = 0;
  352. sector = 1;
  353. track = 0;
  354. }
  355. do
  356. {
  357. ret = fl_read((WORD)miarray[rp -> r_unit].mi_drive,
  358.                       (WORD)head, (WORD)track, (WORD)sector, (WORD)1, (byteptr)&buffer);
  359. } while (ret != 0 && --retry > 0);
  360. if(ret != 0)
  361. return(dskerr(ret));
  362. getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NBYTE]), &bpbarray[rp -> r_unit].bpb_nbyte);
  363. getbyte(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NSECTOR]), &bpbarray[rp -> r_unit].bpb_nsector);
  364. getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NRESERVED]), &bpbarray[rp -> r_unit].bpb_nreserved);
  365. getbyte(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NFAT]), &bpbarray[rp -> r_unit].bpb_nfat);
  366. getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NDIRENT]), &bpbarray[rp -> r_unit].bpb_ndirent);
  367. getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NSIZE]), &bpbarray[rp -> r_unit].bpb_nsize);
  368. getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NSIZE]), &bpbarray[rp -> r_unit].bpb_nsize);
  369. getbyte(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_MDESC]), &bpbarray[rp -> r_unit].bpb_mdesc);
  370. getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NFSECT]), &bpbarray[rp -> r_unit].bpb_nfsect);
  371. getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NSECS]), &bpbarray[rp -> r_unit].bpb_nsecs);
  372. getword(&((((BYTE *)&buffer.bytes[BT_BPB]))[BPB_NHEADS]), &bpbarray[rp -> r_unit].bpb_nheads);
  373. getlong(&((((BYTE *)&buffer.bytes[BT_BPB])[BPB_HIDDEN])), &bpbarray[rp -> r_unit].bpb_hidden);
  374. getlong(&((((BYTE *)&buffer.bytes[BT_BPB])[BPB_HUGE])), &bpbarray[rp -> r_unit].bpb_huge);
  375. #ifdef DSK_DEBUG
  376. printf("BPB_NBYTE     = %04xn", bpbarray[rp -> r_unit].bpb_nbyte);
  377. printf("BPB_NSECTOR   = %02xn", bpbarray[rp -> r_unit].bpb_nsector);
  378. printf("BPB_NRESERVED = %04xn", bpbarray[rp -> r_unit].bpb_nreserved);
  379. printf("BPB_NFAT      = %02xn", bpbarray[rp -> r_unit].bpb_nfat);
  380. printf("BPB_NDIRENT   = %04xn", bpbarray[rp -> r_unit].bpb_ndirent);
  381. printf("BPB_NSIZE     = %04xn", bpbarray[rp -> r_unit].bpb_nsize);
  382. printf("BPB_MDESC     = %02xn", bpbarray[rp -> r_unit].bpb_mdesc);
  383. printf("BPB_NFSECT    = %04xn", bpbarray[rp -> r_unit].bpb_nfsect);
  384. #endif
  385. rp -> r_bpptr = &bpbarray[rp -> r_unit];
  386. count = miarray[rp -> r_unit].mi_size =
  387.  bpbarray[rp -> r_unit].bpb_nsize == 0 ?
  388.   bpbarray[rp -> r_unit].bpb_huge :
  389.   bpbarray[rp -> r_unit].bpb_nsize;
  390. getword((&(((BYTE *)&buffer.bytes[BT_BPB])[BPB_NHEADS])), &miarray[rp -> r_unit].mi_heads);
  391. head = miarray[rp -> r_unit].mi_heads;
  392. getword((&(((BYTE *)&buffer.bytes[BT_BPB])[BPB_NSECS])), &miarray[rp -> r_unit].mi_sectors);
  393. if(miarray[rp -> r_unit].mi_size == 0)
  394. getlong(&((((BYTE *)&buffer.bytes[BT_BPB])[BPB_HUGE])), &miarray[rp -> r_unit].mi_size);
  395. sector = miarray[rp -> r_unit].mi_sectors;
  396. if(head == 0 || sector == 0)
  397. {
  398. tmark();
  399. return failure(E_FAILURE);
  400. }
  401. miarray[rp -> r_unit].mi_cyls = count / (head * sector);
  402. tmark();
  403. #ifdef DSK_DEBUG
  404. printf("BPB_NSECS     = %04xn", sector);
  405. printf("BPB_NHEADS    = %04xn", head);
  406. printf("BPB_HIDDEN    = %08lxn", bpbarray[rp -> r_unit].bpb_hidden);
  407. printf("BPB_HUGE      = %08lxn", bpbarray[rp -> r_unit].bpb_huge);
  408. #endif
  409. return S_DONE;
  410. }
  411. static WORD 
  412. blockio (rqptr rp)
  413. {
  414. REG retry = N_RETRY, remaining;
  415. UWORD cmd, total;
  416. ULONG start;
  417. byteptr trans;
  418. cmd = rp -> r_command;
  419. total = 0;
  420. trans = rp -> r_trans;
  421. tmark();
  422. for
  423. (
  424. remaining = rp -> r_count,
  425.  start = (rp -> r_start != HUGECOUNT ? rp -> r_start : rp -> r_huge)
  426.   + miarray[rp -> r_unit].mi_offset;
  427. remaining > 0;
  428. remaining -= count, trans += count * SEC_SIZE, start += count
  429. )
  430. {
  431. if(ltop(&track, &sector, &head,  rp -> r_unit, 1, start, trans) != 1)
  432. {
  433. /* printf("split sector at 0x%lx", trans);*/
  434. }
  435. count = ltop(&track, &sector, &head,  rp -> r_unit, remaining, start, trans);
  436. total += count;
  437. do
  438. {
  439. switch(cmd)
  440. {
  441. case C_INPUT:
  442. ret = fl_read((WORD)miarray[rp -> r_unit].mi_drive, (WORD)head, (WORD)track, (WORD)sector, (WORD)count, trans);
  443. break;
  444. case C_OUTPUT:
  445. case C_OUTVFY:
  446. ret = fl_write((WORD)miarray[rp -> r_unit].mi_drive, (WORD)head, (WORD)track, (WORD)sector, (WORD)count, trans);
  447. break;
  448. default:
  449. return failure(E_FAILURE);
  450. }
  451. } while (ret != 0 && --retry > 0);
  452. if(ret != 0)
  453. {
  454. rp -> r_count = 0;
  455. return dskerr(ret);
  456. }
  457. if(cmd == C_OUTVFY)
  458. {
  459. ret = fl_verify((WORD)miarray[rp -> r_unit].mi_drive, (WORD)head, (WORD)track, (WORD)sector, (WORD)count, rp -> r_trans);
  460. if(ret != 0)
  461. {
  462. rp -> r_count = 0;
  463. return dskerr(ret);
  464. }
  465. }
  466. }
  467. rp -> r_count = total;
  468. return S_DONE;
  469. }
  470. static WORD
  471. blk_error (rqptr rp)
  472. {
  473. rp -> r_count = 0;
  474. return failure(E_FAILURE); /* general failure */
  475. }
  476. static WORD
  477. dskerr (COUNT code)
  478. {
  479. /* printf("diskette error:nhead = %dntrack = %dnsector = %dncount = %dn",
  480. head, track, sector, count);*/
  481. switch(code & 0x03)
  482. {
  483. case 1: /* invalid command - general failure */
  484. if(code & 0x08)
  485. return(E_FAILURE);
  486. else
  487. return failure(E_CMD);
  488. case 2: /* address mark not found - general  failure */
  489. return failure(E_FAILURE);
  490. case 3: /* write protect */
  491. return failure(E_WRPRT);
  492. default:
  493. if(code & 0x80) /* time-out */
  494. return failure(E_NOTRDY);
  495. else if(code & 0x40) /* seek error */
  496. return failure(E_SEEK);
  497. else if(code & 0x10) /* CRC error */
  498. return failure(E_CRC);
  499. else if(code & 0x04)
  500. return failure(E_NOTFND);
  501. else
  502. return failure(E_FAILURE);
  503. }
  504. }
  505. /* */
  506. /* Do logical block number to physical head/track/sector mapping */
  507. /* */
  508. static COUNT
  509. ltop (WORD *trackp, WORD *sectorp, WORD *headp, REG COUNT unit, COUNT count, LONG strt_sect, byteptr strt_addr)
  510. {
  511. #ifdef I86
  512. ULONG ltemp;
  513. #endif
  514. REG ls, ps;
  515. #ifdef I86
  516. /* Adjust for segmented architecture */
  517. ltemp = (((ULONG)mk_segment(strt_addr) << 4) + mk_offset(strt_addr)) & 0xffff;
  518. /* Test for 64K boundary crossing and return count large */
  519. /* enough not to exceed the threshold. */
  520. count = (((ltemp + SEC_SIZE * count) & 0xffff0000l) != 0l)
  521. ? (0xffffl - ltemp) / SEC_SIZE
  522. : count;
  523. #endif
  524. *trackp = strt_sect / (miarray[unit].mi_heads * miarray[unit].mi_sectors);
  525. *sectorp = strt_sect % miarray[unit].mi_sectors + 1;
  526. *headp = (strt_sect % (miarray[unit].mi_sectors * miarray[unit].mi_heads))
  527. / miarray[unit].mi_sectors;
  528. if(((ls = *headp * miarray[unit].mi_sectors + *sectorp - 1) + count) >
  529. (ps = miarray[unit].mi_heads * miarray[unit].mi_sectors))
  530. count = ps - ls;
  531. return count;
  532. }