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