Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00089 #include <dev/blockdev.h>
00090 
00091 #include <sys/event.h>
00092 
00093 #include <fs/dospart.h>
00094 #include <fs/phatio.h>
00095 #include <fs/phatutil.h>
00096 #include <fs/phatvol.h>
00097 
00098 #include <errno.h>
00099 #include <stdlib.h>
00100 #include <string.h>
00101 #include <memdebug.h>
00102 
00103 
00104 #if 0
00105 
00106 #define NUTDEBUG
00107 #include <stdio.h>
00108 #include <fs/phatdbg.h>
00109 #endif
00110 
00115 
00123 static uint32_t PhatCountFreeClusters(NUTDEVICE * dev)
00124 {
00125     uint32_t rc = 0;
00126     uint32_t i = 2;
00127     uint32_t link;
00128     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00129 
00130     if (vol->vol_type == 32) {
00131         while (i < vol->vol_last_clust) {
00132             if (Phat32GetClusterLink(dev, i, &link)) {
00133                 break;
00134             }
00135             if (link == 0) {
00136                 rc++;
00137             }
00138             i++;
00139         }
00140     } else if (vol->vol_type == 16) {
00141         while (i < vol->vol_last_clust) {
00142             if (Phat16GetClusterLink(dev, i, &link)) {
00143                 break;
00144             }
00145             if (link == 0) {
00146                 rc++;
00147             }
00148             i++;
00149         }
00150     } else {
00151         while (i < vol->vol_last_clust) {
00152             if (Phat12GetClusterLink(dev, i, &link)) {
00153                 break;
00154             }
00155             if (link == 0) {
00156                 rc++;
00157             }
00158             i++;
00159         }
00160     }
00161     return rc;
00162 }
00163 
00186 int PhatVolMount(NUTDEVICE * dev, NUTFILE * blkmnt, uint8_t part_type)
00187 {
00188     PHATVOL *vol;
00189     PHATVBR *vbr;
00190     BLKPAR_INFO pari;
00191     int sbn;
00192     NUTDEVICE *blkdev = blkmnt->nf_dev;
00193 
00194     
00195 
00196 
00197     if ((dev->dev_dcb = malloc(sizeof(PHATVOL))) == 0) {
00198         return -1;
00199     }
00200     vol = (PHATVOL *) memset(dev->dev_dcb, 0, sizeof(PHATVOL));
00201 
00202     
00203 
00204 
00205     switch (part_type) {
00206     case PTYPE_FAT32:
00207     case PTYPE_FAT32_LBA:
00208         vol->vol_type = 32;
00209         break;
00210     case PTYPE_FAT16:
00211     case PTYPE_FAT16_BIG:
00212     case PTYPE_FAT16_LBA:
00213         vol->vol_type = 16;
00214         break;
00215     case PTYPE_FAT12:
00216         vol->vol_type = 12;
00217         break;
00218     }
00219 
00220     
00221 
00222 
00223     pari.par_nfp = blkmnt;
00224     if ((*blkdev->dev_ioctl) (blkdev, NUTBLKDEV_INFO, &pari)) {
00225         free(vol);
00226         errno = ENODEV;
00227         return -1;
00228     }
00229 #if PHAT_SECTOR_BUFFERS
00230     for (sbn = 0; sbn < PHAT_SECTOR_BUFFERS; sbn++) {
00231         if ((vol->vol_buf[sbn].sect_data = malloc(pari.par_blksz)) == NULL) {
00232             PhatVolUnmount(dev);
00233             return -1;
00234         }
00235         vol->vol_buf[sbn].sect_num = (uint32_t)-1;
00236     }
00237 #else
00238     vol->vol_buf[0].sect_data = pari.par_blkbp;
00239 #endif
00240     sbn = 0;
00241 
00242     
00243 
00244 
00245 
00246     if (PhatSectorRead(blkmnt, 0, vol->vol_buf[sbn].sect_data)) {
00247         PhatVolUnmount(dev);
00248         return -1;
00249     }
00250     vol->vol_buf[sbn].sect_num = 0;
00251     vbr = (PHATVBR *) vol->vol_buf[sbn].sect_data;
00252 
00253     
00254 
00255 
00256 
00257 
00258 
00259     if (vol->vol_type == 0 && vbr->bios_rootsz == 0) {
00260         vol->vol_type = 32;
00261     }
00262 
00263     
00264     if (vol->vol_type != 32) {
00265         memcpy(&vbr->boot_drive, &vbr->bios_tabsz_big, 26);
00266         memset(&vbr->bios_tabsz_big, 0, 28);
00267     }
00268 #ifdef NUTDEBUG
00269     PhatDbgVbr(stdout, "Volume Boot Record", vbr);
00270 #endif
00271 
00272     
00273 
00274 
00275     if (vol->vol_buf[sbn].sect_data[510] != 0x55 || vol->vol_buf[sbn].sect_data[511] != 0xAA) {
00276         PhatVolUnmount(dev);
00277         errno = ENODEV;
00278         return -1;
00279     }
00280 
00281     
00282 
00283 
00284     if (vbr->bios_media != 0xF0 && vbr->bios_media < 0xF8) {
00285         PhatVolUnmount(dev);
00286         errno = ENODEV;
00287         return -1;
00288     }
00289 
00290     
00291 
00292 
00293     
00294     vol->vol_sectsz = vbr->bios_sectsz;
00295     if (vol->vol_sectsz < 512 || vol->vol_sectsz & 0xFF) {
00296         PhatVolUnmount(dev);
00297         errno = ENODEV;
00298         return -1;
00299     }
00300     
00301     if ((vol->vol_clustsz = vbr->bios_clustsz) == 0) {
00302         PhatVolUnmount(dev);
00303         errno = ENODEV;
00304         return -1;
00305     }
00306     
00307     if (vbr->bios_tabsz) {
00308         vol->vol_tabsz = vbr->bios_tabsz;
00309     } else {
00310         vol->vol_tabsz = vbr->bios_tabsz_big;
00311     }
00312     vol->vol_tab_sect[0] = vbr->bios_rsvd_sects;
00313     if (vbr->bios_ntabs > 1) {
00314         vol->vol_tab_sect[1] = vol->vol_tab_sect[0] + vol->vol_tabsz;
00315     }
00316     
00317     vol->vol_rootsz = (vbr->bios_rootsz * sizeof(PHATDIRENT) +  
00318                        vol->vol_sectsz - 1) / vol->vol_sectsz;
00319     vol->vol_root_sect = vbr->bios_rsvd_sects + 
00320         vbr->bios_ntabs * vol->vol_tabsz;
00321     if (vol->vol_type == 32) {
00322         vol->vol_root_clust = vbr->bios_root_clust;
00323     }
00324     
00325     vol->vol_data_sect = vol->vol_root_sect + vol->vol_rootsz;
00326     if (vbr->bios_volsz) {
00327         vol->vol_last_clust = vbr->bios_volsz - vol->vol_data_sect;
00328     } else {
00329         vol->vol_last_clust = vbr->bios_volsz_big - vol->vol_data_sect;
00330     }
00331     vol->vol_last_clust /= vol->vol_clustsz;
00332     
00333     vol->vol_last_clust += 2;
00334 
00335     
00336 
00337 
00338 
00339     if (vol->vol_type == 0) {
00340         if (vol->vol_last_clust > 4086) {
00341             vol->vol_type = 16;
00342         }
00343         else {
00344             vol->vol_type = 12;
00345         }
00346     }
00347 #ifdef NUTDEBUG
00348     printf("\n%lu cluster -> PHAT%d\n", vol->vol_last_clust, vol->vol_type);
00349 #endif
00350 
00351     dev->dev_icb = blkmnt;
00352 
00353     
00354     NutEventPost(&vol->vol_fsmutex);
00355     NutEventPost(&vol->vol_iomutex);
00356 
00357     vol->vol_numfree = PhatCountFreeClusters(dev);
00358 
00359     return 0;
00360 }
00361 
00372 int PhatVolUnmount(NUTDEVICE * dev)
00373 {
00374     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00375 
00376     if (vol) {
00377 #if PHAT_SECTOR_BUFFERS
00378         int sbn;
00379 
00380         for (sbn = 0; sbn < PHAT_SECTOR_BUFFERS; sbn++) {
00381             if (vol->vol_buf[sbn].sect_data) {
00382                 free(vol->vol_buf[sbn].sect_data);
00383             }
00384         }
00385 #endif
00386         free(vol);
00387     }
00388     return 0;
00389 }
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 uint32_t PhatClusterSector(NUTFILE * nfp, uint32_t clust)
00398 {
00399     NUTDEVICE *dev = nfp->nf_dev;
00400     PHATVOL *vol = (PHATVOL *) dev->dev_dcb;
00401 
00402     
00403 
00404 
00405 
00406     if (IsFixedRootDir(nfp)) {
00407         return vol->vol_root_sect;
00408     }
00409 
00410     
00411 
00412 
00413 
00414     if (clust >= 2) {
00415         clust -= 2;
00416     }
00417     return vol->vol_data_sect + clust * vol->vol_clustsz;
00418 }
00419