Indentation fix, cleanup.
[AROS.git] / tools / adflib / adf_hd.c
blob1c5fae72149f920454c8633c41510952c118f7ac
1 /*
2 * ADF Library. (C) 1997-1998 Laurent Clevy
4 * adf_hd.c
6 */
10 #include<stdio.h>
11 #include<stdlib.h>
12 #include<string.h>
14 #include"adf_str.h"
15 #include"hd_blk.h"
16 #include"adf_raw.h"
17 #include"adf_hd.h"
18 #include"adf_util.h"
19 #include"adf_disk.h"
20 #include"adf_nativ.h"
21 #include"adf_dump.h"
22 #include"adf_err.h"
24 #include"defendian.h"
26 extern struct Env adfEnv;
29 * adfDevType
31 * returns the type of a device
32 * only based of the field 'dev->size'
34 int adfDevType(struct Device* dev)
36 if (dev->size==512*11*2*80)
37 return(DEVTYPE_FLOPDD);
38 else if (dev->size==512*22*2*80)
39 return(DEVTYPE_FLOPHD);
40 else if (dev->size>512*22*2*80)
41 return(DEVTYPE_HARDDISK);
42 else {
43 (*adfEnv.eFct)("adfDevType : unknown device type");
44 return(-1);
50 * adfDeviceInfo
52 * display information about the device and its volumes
53 * for demonstration purpose only since the output is stdout !
55 * can be used before adfCreateVol() or adfMount()
57 void adfDeviceInfo(struct Device *dev)
59 int i;
61 printf("Cylinders = %ld\n",(long)dev->cylinders);
62 printf("Heads = %ld\n",(long)dev->heads);
63 printf("Sectors/Cyl = %ld\n\n",(long)dev->sectors);
64 if (!dev->isNativeDev)
65 printf("Dump device\n\n");
66 else
67 printf("Real device\n\n");
68 printf("Volumes = %d\n\n",dev->nVol);
70 switch(dev->devType){
71 case DEVTYPE_FLOPDD:
72 printf("floppy dd\n"); break;
73 case DEVTYPE_FLOPHD:
74 printf("floppy hd\n"); break;
75 case DEVTYPE_HARDDISK:
76 printf("harddisk\n"); break;
77 case DEVTYPE_HARDFILE:
78 printf("hardfile\n"); break;
79 default:
80 printf("unknown devType!\n"); break;
84 for(i=0; i<dev->nVol; i++) {
85 if (dev->volList[i]->volName)
86 printf("%2d : %7ld ->%7ld, \"%s\"", i,
87 (long)dev->volList[i]->firstBlock,
88 (long)dev->volList[i]->firstBlock + dev->volList[i]->totalBlocks - 1,
89 dev->volList[i]->volName);
90 else
91 printf("%2d : %7ld ->%7ld\n", i,
92 (long)dev->volList[i]->firstBlock,
93 (long)dev->volList[i]->firstBlock + dev->volList[i]->totalBlocks - 1);
94 if (dev->volList[i]->mounted)
95 printf(", mounted");
96 putchar('\n');
102 * adfFreeTmpVolList
105 void adfFreeTmpVolList(struct List *root)
107 struct List *cell;
108 struct Volume *vol;
110 cell = root;
111 while(cell!=NULL) {
112 vol = (struct Volume *)cell->content;
113 if (vol->volName!=NULL)
114 free(vol->volName);
115 cell = cell->next;
117 freeList(root);
123 * adfMountHdFile
126 RETCODE adfMountHdFile(struct Device *dev)
128 struct Volume* vol;
129 unsigned char buf[512];
130 ULONG size;
131 BOOL found;
133 dev->devType = DEVTYPE_HARDFILE;
134 dev->nVol = 0;
135 dev->volList = (struct Volume**)malloc(sizeof(struct Volume*));
136 if (!dev->volList) {
137 (*adfEnv.eFct)("adfMountHdFile : malloc");
138 return RC_ERROR;
141 vol=(struct Volume*)malloc(sizeof(struct Volume));
142 if (!vol) {
143 (*adfEnv.eFct)("adfMountHdFile : malloc");
144 return RC_ERROR;
146 dev->volList[0] = vol;
147 dev->nVol++; /* fixed by Dan, ... and by Gary */
149 vol->volName=NULL;
151 dev->cylinders = dev->size/512;
152 dev->heads = 1;
153 dev->sectors = 1;
155 vol->firstBlock = 0;
156 vol->reservedBlocks = 2;
158 size = dev->size + 512-(dev->size%512);
159 //printf("size=%ld\n",size);
160 vol->rootBlock = ((size/512)-1+vol->reservedBlocks)/2;
161 //printf("root=%ld\n",vol->rootBlock);
162 adfReadDumpSector(dev, 0, 512, buf);
163 vol->rootBlock = swapLong(buf+8);
165 adfReadDumpSector(dev, vol->rootBlock, 512, buf);
166 found = swapLong(buf)==T_HEADER && swapLong(buf+508)==ST_ROOT;
167 if (!found) {
168 (*adfEnv.eFct)("adfMountHdFile : rootblock not found");
169 return RC_ERROR;
171 vol->totalBlocks = vol->rootBlock*2;
173 return RC_OK;
178 * adfMountHd
180 * normal not used directly : called by adfMount()
182 * fills geometry fields and volumes list (dev->nVol and dev->volList[])
184 RETCODE adfMountHd(struct Device *dev)
186 struct bRDSKblock rdsk;
187 struct bPARTblock part;
188 struct bFSHDblock fshd;
189 struct bLSEGblock lseg;
190 ULONG next;
191 struct List *vList, *listRoot;
192 int i;
193 struct Volume* vol;
194 int len;
196 if (adfReadRDSKblock( dev, &rdsk )!=RC_OK)
197 return RC_ERROR;
199 dev->cylinders = rdsk.cylinders;
200 dev->heads = rdsk.heads;
201 dev->sectors = rdsk.sectors;
203 /* PART blocks */
204 listRoot = NULL;
205 next = rdsk.partitionList;
206 dev->nVol=0;
207 vList = NULL;
208 while( next!=-1 ) {
209 if (adfReadPARTblock( dev, next, &part )!=RC_OK) {
210 adfFreeTmpVolList(listRoot);
211 (*adfEnv.eFct)("adfMountHd : malloc");
212 return RC_ERROR;
215 vol=(struct Volume*)malloc(sizeof(struct Volume));
216 if (!vol) {
217 adfFreeTmpVolList(listRoot);
218 (*adfEnv.eFct)("adfMountHd : malloc");
219 return RC_ERROR;
221 vol->volName=NULL;
222 dev->nVol++;
224 vol->firstBlock = rdsk.cylBlocks * part.lowCyl;
225 vol->totalBlocks = (part.highCyl - part.lowCyl + 1)*rdsk.cylBlocks;
226 vol->reservedBlocks = part.dosReserved;
227 vol->rootBlock = (vol->totalBlocks-1 + vol->reservedBlocks)/2;
228 vol->blockSize = part.blockSize*4;
230 len = min(31, part.nameLen);
231 vol->volName = (char*)malloc(len+1);
232 if (!vol->volName) {
233 adfFreeTmpVolList(listRoot);
234 (*adfEnv.eFct)("adfMount : malloc");
235 return RC_ERROR;
237 memcpy(vol->volName,part.name,len);
238 vol->volName[len] = '\0';
240 vol->mounted = FALSE;
242 /* stores temporaly the volumes in a linked list */
243 if (listRoot==NULL)
244 vList = listRoot = newCell(NULL, (void*)vol);
245 else
246 vList = newCell(vList, (void*)vol);
248 if (vList==NULL) {
249 adfFreeTmpVolList(listRoot);
250 (*adfEnv.eFct)("adfMount : newCell() malloc");
251 return RC_ERROR;
254 next = part.next;
257 /* stores the list in an array */
258 dev->volList = (struct Volume**)malloc(sizeof(struct Volume*) * dev->nVol);
259 if (!dev->volList) {
260 adfFreeTmpVolList(listRoot);
261 (*adfEnv.eFct)("adfMount : unknown device type");
262 return RC_ERROR;
264 vList = listRoot;
265 for(i=0; i<dev->nVol; i++) {
266 dev->volList[i]=(struct Volume*)vList->content;
267 vList = vList->next;
269 freeList(listRoot);
271 fshd.segListBlock = -1;
272 next = rdsk.fileSysHdrList;
273 while( next!=-1 ) {
274 if (adfReadFSHDblock( dev, next, &fshd )!=RC_OK) {
275 for(i=0;i<dev->nVol;i++) free(dev->volList[i]);
276 free(dev->volList);
277 (*adfEnv.eFct)("adfMount : adfReadFSHDblock");
278 return RC_ERROR;
280 next = fshd.next;
283 next = fshd.segListBlock;
284 while( next!=-1 ) {
285 if (adfReadLSEGblock( dev, next, &lseg )!=RC_OK) {
286 (*adfEnv.wFct)("adfMount : adfReadLSEGblock");
288 next = lseg.next;
291 return RC_OK;
296 * adfMountFlop
298 * normaly not used directly, called directly by adfMount()
300 * use dev->devType to choose between DD and HD
301 * fills geometry and the volume list with one volume
303 RETCODE adfMountFlop(struct Device* dev)
305 struct Volume *vol;
306 struct bRootBlock root;
307 char diskName[35];
309 dev->cylinders = 80;
310 dev->heads = 2;
311 if (dev->devType==DEVTYPE_FLOPDD)
312 dev->sectors = 11;
313 else
314 dev->sectors = 22;
316 vol=(struct Volume*)malloc(sizeof(struct Volume));
317 if (!vol) {
318 (*adfEnv.eFct)("adfMount : malloc");
319 return RC_ERROR;
322 vol->mounted = TRUE;
323 vol->firstBlock = 0;
324 vol->totalBlocks =(dev->cylinders * dev->heads * dev->sectors);
325 vol->reservedBlocks = 2;
326 vol->rootBlock = (vol->totalBlocks-1 + vol->reservedBlocks)/2;
327 vol->blockSize = 512;
328 vol->dev = dev;
330 if (adfReadRootBlock(vol, vol->rootBlock, &root)!=RC_OK)
331 return RC_ERROR;
332 memset(diskName, 0, 35);
333 memcpy(diskName, root.diskName, root.nameLen);
335 vol->volName = strdup(diskName);
337 dev->volList =(struct Volume**) malloc(sizeof(struct Volume*));
338 if (!dev->volList) {
339 free(vol);
340 (*adfEnv.eFct)("adfMount : malloc");
341 return RC_ERROR;
343 dev->volList[0] = vol;
344 dev->nVol = 1;
346 /*printf("root=%d\n",vol->rootBlock); */
347 return RC_OK;
352 * adfMountDev
354 * mount a dump file (.adf) or a real device (uses adf_nativ.c and .h)
356 * adfInitDevice() must fill dev->size !
358 struct Device* adfMountDev( char* filename, BOOL ro)
360 struct Device* dev;
361 struct nativeFunctions *nFct;
362 RETCODE rc;
363 UBYTE buf[512];
365 dev = (struct Device*)malloc(sizeof(struct Device));
366 if (!dev) {
367 (*adfEnv.eFct)("adfMountDev : malloc error");
368 return NULL;
371 dev->readOnly = ro;
373 /* switch between dump files and real devices */
374 nFct = adfEnv.nativeFct;
375 dev->isNativeDev = (*nFct->adfIsDevNative)(filename);
376 if (dev->isNativeDev)
377 rc = (*nFct->adfInitDevice)(dev, filename,ro);
378 else
379 rc = adfInitDumpDevice(dev,filename,ro);
380 if (rc!=RC_OK) {
381 free(dev); return(NULL);
384 dev->devType = adfDevType(dev);
386 switch( dev->devType ) {
388 case DEVTYPE_FLOPDD:
389 case DEVTYPE_FLOPHD:
390 if (adfMountFlop(dev)!=RC_OK) {
391 free(dev); return NULL;
393 break;
395 case DEVTYPE_HARDDISK:
396 /* to choose between hardfile or harddisk (real or dump) */
397 if (adfReadDumpSector(dev, 0, 512, buf)!=RC_OK) {
398 (*adfEnv.eFct)("adfMountDev : adfReadDumpSector failed");
399 free(dev); return NULL;
402 /* a file with the first three bytes equal to 'DOS' */
403 if (!dev->isNativeDev && strncmp("DOS",(char *)buf,3)==0) {
404 if (adfMountHdFile(dev)!=RC_OK) {
405 free(dev); return NULL;
408 else if (adfMountHd(dev)!=RC_OK) {
409 /* Just return the device */
410 return dev;
412 break;
414 default:
415 (*adfEnv.eFct)("adfMountDev : unknown device type");
418 return dev;
423 * adfCreateHdHeader
425 * create PARTIALLY the sectors of the header of one harddisk : can not be mounted
426 * back on a real Amiga ! It's because some device dependant values can't be guessed...
428 * do not use dev->volList[], but partList for partitions information : start and len are cylinders,
429 * not blocks
430 * do not fill dev->volList[]
431 * called by adfCreateHd()
433 RETCODE adfCreateHdHeader(struct Device* dev, int n, struct Partition** partList )
435 int i;
436 struct bRDSKblock rdsk;
437 struct bPARTblock part;
438 SECTNUM j;
439 int len;
441 /* RDSK */
443 memset((unsigned char*)&rdsk,0,sizeof(struct bRDSKblock));
444 memset((unsigned char*)&part,0,sizeof(struct bPARTblock));
446 rdsk.rdbBlockLo = 0;
447 rdsk.rdbBlockHi = (dev->sectors*dev->heads*2)-1;
448 rdsk.loCylinder = 2;
449 rdsk.hiCylinder = dev->cylinders-1;
450 rdsk.cylBlocks = dev->sectors*dev->heads;
452 rdsk.cylinders = dev->cylinders;
453 rdsk.sectors = dev->sectors;
454 rdsk.heads = dev->heads;
456 rdsk.badBlockList = -1;
457 rdsk.partitionList = 1;
458 rdsk.fileSysHdrList = -1;
459 rdsk.driveInit = -1;
460 rdsk.bootBlockList = -1;
461 for ( i = 0; i < 5; i++)
462 rdsk.r1[i] = -1;
464 /* Clear all sectors in the header */
465 for (i = rdsk.rdbBlockLo; i <= rdsk.rdbBlockHi; i++)
466 adfWriteBlockDev(dev, i, sizeof(part), (unsigned char *)&part);
468 if (adfWriteRDSKblock(dev, &rdsk)!=RC_OK)
469 return RC_ERROR;
471 /* PART */
473 j=1;
474 for(i=0; i<dev->nVol; i++) {
475 ULONG reserved;
477 memset(&part, 0, sizeof(struct bPARTblock));
479 if (i<dev->nVol-1)
480 part.next = j+1;
481 else
482 part.next = -1;
484 len = min(MAXNAMELEN,strlen(partList[i]->volName));
485 part.nameLen = len;
486 strncpy(part.name, partList[i]->volName, len);
488 if (partList[i]->reserved >= 1)
489 reserved = partList[i]->reserved;
490 else
491 reserved = 2;
493 part.surfaces = dev->heads;
494 part.blocksPerTrack = dev->sectors;
495 part.lowCyl = partList[i]->startCyl;
496 part.highCyl = partList[i]->startCyl + partList[i]->lenCyl -1;
497 part.maxTransfer = 0x00ffffff;
498 part.mask = 0xfffffffe;
499 part.dosReserved = reserved;
500 part.numBuffer = 100;
501 part.vectorSize = 16;
502 part.blockSize = 128;
503 part.sectorsPerBlock = 1;
504 part.bootBlocks = (reserved < 2) ? reserved : 2;
505 part.flags = (partList[i]->bootable ? 1 : 0) |
506 (partList[i]->nomount ? 2 : 0);
508 memcpy(part.dosType, partList[i]->volType, 4);
510 if (adfWritePARTblock(dev, j, &part))
511 return RC_ERROR;
512 j++;
515 return RC_OK;
520 * adfCreateFlop
522 * create a filesystem on a floppy device
523 * fills dev->volList[]
525 RETCODE adfCreateFlop(struct Device* dev, char* volName, int volType )
527 if (dev==NULL) {
528 (*adfEnv.eFct)("adfCreateFlop : dev==NULL");
529 return RC_ERROR;
531 dev->volList =(struct Volume**) malloc(sizeof(struct Volume*));
532 if (!dev->volList) {
533 (*adfEnv.eFct)("adfCreateFlop : unknown device type");
534 return RC_ERROR;
536 dev->volList[0] = adfCreateVol( dev, 0L, 80L, 2, volName, volType );
537 if (dev->volList[0]==NULL) {
538 free(dev->volList);
539 return RC_ERROR;
541 dev->nVol = 1;
542 dev->volList[0]->blockSize = 512;
543 if (dev->sectors==11)
544 dev->devType=DEVTYPE_FLOPDD;
545 else
546 dev->devType=DEVTYPE_FLOPHD;
548 return RC_OK;
553 * adfCreateHd
555 * create a filesystem one an harddisk device (partitions==volumes, and the header)
557 * fills dev->volList[]
560 RETCODE adfCreateHd(struct Device* dev, int n, struct Partition** partList )
562 int i, j;
564 //struct Volume *vol;
566 if (dev==NULL || partList==NULL || n<=0) {
567 (*adfEnv.eFct)("adfCreateHd : illegal parameter(s)");
568 return RC_ERROR;
571 dev->volList =(struct Volume**) malloc(sizeof(struct Volume*)*n);
572 if (!dev->volList) {
573 (*adfEnv.eFct)("adfCreateFlop : malloc");
574 return RC_ERROR;
576 for(i=0; i<n; i++) {
577 if (memcmp(partList[i]->volType, "DOS", 3) != 0) {
578 (*adfEnv.eFct)("adfCreateHd : Skipping non-DOS volume\n");
579 continue;
581 dev->volList[i] = adfCreateVol( dev,
582 partList[i]->startCyl,
583 partList[i]->lenCyl,
584 partList[i]->reserved,
585 partList[i]->volName,
586 partList[i]->volType[3] );
587 if (dev->volList[i]==NULL) {
588 for(j=0; j<i; j++) {
589 free( dev->volList[i] );
590 /* pas fini */
592 free(dev->volList);
593 (*adfEnv.eFct)("adfCreateHd : adfCreateVol() fails");
595 dev->volList[i]->blockSize = 512;
597 dev->nVol = n;
599 if (adfCreateHdHeader(dev, n, partList )!=RC_OK)
600 return RC_ERROR;
601 return RC_OK;
606 * adfUnMountDev
609 void adfUnMountDev( struct Device* dev)
611 int i;
612 struct nativeFunctions *nFct;
614 if (dev==0)
615 return;
617 for(i=0; i<dev->nVol; i++) {
618 free(dev->volList[i]->volName);
619 free(dev->volList[i]);
621 if (dev->nVol>0)
622 free(dev->volList);
623 dev->nVol = 0;
625 nFct = adfEnv.nativeFct;
626 if (dev->isNativeDev)
627 (*nFct->adfReleaseDevice)(dev);
628 else
629 adfReleaseDumpDevice(dev);
631 free(dev);
635 * adfReadBlockDev
637 RETCODE adfReadBlockDev( struct Device* dev, ULONG nSect, ULONG size, unsigned char* buf )
639 struct nativeFunctions *nFct;
640 RETCODE rc;
642 nFct = adfEnv.nativeFct;
643 if (dev->isNativeDev)
644 rc = (*nFct->adfNativeReadSector)(dev, nSect, size, buf);
645 else
646 rc = adfReadDumpSector(dev, nSect, size, buf);
648 if (rc != RC_OK)
649 return rc;
651 if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
652 rc |= RC_BLOCKTYPE;
654 if ( Long(buf + 8) == 0)
655 rc |= RC_BLOCKSTYPE;
657 if ( Long(buf + 8) != adfNormalSum(buf,8,Long(buf + 4) * 4) )
658 rc |= RC_BLOCKSUM;
660 return rc;
664 * adfWriteBlockDev
666 RETCODE adfWriteBlockDev( struct Device* dev, ULONG nSect, ULONG size, unsigned char* buf )
668 struct nativeFunctions *nFct;
669 ULONG sum;
671 memset(buf+8, 0, 4);
672 sum = adfNormalSum(buf, 8, Long(buf + 4) * 4);
673 swLong(buf+8, sum);
675 nFct = adfEnv.nativeFct;
676 if (dev->isNativeDev)
677 return (*nFct->adfNativeWriteSector)(dev, nSect, size, buf);
678 else
679 return adfWriteDumpSector(dev, nSect, size, buf);
683 * ReadRDSKblock
686 RETCODE
687 adfReadRDSKblock( struct Device* dev, struct bRDSKblock* blk )
690 UCHAR buf[256];
691 RETCODE rc2;
692 RETCODE rc = RC_OK;
694 rc2 = adfReadBlockDev(dev, 0, 256, buf);
695 if (rc2!=RC_OK)
696 return(RC_ERROR);
698 memcpy(blk, buf, 256);
699 #ifdef LITT_ENDIAN
700 /* big to little = 68000 to x86 */
701 swapEndian((unsigned char*)blk, SWBL_RDSK);
702 #endif
704 if ( strncmp(blk->id,"RDSK",4)!=0 ) {
705 (*adfEnv.eFct)("ReadRDSKblock : RDSK id not found");
706 return RC_ERROR;
709 if ( blk->size != 64 )
710 (*adfEnv.wFct)("ReadRDSKBlock : size != 64\n");
712 if ( blk->blockSize != 512 )
713 (*adfEnv.wFct)("ReadRDSKBlock : blockSize != 512\n");
715 if ( blk->cylBlocks != blk->sectors*blk->heads )
716 (*adfEnv.wFct)( "ReadRDSKBlock : cylBlocks != sectors*heads");
718 return rc;
723 * adfWriteRDSKblock
726 RETCODE
727 adfWriteRDSKblock(struct Device *dev, struct bRDSKblock* rdsk)
729 unsigned char buf[LOGICAL_BLOCK_SIZE];
731 if (dev->readOnly) {
732 (*adfEnv.wFct)("adfWriteRDSKblock : can't write block, read only device");
733 return RC_ERROR;
736 memset(buf,0,LOGICAL_BLOCK_SIZE);
738 strncpy(rdsk->id,"RDSK",4);
739 rdsk->size = sizeof(struct bRDSKblock)/sizeof(ULONG);
740 rdsk->blockSize = LOGICAL_BLOCK_SIZE;
741 rdsk->badBlockList = -1;
743 strncpy(rdsk->diskVendor,"ADFlib ",8);
744 strncpy(rdsk->diskProduct,"harddisk.adf ",16);
745 strncpy(rdsk->diskRevision,"v1.0",4);
747 memcpy(buf, rdsk, sizeof(struct bRDSKblock));
748 #ifdef LITT_ENDIAN
749 swapEndian(buf, SWBL_RDSK);
750 #endif
752 return adfWriteBlockDev(dev, 0, LOGICAL_BLOCK_SIZE, buf);
757 * ReadPARTblock
760 RETCODE
761 adfReadPARTblock( struct Device* dev, ULONG nSect, struct bPARTblock* blk )
763 UCHAR buf[ sizeof(struct bPARTblock) ];
764 RETCODE rc2, rc = RC_OK;
766 rc2 = adfReadBlockDev(dev, nSect, sizeof(struct bPARTblock), buf);
767 if (rc2!=RC_OK)
768 return RC_ERROR;
770 memcpy(blk, buf, sizeof(struct bPARTblock));
771 #ifdef LITT_ENDIAN
772 /* big to little = 68000 to x86 */
773 swapEndian((unsigned char*)blk, SWBL_PART);
774 #endif
776 if ( strncmp(blk->id,"PART",4)!=0 ) {
777 (*adfEnv.eFct)("ReadPARTblock : PART id not found");
778 return RC_ERROR;
781 if ( blk->size != 64 )
782 (*adfEnv.wFct)("ReadPARTBlock : size != 64");
784 if ( blk->blockSize!=128 ) {
785 (*adfEnv.eFct)("ReadPARTblock : blockSize!=512, not supported (yet)");
786 return RC_ERROR;
789 return rc;
794 * adfWritePARTblock
797 RETCODE
798 adfWritePARTblock(struct Device *dev, ULONG nSect, struct bPARTblock* part)
800 unsigned char buf[LOGICAL_BLOCK_SIZE];
802 if (dev->readOnly) {
803 (*adfEnv.wFct)("adfWritePARTblock : can't write block, read only device");
804 return RC_ERROR;
807 memset(buf,0,LOGICAL_BLOCK_SIZE);
809 strncpy(part->id,"PART",4);
810 part->size = sizeof(struct bPARTblock)/sizeof(ULONG);
811 part->blockSize = LOGICAL_BLOCK_SIZE;
812 part->vectorSize = 16;
813 part->blockSize = 128;
814 part->sectorsPerBlock = 1;
815 part->dosReserved = 2;
817 memcpy(buf, part, sizeof(struct bPARTblock));
818 #ifdef LITT_ENDIAN
819 swapEndian(buf, SWBL_PART);
820 #endif
822 return adfWriteBlockDev(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
826 * ReadFSHDblock
829 RETCODE
830 adfReadFSHDblock( struct Device* dev, ULONG nSect, struct bFSHDblock* blk)
832 UCHAR buf[sizeof(struct bFSHDblock)];
833 RETCODE rc;
835 rc = adfReadBlockDev(dev, nSect, sizeof(struct bFSHDblock), buf);
836 if (rc!=RC_OK)
837 return RC_ERROR;
839 memcpy(blk, buf, sizeof(struct bFSHDblock));
840 #ifdef LITT_ENDIAN
841 /* big to little = 68000 to x86 */
842 swapEndian((unsigned char*)blk, SWBL_FSHD);
843 #endif
845 if ( strncmp(blk->id,"FSHD",4)!=0 ) {
846 (*adfEnv.eFct)("ReadFSHDblock : FSHD id not found");
847 return RC_ERROR;
850 if ( blk->size != 64 )
851 (*adfEnv.wFct)("ReadFSHDblock : size != 64");
853 return RC_OK;
858 * adfWriteFSHDblock
861 RETCODE
862 adfWriteFSHDblock(struct Device *dev, ULONG nSect, struct bFSHDblock* fshd)
864 unsigned char buf[LOGICAL_BLOCK_SIZE];
866 if (dev->readOnly) {
867 (*adfEnv.wFct)("adfWriteFSHDblock : can't write block, read only device");
868 return RC_ERROR;
871 memset(buf,0,LOGICAL_BLOCK_SIZE);
873 strncpy(fshd->id,"FSHD",4);
874 fshd->size = sizeof(struct bFSHDblock)/sizeof(ULONG);
876 memcpy(buf, fshd, sizeof(struct bFSHDblock));
877 #ifdef LITT_ENDIAN
878 swapEndian(buf, SWBL_FSHD);
879 #endif
881 return adfWriteBlockDev(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
886 * ReadLSEGblock
889 RETCODE
890 adfReadLSEGblock(struct Device* dev, ULONG nSect, struct bLSEGblock* blk)
892 UCHAR buf[sizeof(struct bLSEGblock)];
893 RETCODE rc;
895 rc = adfReadBlockDev(dev, nSect, sizeof(struct bLSEGblock), buf);
896 if (rc!=RC_OK)
897 return RC_ERROR;
899 memcpy(blk, buf, sizeof(struct bLSEGblock));
900 #ifdef LITT_ENDIAN
901 /* big to little = 68000 to x86 */
902 swapEndian((unsigned char*)blk, SWBL_LSEG);
903 #endif
905 if ( strncmp(blk->id,"LSEG",4)!=0 ) {
906 (*adfEnv.eFct)("ReadLSEGblock : LSEG id not found");
907 return RC_ERROR;
910 if ( blk->next!=-1 && blk->size != 128 )
911 (*adfEnv.wFct)("ReadLSEGBlock : size != 128");
913 return RC_OK;
918 * adfWriteLSEGblock
921 RETCODE
922 adfWriteLSEGblock(struct Device *dev, ULONG nSect, struct bLSEGblock* lseg)
924 unsigned char buf[LOGICAL_BLOCK_SIZE];
926 if (dev->readOnly) {
927 (*adfEnv.wFct)("adfWriteLSEGblock : can't write block, read only device");
928 return RC_ERROR;
931 memset(buf,0,LOGICAL_BLOCK_SIZE);
933 strncpy(lseg->id,"LSEG",4);
934 lseg->size = sizeof(struct bLSEGblock)/sizeof(ULONG);
936 memcpy(buf, lseg, sizeof(struct bLSEGblock));
937 #ifdef LITT_ENDIAN
938 swapEndian(buf, SWBL_LSEG);
939 #endif
941 return adfWriteBlockDev(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
945 * ReadBOOTblock
948 RETCODE
949 adfReadBOOTblock(struct Device* dev, ULONG nSect, struct bBOOTblock* blk)
951 UCHAR buf[sizeof(struct bBOOTblock)];
952 RETCODE rc;
954 rc = adfReadBlockDev(dev, nSect, sizeof(struct bBOOTblock), buf);
955 if (rc!=RC_OK)
956 return RC_ERROR;
958 memcpy(blk, buf, sizeof(struct bBOOTblock));
959 #ifdef LITT_ENDIAN
960 /* big to little = 68000 to x86 */
961 swapEndian((unsigned char*)blk, SWBL_BOOT);
962 #endif
964 if ( strncmp(blk->id,"BOOT",4)!=0 ) {
965 (*adfEnv.eFct)("ReadBOOTblock : BOOT id not found");
966 return RC_ERROR;
969 if ( blk->next!=-1 && blk->size != 128 )
970 (*adfEnv.wFct)("ReadBOOTBlock : size != 128");
972 return RC_OK;
977 * adfWriteBOOTblock
980 RETCODE
981 adfWriteBOOTblock(struct Device *dev, ULONG nSect, struct bBOOTblock* lseg)
983 unsigned char buf[LOGICAL_BLOCK_SIZE];
985 if (dev->readOnly) {
986 (*adfEnv.wFct)("adfWriteBOOTblock : can't write block, read only device");
987 return RC_ERROR;
990 memset(buf,0,LOGICAL_BLOCK_SIZE);
992 strncpy(lseg->id,"BOOT",4);
993 lseg->size = sizeof(struct bBOOTblock)/sizeof(ULONG);
995 memcpy(buf, lseg, sizeof(struct bBOOTblock));
996 #ifdef LITT_ENDIAN
997 swapEndian(buf, SWBL_BOOT);
998 #endif
1000 return adfWriteBlockDev(dev, nSect, LOGICAL_BLOCK_SIZE, buf);
1003 /* Write BOOT code
1005 RETCODE adfWriteBOOT(struct Device *dev, const UBYTE *code, size_t size)
1007 struct bRDSKblock rdsk;
1008 struct bBOOTblock boot;
1009 UBYTE buf[LOGICAL_BLOCK_SIZE];
1010 ULONG *sector, *next_block;
1011 int i, sectors, n;
1012 RETCODE rc;
1014 if (size & 3) {
1015 printf("adfWriteBOOT: Size must be a multiple of 4\n");
1016 return RC_ERROR;
1019 rc = adfReadRDSKblock(dev, &rdsk);
1020 if (rc != RC_OK)
1021 return rc;
1023 /* Sector map of sectors we can use for boot code */
1024 sectors = (size + sizeof(boot.loadData) - 1) / sizeof(boot.loadData);
1025 sector = alloca((rdsk.rdbBlockHi - rdsk.rdbBlockLo + 1) * sizeof(sector[0]));
1027 /* Do we have space for the new boot code? */
1028 next_block = &rdsk.bootBlockList;
1029 for (n = 0, i = rdsk.rdbBlockLo; i <= rdsk.rdbBlockHi; i++) {
1030 sector[i - rdsk.rdbBlockLo] = (ULONG)-1;
1031 rc = adfReadBlockDev(dev, i, sizeof(buf), buf);
1032 if (rc == RC_OK) {
1033 if (memcmp(buf, "BOOT", 4) != 0)
1034 continue;
1035 } else if (rc & RC_BLOCKREAD) {
1036 /* Skip unreadable blocks */
1037 continue;
1039 if (n < sectors) {
1040 *next_block = i;
1041 next_block = &sector[i - rdsk.rdbBlockLo];
1042 n++;
1043 } else
1044 sector[i - rdsk.rdbBlockLo] = (ULONG)-2; /* Erase sector */
1046 *next_block = (ULONG)-1;
1048 if (n < sectors) {
1049 printf("Needed %d sectors for the BOOT code, only found %d\n", sectors, n);
1050 return RC_ERROR;
1053 /* Clear out unused sectors */
1054 memset(buf, 0, 512);
1055 for (i = rdsk.rdbBlockLo; i <= rdsk.rdbBlockHi; i++) {
1056 if (sector[i - rdsk.rdbBlockLo] == (ULONG)-2)
1057 adfWriteBlockDev(dev, i, sizeof(buf), buf);
1060 /* Write the new boot code */
1061 n = rdsk.bootBlockList;
1062 while (size > 0) {
1063 int longs = (size > sizeof(boot.loadData)) ? sizeof(boot.loadData) : size;
1064 longs = (longs + 3) / 4;
1065 boot.size = longs + 5;
1066 boot.hostID = 7; /* Default */
1067 boot.next = sector[n - rdsk.rdbBlockLo];
1068 memset(boot.loadData, 0xff, sizeof(boot.loadData));
1069 for (i = 0; i < longs; i++) {
1070 boot.loadData[i] = *(ULONG *)code;
1071 code += 4;
1072 size -= 4;
1075 adfWriteBOOTblock(dev, n, &boot);
1077 n = sector[n - rdsk.rdbBlockLo];
1080 return adfWriteRDSKblock(dev, &rdsk);
1083 /*##########################################################################*/