home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / TTFHDX / BSL.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  20.0 KB  |  701 lines

  1. /*
  2.  * BSL.C
  3.  *
  4.  *     Functions to manipulate the Bad Sector List.
  5.  *
  6.  * 25-Nov-87    ml.    Started this mess.
  7.  * 04-Dec-87    ml.    Hmmm, looks OK.
  8.  * 11-Dec-87    ml.    Added bsl2fat().
  9.  * 14-Dec-87    ml.    Structure of BSL is changed (_again_!).
  10.  *            Now, first entry in BSL contains number VENDOR
  11.  *            entries.  First byte of 2nd entry is the checksum
  12.  *            byte, while 2nd and 3rd bytes are reserved for 
  13.  *            future use.
  14.  * 14-Sep-89    ml.    Uses Rwabs() instead of hread() and hwrite().
  15.  *            Will handle SCSI as well as ACSI drives.
  16.  * 21-Sep-89    ml.    Modified to work with big sectors for big 
  17.  *            partitions.
  18.  *
  19.  */
  20.  
  21. #include <obdefs.h>
  22. #include <osbind.h>
  23. #include "fhdx.h"
  24. #include "define.h"
  25. #include "part.h"
  26. #include "bsl.h" 
  27. #include "addr.h" 
  28. #include "lrwabs.h" 
  29.  
  30. /* Globals */
  31. char *bsl;                /* bad sector list */
  32. long bslsiz;                /* num sectors BSL occupies */
  33.  
  34. extern SECTOR *badbuf;
  35.  
  36. /*
  37.  *  Get size of the Bad Sector List (in sectors)
  38.  *    Input:
  39.  *        pdev - physical unit BSL belongs to.
  40.  *    Return:
  41.  *        number of sectors BSL occupies.
  42.  */
  43. long 
  44. gbslsiz(pdev) 
  45. int pdev;    /* physical device number */
  46. {
  47.     char bs[512];    /* boot sector image */
  48.     
  49.     if (getroot(pdev, bs) == ERROR)
  50.         return ((long)err(rootread));
  51.     
  52.     if (((RSECT *)(bs + 0x200 - sizeof(RSECT)))->bsl_st != STBSL) {
  53.         form_alert(1, "[1][No BSL recorded in root sector!][ OK ]");
  54.         return 0L;
  55.     }       
  56.     
  57.     return(((RSECT *)(bs + 0x200 - sizeof(RSECT)))->bsl_cnt);
  58. }
  59.  
  60.  
  61. /*
  62.  *  Set BSL parameters (starting sector and size of BSL) into
  63.  *  root sector image.
  64.  *    Input:
  65.  *        image - root sector image.
  66.  */
  67. sbslparm(image)
  68. char *image;
  69. {
  70.     ((RSECT *)(image + 0x200 - sizeof(RSECT)))->bsl_st = STBSL;
  71.     ((RSECT *)(image + 0x200 - sizeof(RSECT)))->bsl_cnt = bslsiz;
  72. }
  73.  
  74.  
  75. /* 
  76.  *  Create a BSL in memory.
  77.  *    Input:
  78.  *        pdev - physical unit BSL will belong to.
  79.  *        type - kind of BSL to be created. NEW or EXPAND.
  80.  *        nents - number of VENDOR entries BSL should hold.
  81.  *    Output:
  82.  *        bsl - pointer to the BSL. (in bsl.h)
  83.  *    Return:
  84.  *        OK - everything is fine.
  85.  *        ERROR - anything is wrong.
  86.  *    Comment:
  87.  *        "NEW" means to create a totally new BSL.
  88.  *        "EXPAND" means to expand an existing BSL.
  89.  */
  90. creabsl(pdev, type, nents)
  91. int  pdev;    /* physical unit number */
  92. int  type;    /* kind of BSL to be created */
  93. long  nents;    /* num VENDOR entries in BSL */
  94. {
  95.     BYTE *newbsl;  /* BSL just created */
  96.     long l, size;  /* l - index into BSL;  size - size of BSL in bytes */ 
  97.     long start;       /* where to start initializing entries to zeroes */
  98.     long nument();
  99.  
  100.     if (type == NEW) {
  101.     if (form_alert(1, "[1][Create a new BSL?][ Yes |  No  ]") == 2)
  102.         return ERROR;
  103.     }
  104.     
  105.     if (nents == 0) {    /* no VENDOR entries specified */
  106.         size = 512L;    /* default size of BSL to 1 sector */
  107.     } else {       /* num VENDOR entries is specified */
  108.         /*------------------------------------------------------*/
  109.         /* Calculate length of BSL in bytes.            */
  110.         /* Have to add space for reserved entries and USER list    */
  111.         /* (note: (+1) to round up)                */
  112.         /*------------------------------------------------------*/
  113.     size = ((nents + RENT + WARNBADSECTS)/EPS + 1) * 512L;
  114.     }
  115.     
  116.     /* allocate enough memory for new BSL */
  117.     if ((newbsl = (BYTE *)mymalloc((int)size)) <= 0)
  118.         return err(nomemory);
  119.     
  120.     if (type == NEW) {    /* a new BSL */
  121.         start = 0;    /* start at 0th entry, i.e. init whole BSL to 0s */
  122.     }    
  123.     else {        /* expand the BSL */
  124.         /* start init to 0s after VENDOR list */
  125.     start = (nument(VENDOR) + RENT) * BPE;
  126.     
  127.         /* copy original BSL into this expanded memory */
  128.         for (l = 0; l < start; l++)
  129.             newbsl[l] = bsl[l];
  130.     }
  131.         
  132.     /* free up old BSL */
  133.     if (bsl > 0L) free(bsl);
  134.     bsl = newbsl;
  135.     
  136.     /* init BSL to zeroes beginning at 'start'th entry */
  137.     for (l = start; l < size; l++)
  138.         bsl[l] = 0;
  139.         
  140.     /* install BSL info */
  141.     bslsiz = size/512;    /* current num sectors BSL occupies */
  142.     put3bytes(bsl, nents);  /* num VENDOR entries */
  143.     mkmagic();    /* make the BSL checks sum to BSLMAGIC byte-wise */
  144.                           
  145.     return OK;
  146. }
  147.  
  148.  
  149. /*
  150.  *  Read the BSL into memory.
  151.  *    Input:
  152.  *        pdev - physical unit that contains the BSL.
  153.  *    Output:
  154.  *        bsl - pointer to the BSL.  (in bsl.h)
  155.  *    Return:
  156.  *        OK - everything is fine.
  157.  *        INVALID - BSL doesn't checksum correctly.
  158.  *        ERROR - can't read BSL.
  159.  */
  160. rdbsl(pdev)
  161. int pdev;    /* physical unit to read from */
  162. {
  163.     int ret;
  164.     extern HINFO hinfo;
  165.     
  166. rdagain:    
  167.     if ((ret = Lrwabs(PHYSREAD, bsl, (WORD)bslsiz, (SECTOR)STBSL, pdev+2))
  168.          == ERROR) {
  169.     if (form_alert(1, "[1][Read from BSL timed out!][ Retry | Quit ]")
  170.         == 1) {
  171.         goto rdagain;
  172.     }
  173.         return ERROR;
  174.     } else if (ret > 0) {
  175.         ret = err(bslread);
  176.         errcode(pdev);
  177.         return ERROR;
  178.     } else {
  179.         if ((ret = sumbsl()) == INVALID) {    /* if BSL is INVALID */
  180.             err(cruptbsl);
  181.             dsplybsl(pdev, (UWORD)hinfo.hi_dhc, (UWORD)hinfo.hi_spt);
  182.             return INVALID;
  183.         }
  184.         return OK;
  185.     }
  186. }
  187.  
  188.  
  189. /*
  190.  *  Count number of entries in the requested portion of BSL.
  191.  *    Input:
  192.  *        portion - portion of BSL.  MEDIA, VENDOR, USER or UNUSED.
  193.  *    Return:
  194.  *        Number of entries of the requested portion.
  195.  *    Comments:
  196.  *        There are 3 bytes per entry (BPE), and the first 2 entries
  197.  *    are reserved (RENT) for BSL info.
  198.  */
  199. long
  200. nument(portion)
  201. int portion;        /* portion of BSL to be counted */
  202. {
  203.     long  vdr, usr;        /* num ent in VENDOR list, num ent in USER list */
  204.     long  nbytes, offset;   /* BSL's len in bytes, index into BSL */
  205.     long  get3bytes();
  206.     
  207.     /* 2nd entry in BSL contains num entries in VENDOR list */
  208.     vdr = get3bytes(bsl);
  209.     
  210.     if (portion == VENDOR)  return (vdr);
  211.     
  212.     nbytes = bslsiz*512;    /* num bytes in BSL */
  213.     
  214.     /* num bytes available for valid entries */
  215.     /* (need this because nbytes may not be divisible by BPE) */
  216.     nbytes -= (nbytes % BPE);
  217.     
  218.     /* find out num entries in USER list */
  219.     usr = 0;
  220.     for (offset = (RENT+vdr)*BPE;  /* index into beginning of USER list */
  221.          (offset < nbytes)       /* while not at end of BSL */
  222.      && get3bytes(bsl+offset); /* and it's a used entry */
  223.          offset += BPE)           /* increment index */
  224.         usr++;        /* increment num entries for USER list */
  225.          
  226.     if (portion == USER)
  227.         return (usr);        /* num entries in USER list */
  228.         
  229.     if (portion == MEDIA)
  230.         return (vdr+usr);    /* num entries in MEDIA list */     
  231.         
  232.     /* portion == UNUSED */
  233.     return ((nbytes/BPE)-RENT-vdr-usr);
  234. }
  235.  
  236.  
  237. /*
  238.  *  Write the BSL into the disk.
  239.  *    Input:
  240.  *        pdev - physical unit number BSL belongs to.
  241.  *        bsl - pointer to buffer containing the BSL. (in bsl.h)
  242.  *    Return:
  243.  *        OK - everything is fine.
  244.  *        ERROR - can't write BSL.
  245.  */
  246. wrbsl(pdev)
  247. int pdev;    /* physical unit number */
  248. {
  249.     extern HINFO hinfo;
  250.     int ret;
  251.     
  252. wrtagain:
  253.     if ((ret = Lrwabs(PHYSWRT, bsl, (WORD)bslsiz, (SECTOR)STBSL, pdev+2))
  254.          == ERROR) {
  255.     if (form_alert(1, "[1][Write to BSL timed out!][ Retry | Quit ]")
  256.         == 1) {
  257.         goto wrtagain;
  258.     }
  259.         return ERROR;
  260.     } else if (ret > 0) {
  261.     err(bslwrite);
  262.         errcode(pdev);
  263.         dsplybsl(pdev, (UWORD)hinfo.hi_dhc, (UWORD)hinfo.hi_spt);
  264.         return ERROR;
  265.     }
  266.         
  267.     return OK;
  268.  
  269.  
  270. /*
  271.  *  Sort the BSL in memory in ascending order.
  272.  *    Input:
  273.  *        entries - number of used entries in BSL
  274.  *        bsl - pointer to the BSL. (in bsl.h)
  275.  *    Output:
  276.  *        a sorted bsl.
  277.  *    Algorithm:
  278.  *        Bubble sort.
  279.  *    Comments:
  280.  *        The reserved entries won't be sorted.
  281.  */
  282. sortbsl(entries)
  283. long  entries;    /* num entries in BSL */
  284. {
  285.     long  i, e1, e2;
  286.     long  start;    /* beginning byte of entries in BSL */
  287.     long  end;        /* tail byte of BSL */
  288.     int   change;    /* signal if changes have been made in current pass */
  289.     long  get3bytes();
  290.     
  291.     if (entries == 0L || entries == 1L)  /* BSL doesn't need to be sorted */
  292.         return;
  293.             
  294.     change = 1;        /* assume list is not in order */
  295.     start = RENT*BPE;    /* beginning of entries in BSL */
  296.     end = entries * BPE;
  297.     while (1) {
  298.         if (change == 0)    /* if no changes made, DONE --> HOME */
  299.         return;
  300.         
  301.         change = 0;    /* assume list is in order */
  302.         for (i = start; i <= end; i += BPE) {
  303.             e1 = get3bytes(bsl+i);
  304.             e2 = get3bytes(bsl+i+BPE);
  305.             if (e1 > e2) {            /* switch if out of order */
  306.                 put3bytes(bsl+i, e2);
  307.                 put3bytes(bsl+i+BPE, e1);
  308.                 change = 1;
  309.             }
  310.         }
  311.         end -= BPE;
  312.     }
  313. }
  314.  
  315.  
  316. /*
  317.  *  Search through a sorted BSL for a given sector number.
  318.  *    Input:
  319.  *        sect - sector number searching for.
  320.  *        entries - number of used entries in the BSL.
  321.  *    Return:
  322.  *        YES - if given sector is found.
  323.  *        NO - if given sector is not found.
  324.  *    Algorithm:
  325.  *        Binary Search.
  326.  */
  327. srchbsl(sect, entries)
  328. SECTOR  sect;    /* sector searching for */
  329. long  entries;    /* num used entries in BSL */
  330. {
  331.     long  start, mid, end; /* start, middle and end indices into list */
  332.     SECTOR  temp;       /* sector number in middle of list */
  333.     long  get3bytes();
  334.  
  335.     start = RENT;        /* start after reserved entries */
  336.     end = entries+RENT-1;    /* end of BSL */ 
  337.     
  338.     while (1) {
  339.          mid = (start + end) / 2;        /* middle entry in list */
  340.         temp = get3bytes(bsl+(mid*BPE));    /* sector num at mid entry */
  341.         
  342.         if (sect == temp)    /* given sector == sector at mid entry */
  343.             return YES;        /* given sector found in list */
  344.         else if (sect < temp)    /* given sector < sector at mid entry */
  345.             end = mid - 1;    /* limit search to smaller sector num */
  346.         else            /* given sector > sector at mid entry */
  347.             start = mid + 1;    /* limit search to larger sector num */
  348.             
  349.         if (end < start)    /* list is exhausted */
  350.             return NO;        /* can't find given sector */    
  351.     }
  352. }
  353.  
  354.  
  355. /*
  356.  *  Checksum (byte-wise) the BSL.
  357.  *    Input:
  358.  *        bsl - pointer to the BSL.  (in bsl.h)
  359.  *    Return:
  360.  *        OK - BSL checksum to BSLMAGIC (0xa5).
  361.  *        INVALID - BSL does not checksum to BSLMAGIC.
  362.  */
  363. sumbsl()
  364. {
  365.     register BYTE sum;    /* byte-wise sum of BSL */
  366.     long i;        /* index into BSL */
  367.     long length;    /* length of BSL in bytes */
  368.  
  369.     length = bslsiz*512;    /* length of entire BSL */
  370.     sum = 0;    /* initialize the sum */
  371.     
  372.     /* Sum up values in the BSL by byte */
  373.     for (i = 0; i < length; i++) {
  374.         sum += bsl[i];
  375.     }
  376.     if (sum != BSLMAGIC) {    /* doesn't checksum correctly */
  377.         return INVALID;
  378.     }
  379.     return OK;    /* checksum correctly */
  380. }
  381.  
  382.  
  383. /*
  384.  *  Make the BSL checks sum to BSLMAGIC.
  385.  */
  386. mkmagic()
  387. {
  388.     register BYTE diff;    /* difference to make BSL checks sum correctly */
  389.     long i;        /* index into BSL */
  390.     long len;        /* length of BSL in bytes */
  391.     
  392.     len = bslsiz*512;    /* length of entire BSl */
  393.     diff = BSLMAGIC;    /* initialize the difference */
  394.     
  395.     /* find out what number would make BSL checks sum to BSLMAGIC */
  396.     for (i = 0; i < len; i++) {
  397.         diff -= bsl[i];
  398.     }
  399.     
  400.     /* add that difference to checksum byte (1st byte of 2nd entry of BSL) */
  401.     bsl[BPE] += diff;
  402. }
  403.  
  404.  
  405. /*
  406.  *  Add bad sectors found to the Bad Sector List.
  407.  *    Input:
  408.  *        pdev - physical unit BSL belongs to.
  409.  *        portion - portion of BSL to add to.  VENDOR or USER.
  410.  *        nbad - number of bad sectors to be added.
  411.  *    Return:
  412.  *        nadd - number of new bad sectors added to the BSL.
  413.  *        USRFULL - user part of the BSL is filled up.
  414.  *        NOMEM - not enough memory for add buffer or BSL.
  415.  *        ERROR - something is wrong.
  416.  *    Comment:
  417.  *        The entry will be added only if it is not already on the
  418.  *    bad sector list.  Binary search is performed to guarantee this.
  419.  *        If the VENDOR list is full, this routine will take care
  420.  *    of the expansion of the list also.
  421.  */
  422. addbsl(pdev, portion, nbad) 
  423. int pdev;        /* physical unit number */
  424. int portion;        /* portion of BSL */
  425. int nbad;        /* num of bad sectors to be added */
  426. {
  427.     long  entries;    /* num entries to be retained in BSL */
  428.     long  empty;    /* num empty slots available for adding entries */
  429.     long  end;        /* address of end of BSL */
  430.     int  i, toadd;    /* index to badbuf, num of bad sectors to be added */
  431.     int  ret;        /* return code */
  432.     SECTOR *addbuf;    /* bad sectors to be added to BSL */
  433.     long  nument();
  434.     
  435.     /* Allocate memory for sector numbers of bad sectors to be added */
  436.     if ((addbuf = (SECTOR *)mymalloc(nbad*4)) <= 0) {
  437.         err(nomemory);
  438.         return NOMEM;
  439.     }
  440.     
  441.     if (portion == VENDOR) {    /* adding to VENDOR list */
  442.         entries = nument(VENDOR);   /* only keep the VENDOR list */
  443.         empty = 0;            /* there's no unused slot for VENDOR ent */
  444.     } else {            /* adding to USER list */
  445.         entries = nument(MEDIA);    /* keep entire list */
  446.         empty = nument(UNUSED);     /* slots left unused */
  447.     }
  448.     sortbsl(entries);        /* sort BSL in ascending order */
  449.     toadd = 0;            /* none is to be added to BSL yet */
  450.  
  451.     /* For all bad sectors found, search for them in the current BSL.
  452.        Add them to the list only when they are not already recorded.  */    
  453.     if (entries) {    /* only search if BSL is not empty */
  454.     for (i = 0; i < nbad; i++) {
  455.         if (srchbsl(*(badbuf+i), entries) == NO) {
  456.         addbuf[toadd] = *(badbuf+i);
  457.         toadd++;
  458.         }
  459.         }
  460.     } else {  /* add in all bad sectors found */
  461.     for (i = 0; i < nbad; i++)
  462.         addbuf[i] = *(badbuf+i);
  463.         toadd = nbad;
  464.     }
  465.     
  466.     /* All bad sectors found have been recorded.  Nothing is added to BSL */
  467.     if (toadd == 0) {
  468.         if (portion == USER && (ret = rdbsl(pdev)) != OK) {
  469.             if (ret == INVALID)
  470.                 err(cruptbsl);
  471.         goto togo;
  472.     }
  473.         ret = toadd;
  474.         goto togo;
  475.     }
  476.     
  477.     /*------------------------------------------------------------------*/
  478.     /* Check if there are enough empty slots for new entries.  If not,    */
  479.     /* determine what kind of entries we are adding, VENDOR or USER.    */    
  480.     /* Expand the BSL if we are adding to VENDOR list.  Give warning    */
  481.     /* if we are adding to USER list.                          */
  482.     /*------------------------------------------------------------------*/
  483.     if (toadd > empty) {
  484.         if (portion == VENDOR) {    /* this only happens at format time */
  485.         /* expanded BSL should hold (entries + toadd) VENDOR entries */
  486.         if ((ret = creabsl(pdev, EXPAND, entries+toadd)) != OK)
  487.             goto togo;
  488.         } else {        /* We are adding to USER list */
  489.             err(manybad);
  490.             toadd = empty;    /* num ent to add = empty slots available */
  491.         }
  492.     }
  493.     
  494.     /* Read in orig unsorted list if adding USER entries */
  495.     if (portion == USER) {
  496.         if ((ret = rdbsl(pdev)) != OK) {
  497.             if (ret == INVALID)
  498.                 err(cruptbsl);
  499.             goto togo;
  500.         }
  501.     }
  502.                 
  503.     /* Append new entries to end of BSL */
  504.     end = bsl + (RENT + entries)*BPE;    /* end of BSL */
  505.     for (i = 0; i < toadd; i++) {
  506.         put3bytes((end + i*BPE), addbuf[i]);
  507.     }
  508.     
  509.     /* make BSL checks sum to magic number */
  510.     mkmagic();
  511.  
  512.     if (portion == USER && toadd == empty) {
  513.         ret = USRFULL;
  514.         goto togo;
  515.     }
  516.  
  517.     ret = toadd;
  518. togo:
  519.     if (addbuf > 0L) free(addbuf);            
  520.     return(ret);
  521. }
  522.  
  523.  
  524. /*
  525.  *  Mark bad sectors from the BSL to FATs of a partition.
  526.  *    Input:
  527.  *        ldev - logical device the FATs belong to.
  528.  *        fat0 - logical sector number of where FAT 0 starts.
  529.  *        fatsiz - size of FAT in # log sectors.
  530.  *        data - logical sector number of where data clusters start.
  531.  *        portion - part of BSL to mark from.
  532.  *        sratio - 
  533.  */
  534. bsl2fat(ldev, fat0, fatsiz, data, portion, sratio)
  535. int  ldev;    /* logical device number */
  536. SECTOR fat0;    /* starting sector number (logical) of FAT 0 */ 
  537. WORD fatsiz;    /* FAT size in # log sectors */
  538. SECTOR data;    /* starting sector number (logical) of data clusters */
  539. int portion;    /* part of BSL to mark from, VENDOR or MEDIA */
  540. WORD sratio;    /* log sector size : phys sector size */
  541. {
  542.     long nument(), entries;    /* num entries in the list to be considered */
  543.     long i, end;        /* indices to the list to be considered */
  544.     SECTOR badsect;        /* a bad sector in the list */
  545.     SECTOR pstart;        /* phys sector num where partition starts */
  546.     SECTOR pdata;        /* phys sector num where data block starts */
  547.     SECTOR pend;        /* phys sector num where data block ends */
  548.     extern SECTOR logstart(), logend();
  549.     int nbad;
  550.     
  551.     pstart = logstart(ldev);        /* find partition phys start sector */
  552.     pdata = pstart + (data*sratio);    /* find data phys start sector */
  553.     pend = logend(ldev);        /* find where data block ends */    
  554.     entries = nument(portion);        /* find num entries in given portion */
  555.     sortbsl(entries);            /* sort given portion of BSL */
  556.     
  557.     end = (RENT + entries) * BPE;
  558.     nbad = 0;
  559.     
  560.     /* Store vendor bad sectors of the logical device in badbuf */
  561.     for (i = BPE*RENT; i < end; i += BPE) {
  562.         if ((badsect = get3bytes(bsl+i)) > pend)
  563.             break;
  564.             
  565.         if (badsect >= pdata) {
  566.             *(badbuf+nbad) = badsect;
  567.             nbad++;
  568.             
  569.             /* if badbuf overflows, mark what we have so far in the FAT */
  570.             if (nbad == WARNBADSECTS) {
  571.                 if (fixbadcls(ldev, fat0, fatsiz, data, nbad, sratio) != OK) {
  572.                     return ERROR;
  573.                 }
  574.                 nbad = 0;    /* reinit num bad sectors in partition to 0 */
  575.             }
  576.         }
  577.     }
  578.     
  579.     /* Bad sectors in partition not marked in FAT yet */
  580.     if (nbad) {
  581.         if (fixbadcls(ldev, fat0, fatsiz, data, nbad, sratio) != OK) {
  582.             return ERROR;
  583.         }
  584.     }
  585.     
  586.     return OK;
  587. }
  588.  
  589.  
  590. /*
  591.  *  Count number of bad sectors on a logical drive recorded in BSL.
  592.  *    Input:
  593.  *        ldev - logical drive to be considered.
  594.  *    Return:
  595.  *        nbad - number of bad sectors found.
  596.  */
  597. long
  598. cntbad(ldev)
  599. int  ldev;    /* logical drive number */
  600. {
  601.     SECTOR pstart, pend;    /* phys starting and ending block of ldev */
  602.     extern SECTOR logstart(), logend();
  603.     long nbad=0L;        /* num bad sectors on ldev */
  604.     long entries, nument(), bslend;
  605.     long curr, get3bytes();
  606.     int done, i;
  607.     
  608.     pstart = logstart(ldev);    /* starting block # of partition */
  609.     pend = logend(ldev);    /* ending block # of partition */
  610.     entries = nument(MEDIA);    /* num entries in BSL */
  611.     sortbsl(entries);        /* sort BSL */
  612.     
  613.     done = 0;
  614.     bslend = (RENT+entries) * BPE;
  615.     for (i = RENT*BPE; (!done) && (i < bslend); i += BPE) {
  616.         curr = get3bytes(bsl+i);  /* get next entry in BSL */
  617.         if (curr < pstart)      /* not within logical drive's range yet */
  618.             continue;
  619.         if (curr <= pend)      /* within logical drive's range */
  620.             nbad++;
  621.         else done = 1;          /* pass logical drive's range */
  622.     }
  623.     return (nbad);
  624. }
  625.  
  626.  
  627. /*
  628.  *  Put a word into memory in 68000 format.
  629.  *    Input:
  630.  *        p - pointer to memory.
  631.  *        i - word to be put.
  632.  */
  633. putword(p, i)
  634. BYTE *p;
  635. unsigned int i;
  636. {
  637.     *p = i >> 8;
  638.     *(p+1) = i;
  639. }
  640.  
  641.  
  642. /*
  643.  *  Get a 68000 format word from memory.
  644.  *    Input:
  645.  *        p - pointer to memory.
  646.  *    Return:
  647.  *        i - word read from memory.
  648.  */        
  649. getword(p)
  650. BYTE *p;
  651. {
  652.     unsigned int i;
  653.     
  654.     i = *p;
  655.     i <<= 8;
  656.     i |= *(p+1);
  657.     return (i);
  658. }
  659.  
  660.  
  661. /*
  662.  *  Put 3 bytes (68000 format) into memory.
  663.  *    Input:
  664.  *        p - pointer to memory.
  665.  *        l - long which contains the 3 bytes at the low-bit end.
  666.  */
  667. put3bytes(p, l)
  668. BYTE *p;
  669. long l;
  670. {
  671.     *p = l >> 16;
  672.     *(p+1) = l >> 8;
  673.     *(p+2) = l;
  674. }    
  675.  
  676.  
  677. /*
  678.  *  Get 3 bytes (68000 format) from memory.
  679.  *    Input:
  680.  *        p - pointer to memory.
  681.  *    Return:
  682.  *        l - a long which contains the 3 bytes read in last 3 bytes.
  683.  */
  684. long
  685. get3bytes(p)
  686. BYTE *p;
  687. {
  688.     long  k=0x000000ff, l=0x000000ff;
  689.     
  690.     l &= *p;        /* first byte */
  691.     l <<= 16;
  692.     k &= *(p+1);    /* second byte */
  693.     k <<= 8;
  694.     l |= k;
  695.     k = 0x000000ff;
  696.     k &= *(p+2);    /* third byte */
  697.     l |= k;
  698.     return (l);
  699. }
  700.