1 /*
2 * ADF Library. (C) 1997-2002 Laurent Clevy
3 *
4 * adf_hd.c
5 *
6 * $Id$
7 *
8 * harddisk / device code
9 *
10 * This file is part of ADFLib.
11 *
12 * ADFLib is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * ADFLib is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Foobar; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 *
26 */
27
28
29
30 #include<stdio.h>
31 #include<stdlib.h>
32 #include<string.h>
33
34 #include"adf_str.h"
35 #include"hd_blk.h"
36 #include"adf_raw.h"
37 #include"adf_hd.h"
38 #include"adf_util.h"
39 #include"adf_disk.h"
40 #include"adf_nativ.h"
41 #include"adf_dump.h"
42 #include"adf_err.h"
43
44 #include"defendian.h"
45
46 extern struct Env adfEnv;
47
48 /*
49 * adfDevType
50 *
51 * returns the type of a device
52 * only based of the field 'dev->size'
53 */
adfDevType(struct Device * dev)54 int adfDevType(struct Device* dev)
55 {
56 if( (dev->size==512*11*2*80) || /* BV */
57 (dev->size==512*11*2*81) || /* BV */
58 (dev->size==512*11*2*82) || /* BV */
59 (dev->size==512*11*2*83) ) /* BV */
60 return(DEVTYPE_FLOPDD);
61 else if (dev->size==512*22*2*80)
62 return(DEVTYPE_FLOPHD);
63 else if (dev->size>512*22*2*80)
64 return(DEVTYPE_HARDDISK);
65 else {
66 (*adfEnv.eFct)("adfDevType : unknown device type");
67 return(-1);
68 }
69 }
70
71
72 /*
73 * adfDeviceInfo
74 *
75 * display information about the device and its volumes
76 * for demonstration purpose only since the output is stdout !
77 *
78 * can be used before adfCreateVol() or adfMount()
79 */
adfDeviceInfo(struct Device * dev)80 void adfDeviceInfo(struct Device *dev)
81 {
82 int i;
83
84 printf("Cylinders = %d\n",dev->cylinders);
85 printf("Heads = %d\n",dev->heads);
86 printf("Sectors/Cyl = %d\n\n",dev->sectors);
87 if (!dev->isNativeDev)
88 printf("Dump device\n\n");
89 else
90 printf("Real device\n\n");
91 printf("Volumes = %d\n\n",dev->nVol);
92 /*
93 switch(dev->devType){
94 case DEVTYPE_FLOPDD:
95 printf("floppy dd\n"); break;
96 case DEVTYPE_FLOPHD:
97 printf("floppy hd\n"); break;
98 case DEVTYPE_HARDDISK:
99 printf("harddisk\n"); break;
100 case DEVTYPE_HARDFILE:
101 printf("hardfile\n"); break;
102 default:
103 printf("unknown devType!\n"); break;
104 }
105 */
106
107 for(i=0; i<dev->nVol; i++) {
108 if (dev->volList[i]->volName)
109 printf("%2d : %7d ->%7d, \"%s\"", i,
110 dev->volList[i]->firstBlock,
111 dev->volList[i]->lastBlock,
112 dev->volList[i]->volName);
113 else
114 printf("%2d : %7d ->%7d\n", i,
115 dev->volList[i]->firstBlock,
116 dev->volList[i]->lastBlock);
117 if (dev->volList[i]->mounted)
118 printf(", mounted");
119 putchar('\n');
120 }
121 }
122
123
124 /*
125 * adfFreeTmpVolList
126 *
127 */
adfFreeTmpVolList(struct List * root)128 void adfFreeTmpVolList(struct List *root)
129 {
130 struct List *cell;
131 struct Volume *vol;
132
133 cell = root;
134 while(cell!=NULL) {
135 vol = (struct Volume *)cell->content;
136 if (vol->volName!=NULL)
137 free(vol->volName);
138 cell = cell->next;
139 }
140 freeList(root);
141
142 }
143
144
145 /*
146 * adfMountHdFile
147 *
148 */
adfMountHdFile(struct Device * dev)149 RETCODE adfMountHdFile(struct Device *dev)
150 {
151 struct Volume* vol;
152 uint8_t buf[512];
153 int32_t size;
154 BOOL found;
155
156 dev->devType = DEVTYPE_HARDFILE;
157 dev->nVol = 0;
158 dev->volList = (struct Volume**)malloc(sizeof(struct Volume*));
159 if (!dev->volList) {
160 (*adfEnv.eFct)("adfMountHdFile : malloc");
161 return RC_ERROR;
162 }
163
164 vol=(struct Volume*)malloc(sizeof(struct Volume));
165 if (!vol) {
166 (*adfEnv.eFct)("adfMountHdFile : malloc");
167 return RC_ERROR;
168 }
169 dev->volList[0] = vol;
170 dev->nVol++; /* fixed by Dan, ... and by Gary */
171
172 vol->volName=NULL;
173
174 dev->cylinders = dev->size/512;
175 dev->heads = 1;
176 dev->sectors = 1;
177
178 vol->firstBlock = 0;
179
180 size = dev->size + 512-(dev->size%512);
181 /*printf("size=%ld\n",size);*/
182 vol->rootBlock = (size/512)/2;
183 /*printf("root=%ld\n",vol->rootBlock);*/
184 do {
185 adfReadDumpSector(dev, vol->rootBlock, 512, buf);
186 found = swapLong(buf)==T_HEADER && swapLong(buf+508)==ST_ROOT;
187 if (!found)
188 (vol->rootBlock)--;
189 }while (vol->rootBlock>1 && !found);
190
191 if (vol->rootBlock==1) {
192 (*adfEnv.eFct)("adfMountHdFile : rootblock not found");
193 return RC_ERROR;
194 }
195 vol->lastBlock = vol->rootBlock*2 - 1 ;
196
197 return RC_OK;
198 }
199
200
201 /*
202 * adfMountHd
203 *
204 * normal not used directly : called by adfMount()
205 *
206 * fills geometry fields and volumes list (dev->nVol and dev->volList[])
207 */
adfMountHd(struct Device * dev)208 RETCODE adfMountHd(struct Device *dev)
209 {
210 struct bRDSKblock rdsk;
211 struct bPARTblock part;
212 struct bFSHDblock fshd;
213 struct bLSEGblock lseg;
214 int32_t next;
215 struct List *vList, *listRoot;
216 int i;
217 struct Volume* vol;
218 int len;
219
220 if (adfReadRDSKblock( dev, &rdsk )!=RC_OK)
221 return RC_ERROR;
222
223 dev->cylinders = rdsk.cylinders;
224 dev->heads = rdsk.heads;
225 dev->sectors = rdsk.sectors;
226
227 /* PART blocks */
228 listRoot = NULL;
229 next = rdsk.partitionList;
230 dev->nVol=0;
231 vList = NULL;
232 while( next!=-1 ) {
233 if (adfReadPARTblock( dev, next, &part )!=RC_OK) {
234 adfFreeTmpVolList(listRoot);
235 (*adfEnv.eFct)("adfMountHd : malloc");
236 return RC_ERROR;
237 }
238
239 vol=(struct Volume*)malloc(sizeof(struct Volume));
240 if (!vol) {
241 adfFreeTmpVolList(listRoot);
242 (*adfEnv.eFct)("adfMountHd : malloc");
243 return RC_ERROR;
244 }
245 vol->volName=NULL;
246 dev->nVol++;
247
248 vol->firstBlock = rdsk.cylBlocks * part.lowCyl;
249 vol->lastBlock = (part.highCyl+1)*rdsk.cylBlocks -1 ;
250 vol->rootBlock = (vol->lastBlock - vol->firstBlock+1)/2;
251 vol->blockSize = part.blockSize*4;
252
253 len = min(31, part.nameLen);
254 vol->volName = (char*)malloc(len+1);
255 if (!vol->volName) {
256 adfFreeTmpVolList(listRoot);
257 (*adfEnv.eFct)("adfMount : malloc");
258 return RC_ERROR;
259 }
260 memcpy(vol->volName,part.name,len);
261 vol->volName[len] = '\0';
262
263 vol->mounted = FALSE;
264
265 /* stores temporaly the volumes in a linked list */
266 if (listRoot==NULL)
267 vList = listRoot = newCell(NULL, (void*)vol);
268 else
269 vList = newCell(vList, (void*)vol);
270
271 if (vList==NULL) {
272 adfFreeTmpVolList(listRoot);
273 (*adfEnv.eFct)("adfMount : newCell() malloc");
274 return RC_ERROR;
275 }
276
277 next = part.next;
278 }
279
280 /* stores the list in an array */
281 dev->volList = (struct Volume**)malloc(sizeof(struct Volume*) * dev->nVol);
282 if (!dev->volList) {
283 adfFreeTmpVolList(listRoot);
284 (*adfEnv.eFct)("adfMount : unknown device type");
285 return RC_ERROR;
286 }
287 vList = listRoot;
288 for(i=0; i<dev->nVol; i++) {
289 dev->volList[i]=(struct Volume*)vList->content;
290 vList = vList->next;
291 }
292 freeList(listRoot);
293
294 next = rdsk.fileSysHdrList;
295 while( next!=-1 ) {
296 if (adfReadFSHDblock( dev, next, &fshd )!=RC_OK) {
297 for(i=0;i<dev->nVol;i++) free(dev->volList[i]);
298 free(dev->volList);
299 (*adfEnv.eFct)("adfMount : adfReadFSHDblock");
300 return RC_ERROR;
301 }
302 next = fshd.next;
303 }
304
305 next = fshd.segListBlock;
306 while( next!=-1 ) {
307 if (adfReadLSEGblock( dev, next, &lseg )!=RC_OK) {
308 (*adfEnv.wFct)("adfMount : adfReadLSEGblock");
309 }
310 next = lseg.next;
311 }
312
313 return RC_OK;
314 }
315
316
317 /*
318 * adfMountFlop
319 *
320 * normaly not used directly, called directly by adfMount()
321 *
322 * use dev->devType to choose between DD and HD
323 * fills geometry and the volume list with one volume
324 */
adfMountFlop(struct Device * dev)325 RETCODE adfMountFlop(struct Device* dev)
326 {
327 struct Volume *vol;
328 struct bRootBlock root;
329 char diskName[35];
330
331 dev->cylinders = 80;
332 dev->heads = 2;
333 if (dev->devType==DEVTYPE_FLOPDD)
334 dev->sectors = 11;
335 else
336 dev->sectors = 22;
337
338 vol=(struct Volume*)malloc(sizeof(struct Volume));
339 if (!vol) {
340 (*adfEnv.eFct)("adfMount : malloc");
341 return RC_ERROR;
342 }
343
344 vol->mounted = TRUE;
345 vol->firstBlock = 0;
346 vol->lastBlock =(dev->cylinders * dev->heads * dev->sectors)-1;
347 vol->rootBlock = (vol->lastBlock+1 - vol->firstBlock)/2;
348 vol->blockSize = 512;
349 vol->dev = dev;
350
351 if (adfReadRootBlock(vol, vol->rootBlock, &root)!=RC_OK)
352 return RC_ERROR;
353 memset(diskName, 0, 35);
354 memcpy(diskName, root.diskName, root.nameLen);
355
356 vol->volName = strdup(diskName);
357
358 dev->volList =(struct Volume**) malloc(sizeof(struct Volume*));
359 if (!dev->volList) {
360 free(vol);
361 (*adfEnv.eFct)("adfMount : malloc");
362 return RC_ERROR;
363 }
364 dev->volList[0] = vol;
365 dev->nVol = 1;
366
367 /*printf("root=%d\n",vol->rootBlock); */
368 return RC_OK;
369 }
370
371
372 /*
373 * adfMountDev
374 *
375 * mount a dump file (.adf) or a real device (uses adf_nativ.c and .h)
376 *
377 * adfInitDevice() must fill dev->size !
378 */
adfMountDev(char * filename,BOOL ro)379 struct Device* adfMountDev( char* filename, BOOL ro)
380 {
381 struct Device* dev;
382 struct nativeFunctions *nFct;
383 RETCODE rc;
384 uint8_t buf[512];
385
386 dev = (struct Device*)malloc(sizeof(struct Device));
387 if (!dev) {
388 (*adfEnv.eFct)("adfMountDev : malloc error");
389 return NULL;
390 }
391
392 dev->readOnly = ro;
393
394 /* switch between dump files and real devices */
395 nFct = adfEnv.nativeFct;
396 dev->isNativeDev = (*nFct->adfIsDevNative)(filename);
397 if (dev->isNativeDev)
398 rc = (*nFct->adfInitDevice)(dev, filename,ro);
399 else
400 rc = adfInitDumpDevice(dev,filename,ro);
401 if (rc!=RC_OK) {
402 free(dev); return(NULL);
403 }
404
405 dev->devType = adfDevType(dev);
406
407 switch( dev->devType ) {
408
409 case DEVTYPE_FLOPDD:
410 case DEVTYPE_FLOPHD:
411 if (adfMountFlop(dev)!=RC_OK) {
412 if (dev->isNativeDev) /* BV */
413 (*nFct->adfReleaseDevice)(dev); /* BV */
414 else /* BV */
415 adfReleaseDumpDevice(dev); /* BV */
416 free(dev); return NULL;
417 }
418 break;
419
420 case DEVTYPE_HARDDISK:
421 /* to choose between hardfile or harddisk (real or dump) */
422 if (dev->isNativeDev) /* BV ...from here*/
423 rc = (*nFct->adfNativeReadSector)(dev, 0, 512, buf);
424 else
425 rc = adfReadDumpSector(dev, 0, 512, buf);
426 if( rc!=RC_OK ) {
427 nFct = adfEnv.nativeFct;
428 if (dev->isNativeDev)
429 (*nFct->adfReleaseDevice)(dev);
430 else
431 adfReleaseDumpDevice(dev);
432 (*adfEnv.eFct)("adfMountDev : adfReadDumpSector failed");
433 free(dev); return NULL;
434 }
435
436 /* a file with the first three bytes equal to 'DOS' */
437 if (!dev->isNativeDev && strncmp("DOS",(char*)buf,3)==0) {
438 if (adfMountHdFile(dev)!=RC_OK) {
439 if (dev->isNativeDev)
440 (*nFct->adfReleaseDevice)(dev);
441 else
442 adfReleaseDumpDevice(dev);
443 free(dev); return NULL;
444 }
445 }
446 else if (adfMountHd(dev)!=RC_OK) {
447 if (dev->isNativeDev)
448 (*nFct->adfReleaseDevice)(dev);
449 else
450 adfReleaseDumpDevice(dev);
451 free(dev); return NULL; /* BV ...to here.*/
452 }
453 break;
454
455 default:
456 (*adfEnv.eFct)("adfMountDev : unknown device type");
457 if (dev->isNativeDev) /* BV */
458 (*nFct->adfReleaseDevice)(dev); /* BV */
459 else /* BV */
460 adfReleaseDumpDevice(dev); /* BV */
461 free(dev); return NULL; /* BV */
462 }
463
464 return dev;
465 }
466
467
468 /*
469 * adfCreateHdHeader
470 *
471 * create PARTIALLY the sectors of the header of one harddisk : can not be mounted
472 * back on a real Amiga ! It's because some device dependant values can't be guessed...
473 *
474 * do not use dev->volList[], but partList for partitions information : start and len are cylinders,
475 * not blocks
476 * do not fill dev->volList[]
477 * called by adfCreateHd()
478 */
adfCreateHdHeader(struct Device * dev,int n,struct Partition ** partList)479 RETCODE adfCreateHdHeader(struct Device* dev, int n, struct Partition** partList )
480 {
481 int i;
482 struct bRDSKblock rdsk;
483 struct bPARTblock part;
484 struct bFSHDblock fshd;
485 struct bLSEGblock lseg;
486 SECTNUM j;
487 int len;
488
489
490 /* RDSK */
491
492 memset((uint8_t*)&rdsk,0,sizeof(struct bRDSKblock));
493
494 rdsk.rdbBlockLo = 0;
495 rdsk.rdbBlockHi = (dev->sectors*dev->heads*2)-1;
496 rdsk.loCylinder = 2;
497 rdsk.hiCylinder = dev->cylinders-1;
498 rdsk.cylBlocks = dev->sectors*dev->heads;
499
500 rdsk.cylinders = dev->cylinders;
501 rdsk.sectors = dev->sectors;
502 rdsk.heads = dev->heads;
503
504 rdsk.badBlockList = -1;
505 rdsk.partitionList = 1;
506 rdsk.fileSysHdrList = 1 + dev->nVol;
507
508 if (adfWriteRDSKblock(dev, &rdsk)!=RC_OK)
509 return RC_ERROR;
510
511 /* PART */
512
513 j=1;
514 for(i=0; i<dev->nVol; i++) {
515 memset(&part, 0, sizeof(struct bPARTblock));
516
517 if (i<dev->nVol-1)
518 part.next = j+1;
519 else
520 part.next = -1;
521
522 len = min(MAXNAMELEN,strlen(partList[i]->volName));
523 part.nameLen = len;
524 strncpy(part.name, partList[i]->volName, len);
525
526 part.surfaces = dev->heads;
527 part.blocksPerTrack = dev->sectors;
528 part.lowCyl = partList[i]->startCyl;
529 part.highCyl = partList[i]->startCyl + partList[i]->lenCyl -1;
530 strncpy(part.dosType, "DOS", 3);
531
532 part.dosType[3] = partList[i]->volType & 0x01;
533
534 if (adfWritePARTblock(dev, j, &part))
535 return RC_ERROR;
536 j++;
537 }
538
539 /* FSHD */
540
541 strncpy(fshd.dosType,"DOS",3);
542 fshd.dosType[3] = partList[0]->volType;
543 fshd.next = -1;
544 fshd.segListBlock = j+1;
545 if (adfWriteFSHDblock(dev, j, &fshd)!=RC_OK)
546 return RC_ERROR;
547 j++;
548
549 /* LSEG */
550 lseg.next = -1;
551 if (adfWriteLSEGblock(dev, j, &lseg)!=RC_OK)
552 return RC_ERROR;
553
554 return RC_OK;
555 }
556
557
558 /*
559 * adfCreateFlop
560 *
561 * create a filesystem on a floppy device
562 * fills dev->volList[]
563 */
adfCreateFlop(struct Device * dev,char * volName,int volType)564 RETCODE adfCreateFlop(struct Device* dev, char* volName, int volType )
565 {
566 if (dev==NULL) {
567 (*adfEnv.eFct)("adfCreateFlop : dev==NULL");
568 return RC_ERROR;
569 }
570 dev->volList =(struct Volume**) malloc(sizeof(struct Volume*));
571 if (!dev->volList) {
572 (*adfEnv.eFct)("adfCreateFlop : unknown device type");
573 return RC_ERROR;
574 }
575 dev->volList[0] = adfCreateVol( dev, 0L, 80L, volName, volType );
576 if (dev->volList[0]==NULL) {
577 free(dev->volList);
578 return RC_ERROR;
579 }
580 dev->nVol = 1;
581 dev->volList[0]->blockSize = 512;
582 if (dev->sectors==11)
583 dev->devType=DEVTYPE_FLOPDD;
584 else
585 dev->devType=DEVTYPE_FLOPHD;
586
587 return RC_OK;
588 }
589
590
591 /*
592 * adfCreateHd
593 *
594 * create a filesystem one an harddisk device (partitions==volumes, and the header)
595 *
596 * fills dev->volList[]
597 *
598 */
adfCreateHd(struct Device * dev,int n,struct Partition ** partList)599 RETCODE adfCreateHd(struct Device* dev, int n, struct Partition** partList )
600 {
601 int i, j;
602
603 /*struct Volume *vol;*/
604
605 if (dev==NULL || partList==NULL || n<=0) {
606 (*adfEnv.eFct)("adfCreateHd : illegal parameter(s)");
607 return RC_ERROR;
608 }
609
610 dev->volList =(struct Volume**) malloc(sizeof(struct Volume*)*n);
611 if (!dev->volList) {
612 (*adfEnv.eFct)("adfCreateFlop : malloc");
613 return RC_ERROR;
614 }
615 for(i=0; i<n; i++) {
616 dev->volList[i] = adfCreateVol( dev,
617 partList[i]->startCyl,
618 partList[i]->lenCyl,
619 partList[i]->volName,
620 partList[i]->volType );
621 if (dev->volList[i]==NULL) {
622 for(j=0; j<i; j++) {
623 free( dev->volList[i] );
624 /* pas fini */
625 }
626 free(dev->volList);
627 (*adfEnv.eFct)("adfCreateHd : adfCreateVol() fails");
628 }
629 dev->volList[i]->blockSize = 512;
630 }
631 dev->nVol = n;
632 /*
633 vol=dev->volList[0];
634 printf("0first=%ld last=%ld root=%ld\n",vol->firstBlock,
635 vol->lastBlock, vol->rootBlock);
636 */
637
638 if (adfCreateHdHeader(dev, n, partList )!=RC_OK)
639 return RC_ERROR;
640 return RC_OK;
641 }
642
643
644 /*
645 * adfUnMountDev
646 *
647 */
adfUnMountDev(struct Device * dev)648 void adfUnMountDev( struct Device* dev)
649 {
650 int i;
651 struct nativeFunctions *nFct;
652
653 if (dev==0)
654 return;
655
656 for(i=0; i<dev->nVol; i++) {
657 free(dev->volList[i]->volName);
658 free(dev->volList[i]);
659 }
660 if (dev->nVol>0)
661 free(dev->volList);
662 dev->nVol = 0;
663
664 nFct = adfEnv.nativeFct;
665 if (dev->isNativeDev)
666 (*nFct->adfReleaseDevice)(dev);
667 else
668 adfReleaseDumpDevice(dev);
669
670 free(dev);
671 }
672
673
674
675 /*
676 * ReadRDSKblock
677 *
678 */
679 RETCODE
adfReadRDSKblock(struct Device * dev,struct bRDSKblock * blk)680 adfReadRDSKblock( struct Device* dev, struct bRDSKblock* blk )
681 {
682
683 UCHAR buf[256];
684 struct nativeFunctions *nFct;
685 RETCODE rc2;
686 RETCODE rc = RC_OK;
687
688 nFct = adfEnv.nativeFct;
689 if (dev->isNativeDev)
690 rc2 =(*nFct->adfNativeReadSector)(dev, 0, 256, buf);
691 else
692 rc2 = adfReadDumpSector(dev, 0, 256, buf);
693
694 if (rc2!=RC_OK)
695 return(RC_ERROR);
696
697 memcpy(blk, buf, 256);
698 #ifdef LITT_ENDIAN
699 /* big to little = 68000 to x86 */
700 swapEndian((uint8_t*)blk, SWBL_RDSK);
701 #endif
702
703 if ( strncmp(blk->id,"RDSK",4)!=0 ) {
704 (*adfEnv.eFct)("ReadRDSKblock : RDSK id not found");
705 return RC_ERROR;
706 }
707
708 if ( blk->size != 64 )
709 (*adfEnv.wFct)("ReadRDSKBlock : size != 64"); /* BV */
710
711 if ( blk->checksum != adfNormalSum(buf,8,256) ) {
712 (*adfEnv.wFct)("ReadRDSKBlock : incorrect checksum");
713 /* BV FIX: Due to malicious Win98 write to sector
714 rc|=RC_BLOCKSUM;*/
715 }
716
717 if ( blk->blockSize != 512 )
718 (*adfEnv.wFct)("ReadRDSKBlock : blockSize != 512"); /* BV */
719
720 if ( blk->cylBlocks != blk->sectors*blk->heads )
721 (*adfEnv.wFct)( "ReadRDSKBlock : cylBlocks != sectors*heads");
722
723 return rc;
724 }
725
726
727 /*
728 * adfWriteRDSKblock
729 *
730 */
731 RETCODE
adfWriteRDSKblock(struct Device * dev,struct bRDSKblock * rdsk)732 adfWriteRDSKblock(struct Device *dev, struct bRDSKblock* rdsk)
733 {
734 uint8_t buf[LOGICAL_BLOCK_SIZE];
735 uint32_t newSum;
736 struct nativeFunctions *nFct;
737 RETCODE rc2, rc = RC_OK;
738
739 if (dev->readOnly) {
740 (*adfEnv.wFct)("adfWriteRDSKblock : can't write block, read only device");
741 return RC_ERROR;
742 }
743
744 memset(buf,0,LOGICAL_BLOCK_SIZE);
745
746 strncpy(rdsk->id,"RDSK",4);
747 rdsk->size = sizeof(struct bRDSKblock)/sizeof(int32_t);
748 rdsk->blockSize = LOGICAL_BLOCK_SIZE;
749 rdsk->badBlockList = -1;
750
751 strncpy(rdsk->diskVendor,"ADFlib ",8);
752 strncpy(rdsk->diskProduct,"harddisk.adf ",16);
753 strncpy(rdsk->diskRevision,"v1.0",4);
754
755 memcpy(buf, rdsk, sizeof(struct bRDSKblock));
756 #ifdef LITT_ENDIAN
757 swapEndian(buf, SWBL_RDSK);
758 #endif
759
760 newSum = adfNormalSum(buf, 8, LOGICAL_BLOCK_SIZE);
761 swLong(buf+8, newSum);
762
763 nFct = adfEnv.nativeFct;
764 if (dev->isNativeDev)
765 rc2=(*nFct->adfNativeWriteSector)(dev, 0, LOGICAL_BLOCK_SIZE, buf);
766 else
767 rc2=adfWriteDumpSector(dev, 0, LOGICAL_BLOCK_SIZE, buf);
768
769 if (rc2!=RC_OK)
770 return RC_ERROR;
771
772 return rc;
773 }
774
775
776 /*
777 * ReadPARTblock
778 *
779 */
780 RETCODE
adfReadPARTblock(struct Device * dev,int32_t nSect,struct bPARTblock * blk)781 adfReadPARTblock( struct Device* dev, int32_t nSect, struct bPARTblock* blk )
782 {
783 UCHAR buf[ sizeof(struct bPARTblock) ];
784 struct nativeFunctions *nFct;
785 RETCODE rc2, rc = RC_OK;
786
787 nFct = adfEnv.nativeFct;
788 if (dev->isNativeDev)
789 rc2=(*nFct->adfNativeReadSector)(dev, nSect, sizeof(struct bPARTblock), buf);
790 else
791 rc2=adfReadDumpSector(dev, nSect, sizeof(struct bPARTblock), buf);
792
793 if (rc2!=RC_OK)
794 return RC_ERROR;
795
796 memcpy(blk, buf, sizeof(struct bPARTblock));
797 #ifdef LITT_ENDIAN
798 /* big to little = 68000 to x86 */
799 swapEndian((uint8_t*)blk, SWBL_PART);
800 #endif
801
802 if ( strncmp(blk->id,"PART",4)!=0 ) {
803 (*adfEnv.eFct)("ReadPARTblock : PART id not found");
804 return RC_ERROR;
805 }
806
807 if ( blk->size != 64 )
808 (*adfEnv.wFct)("ReadPARTBlock : size != 64");
809
810 if ( blk->blockSize!=128 ) {
811 (*adfEnv.eFct)("ReadPARTblock : blockSize!=512, not supported (yet)");
812 return RC_ERROR;
813 }
814
815 if ( blk->checksum != adfNormalSum(buf,8,256) )
816 (*adfEnv.wFct)( "ReadPARTBlock : incorrect checksum");
817
818 return rc;
819 }
820
821
822 /*
823 * adfWritePARTblock
824 *
825 */
826 RETCODE
adfWritePARTblock(struct Device * dev,int32_t nSect,struct bPARTblock * part)827 adfWritePARTblock(struct Device *dev, int32_t nSect, struct bPARTblock* part)
828 {
829 uint8_t buf[LOGICAL_BLOCK_SIZE];
830 uint32_t newSum;
831 struct nativeFunctions *nFct;
832 RETCODE rc2, rc = RC_OK;
833
834 if (dev->readOnly) {
835 (*adfEnv.wFct)("adfWritePARTblock : can't write block, read only device");
836 return RC_ERROR;
837 }
838
839 memset(buf,0,LOGICAL_BLOCK_SIZE);
840
841 strncpy(part->id,"PART",4);
842 part->size = sizeof(struct bPARTblock)/sizeof(int32_t);
843 part->blockSize = LOGICAL_BLOCK_SIZE;
844 part->vectorSize = 16;
845 part->blockSize = 128;
846 part->sectorsPerBlock = 1;
847 part->dosReserved = 2;
848
849 memcpy(buf, part, sizeof(struct bPARTblock));
850 #ifdef LITT_ENDIAN
851 swapEndian(buf, SWBL_PART);
852 #endif
853
854 newSum = adfNormalSum(buf, 8, LOGICAL_BLOCK_SIZE);
855 swLong(buf+8, newSum);
856 /* *(int32_t*)(buf+8) = swapLong((uint8_t*)&newSum);*/
857
858 nFct = adfEnv.nativeFct;
859 if (dev->isNativeDev)
860 rc2=(*nFct->adfNativeWriteSector)(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
861 else
862 rc2=adfWriteDumpSector(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
863 if (rc2!=RC_OK)
864 return RC_ERROR;
865
866 return rc;
867 }
868
869 /*
870 * ReadFSHDblock
871 *
872 */
873 RETCODE
adfReadFSHDblock(struct Device * dev,int32_t nSect,struct bFSHDblock * blk)874 adfReadFSHDblock( struct Device* dev, int32_t nSect, struct bFSHDblock* blk)
875 {
876 UCHAR buf[sizeof(struct bFSHDblock)];
877 struct nativeFunctions *nFct;
878 RETCODE rc;
879
880 nFct = adfEnv.nativeFct;
881 if (dev->isNativeDev)
882 rc = (*nFct->adfNativeReadSector)(dev, nSect, sizeof(struct bFSHDblock), buf);
883 else
884 rc = adfReadDumpSector(dev, nSect, sizeof(struct bFSHDblock), buf);
885 if (rc!=RC_OK)
886 return RC_ERROR;
887
888 memcpy(blk, buf, sizeof(struct bFSHDblock));
889 #ifdef LITT_ENDIAN
890 /* big to little = 68000 to x86 */
891 swapEndian((uint8_t*)blk, SWBL_FSHD);
892 #endif
893
894 if ( strncmp(blk->id,"FSHD",4)!=0 ) {
895 (*adfEnv.eFct)("ReadFSHDblock : FSHD id not found");
896 return RC_ERROR;
897 }
898
899 if ( blk->size != 64 )
900 (*adfEnv.wFct)("ReadFSHDblock : size != 64");
901
902 if ( blk->checksum != adfNormalSum(buf,8,256) )
903 (*adfEnv.wFct)( "ReadFSHDblock : incorrect checksum");
904
905 return RC_OK;
906 }
907
908
909 /*
910 * adfWriteFSHDblock
911 *
912 */
913 RETCODE
adfWriteFSHDblock(struct Device * dev,int32_t nSect,struct bFSHDblock * fshd)914 adfWriteFSHDblock(struct Device *dev, int32_t nSect, struct bFSHDblock* fshd)
915 {
916 uint8_t buf[LOGICAL_BLOCK_SIZE];
917 uint32_t newSum;
918 struct nativeFunctions *nFct;
919 RETCODE rc = RC_OK;
920
921 if (dev->readOnly) {
922 (*adfEnv.wFct)("adfWriteFSHDblock : can't write block, read only device");
923 return RC_ERROR;
924 }
925
926 memset(buf,0,LOGICAL_BLOCK_SIZE);
927
928 strncpy(fshd->id,"FSHD",4);
929 fshd->size = sizeof(struct bFSHDblock)/sizeof(int32_t);
930
931 memcpy(buf, fshd, sizeof(struct bFSHDblock));
932 #ifdef LITT_ENDIAN
933 swapEndian(buf, SWBL_FSHD);
934 #endif
935
936 newSum = adfNormalSum(buf, 8, LOGICAL_BLOCK_SIZE);
937 swLong(buf+8, newSum);
938 /* *(int32_t*)(buf+8) = swapLong((uint8_t*)&newSum);*/
939
940 nFct = adfEnv.nativeFct;
941 if (dev->isNativeDev)
942 rc=(*nFct->adfNativeWriteSector)(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
943 else
944 rc=adfWriteDumpSector(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
945 if (rc!=RC_OK)
946 return RC_ERROR;
947
948 return RC_OK;
949 }
950
951
952 /*
953 * ReadLSEGblock
954 *
955 */
956 RETCODE
adfReadLSEGblock(struct Device * dev,int32_t nSect,struct bLSEGblock * blk)957 adfReadLSEGblock(struct Device* dev, int32_t nSect, struct bLSEGblock* blk)
958 {
959 UCHAR buf[sizeof(struct bLSEGblock)];
960 struct nativeFunctions *nFct;
961 RETCODE rc;
962
963 nFct = adfEnv.nativeFct;
964 if (dev->isNativeDev)
965 rc=(*nFct->adfNativeReadSector)(dev, nSect, sizeof(struct bLSEGblock), buf);
966 else
967 rc=adfReadDumpSector(dev, nSect, sizeof(struct bLSEGblock), buf);
968 if (rc!=RC_OK)
969 return RC_ERROR;
970
971 memcpy(blk, buf, sizeof(struct bLSEGblock));
972 #ifdef LITT_ENDIAN
973 /* big to little = 68000 to x86 */
974 swapEndian((uint8_t*)blk, SWBL_LSEG);
975 #endif
976
977 if ( strncmp(blk->id,"LSEG",4)!=0 ) {
978 (*adfEnv.eFct)("ReadLSEGblock : LSEG id not found");
979 return RC_ERROR;
980 }
981
982 if ( blk->checksum != adfNormalSum(buf,8,sizeof(struct bLSEGblock)) )
983 (*adfEnv.wFct)("ReadLSEGBlock : incorrect checksum");
984
985 if ( blk->next!=-1 && blk->size != 128 )
986 (*adfEnv.wFct)("ReadLSEGBlock : size != 128");
987
988 return RC_OK;
989 }
990
991
992 /*
993 * adfWriteLSEGblock
994 *
995 */
996 RETCODE
adfWriteLSEGblock(struct Device * dev,int32_t nSect,struct bLSEGblock * lseg)997 adfWriteLSEGblock(struct Device *dev, int32_t nSect, struct bLSEGblock* lseg)
998 {
999 uint8_t buf[LOGICAL_BLOCK_SIZE];
1000 uint32_t newSum;
1001 struct nativeFunctions *nFct;
1002 RETCODE rc;
1003
1004 if (dev->readOnly) {
1005 (*adfEnv.wFct)("adfWriteLSEGblock : can't write block, read only device");
1006 return RC_ERROR;
1007 }
1008
1009 memset(buf,0,LOGICAL_BLOCK_SIZE);
1010
1011 strncpy(lseg->id,"LSEG",4);
1012 lseg->size = sizeof(struct bLSEGblock)/sizeof(int32_t);
1013
1014 memcpy(buf, lseg, sizeof(struct bLSEGblock));
1015 #ifdef LITT_ENDIAN
1016 swapEndian(buf, SWBL_LSEG);
1017 #endif
1018
1019 newSum = adfNormalSum(buf, 8, LOGICAL_BLOCK_SIZE);
1020 swLong(buf+8,newSum);
1021 /* *(int32_t*)(buf+8) = swapLong((uint8_t*)&newSum);*/
1022
1023 nFct = adfEnv.nativeFct;
1024 if (dev->isNativeDev)
1025 rc=(*nFct->adfNativeWriteSector)(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
1026 else
1027 rc=adfWriteDumpSector(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
1028
1029 if (rc!=RC_OK)
1030 return RC_ERROR;
1031
1032 return RC_OK;
1033 }
1034
1035 /*##########################################################################*/
1036