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