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