2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
7 #include <proto/exec.h>
8 #include <devices/newstyle.h>
9 #include <utility/tagitem.h>
11 #include "partition_intern.h"
12 #include "partition_support.h"
15 const struct PTFunctionTable
* const PartitionSupport
[] =
18 &PartitionGPT
, /* The order of these two is important, GPT must be checked before MBR */
25 LONG PartitionGetGeometry
27 struct Library
*PartitionBase
,
28 struct IOExtTD
*ioreq
,
29 struct DriveGeometry
*dg
33 ioreq
->iotd_Req
.io_Command
= TD_GETGEOMETRY
;
34 ioreq
->iotd_Req
.io_Data
= dg
;
35 ioreq
->iotd_Req
.io_Length
= sizeof(struct DriveGeometry
);
36 return DoIO((struct IORequest
*)ioreq
);
39 /* query NSD commands */
40 void PartitionNsdCheck
42 struct Library
*PartitionBase
,
43 struct PartitionHandle
*root
46 struct NSDeviceQueryResult nsdq
;
47 struct IOExtTD
*ioreq
= root
->bd
->ioreq
;
54 root
->de
.de_BlocksPerTrack
*
55 ((root
->de
.de_SizeBlock
<<2)/512)
59 nsdq
.DevQueryFormat
=0;
60 ioreq
->iotd_Req
.io_Command
=NSCMD_DEVICEQUERY
;
61 ioreq
->iotd_Req
.io_Data
=&nsdq
;
62 ioreq
->iotd_Req
.io_Length
=sizeof(struct NSDeviceQueryResult
);
63 if (DoIO((struct IORequest
*)ioreq
)==0)
66 (ioreq
->iotd_Req
.io_Actual
<=sizeof(struct NSDeviceQueryResult
)) &&
67 (ioreq
->iotd_Req
.io_Actual
!=0) &&
68 (ioreq
->iotd_Req
.io_Actual
==nsdq
.SizeAvailable
)
71 if (nsdq
.DeviceType
!= NSDEVTYPE_TRACKDISK
)
72 D(bug("partition: NSDcheck: WARNING no trackdisk type\n"));
73 for (cmdcheck
=nsdq
.SupportedCommands
;*cmdcheck
;cmdcheck
++)
75 if (*cmdcheck
== NSCMD_TD_READ64
)
76 root
->bd
->cmdread
= NSCMD_TD_READ64
;
77 if (*cmdcheck
== NSCMD_TD_WRITE64
);
78 root
->bd
->cmdwrite
= NSCMD_TD_WRITE64
;
82 D(bug("partition: NSDcheck: WARNING wrong io_Actual using NSD\n"));
87 /* get real first block of partition ph */
88 ULONG
getStartBlock(struct PartitionHandle
*ph
) {
93 start
+= ph
->de
.de_LowCyl
*ph
->de
.de_BlocksPerTrack
*ph
->de
.de_Surfaces
;
99 /* read a single block within partition ph */
100 LONG
readBlock(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, ULONG block
, void *mem
)
102 return readDataFromBlock(ph
, block
, ph
->de
.de_SizeBlock
<<2, mem
);
105 /* read 'size' bytes starting from 'block' within partition ph */
106 LONG
readDataFromBlock(struct PartitionHandle
*ph
, UQUAD block
, ULONG size
, void *mem
)
108 UQUAD offset
= (getStartBlock(ph
) + block
) * (ph
->de
.de_SizeBlock
<<2);
109 struct IOExtTD
*ioreq
= ph
->bd
->ioreq
;
111 ioreq
->iotd_Req
.io_Command
= ph
->bd
->cmdread
;
112 ioreq
->iotd_Req
.io_Length
= size
;
113 ioreq
->iotd_Req
.io_Data
= mem
;
114 ioreq
->iotd_Req
.io_Offset
= offset
;
115 ioreq
->iotd_Req
.io_Actual
= offset
>> 32;
117 return DoIO((struct IORequest
*)ioreq
);
121 write a single block within partition ph
123 LONG
PartitionWriteBlock(struct Library
*PartitionBase
, struct PartitionHandle
*ph
, ULONG block
, void *mem
)
125 return writeDataFromBlock(ph
, block
, ph
->de
.de_SizeBlock
<< 2, mem
);
128 /* write 'size' bytes starting from 'block' within partition ph */
129 LONG
writeDataFromBlock(struct PartitionHandle
*ph
, UQUAD block
, ULONG size
, void *mem
)
131 UQUAD offset
= (getStartBlock(ph
) + block
) * (ph
->de
.de_SizeBlock
<<2);
132 struct IOExtTD
*ioreq
= ph
->bd
->ioreq
;
134 ioreq
->iotd_Req
.io_Command
= ph
->bd
->cmdwrite
;
135 ioreq
->iotd_Req
.io_Length
= size
;
136 ioreq
->iotd_Req
.io_Data
= mem
;
137 ioreq
->iotd_Req
.io_Offset
= offset
;
138 ioreq
->iotd_Req
.io_Actual
= offset
>>32;
140 return DoIO((struct IORequest
*)ioreq
);
143 LONG
deviceError(LONG err
)
150 case TDERR_WriteProt
:
151 return ERROR_DISK_WRITE_PROTECTED
;
153 case TDERR_SeekError
:
154 return ERROR_SEEK_ERROR
;
157 return ERROR_NOT_A_DOS_DISK
;
162 * Initialize partition handle based on parent's data.
163 * Geometry will be inherited from parent and adjusted if needed
164 * for given start block and length in blocks to fit in.
166 void initPartitionHandle(struct PartitionHandle
*root
, struct PartitionHandle
*ph
, ULONG first_sector
, ULONG count_sector
)
168 ULONG cylsecs
= root
->de
.de_BlocksPerTrack
* root
->de
.de_Surfaces
;
174 /* initialize DosEnvec */
175 CopyMem(&root
->de
, &ph
->de
, sizeof(struct DosEnvec
));
177 /* Check if partition starts and ends on a cylinder boundary */
178 if ((first_sector
% cylsecs
!= 0) || (count_sector
% cylsecs
!= 0))
180 /* Treat each track as a cylinder if possible */
181 ph
->de
.de_Surfaces
= 1;
182 cylsecs
= ph
->de
.de_BlocksPerTrack
;
184 if ((first_sector
% cylsecs
!= 0) || (count_sector
% cylsecs
!= 0))
187 * We can't. We could find the highest common factor of
188 * first_sector and count_sector here, but currently we
189 * simply use one block per cylinder (flat LBA)
191 ph
->de
.de_BlocksPerTrack
= 1;
196 /* initialize DriveGeometry */
197 ph
->dg
.dg_DeviceType
= DG_DIRECT_ACCESS
;
198 ph
->dg
.dg_SectorSize
= ph
->de
.de_SizeBlock
<<2;
199 ph
->dg
.dg_Heads
= ph
->de
.de_Surfaces
;
200 ph
->dg
.dg_TrackSectors
= ph
->de
.de_BlocksPerTrack
;
201 ph
->dg
.dg_Cylinders
= count_sector
/ cylsecs
;
202 ph
->dg
.dg_BufMemType
= ph
->de
.de_BufMemType
;
204 /* Set start/end cylinder in DosEnvec */
205 ph
->de
.de_LowCyl
= first_sector
/ cylsecs
;
206 ph
->de
.de_HighCyl
= ph
->de
.de_LowCyl
+ ph
->dg
.dg_Cylinders
- 1;
208 /* Fix up DosEnvec size if necessary */
209 if (ph
->de
.de_TableSize
< DE_BUFMEMTYPE
)
210 ph
->de
.de_TableSize
= DE_BUFMEMTYPE
;
213 /* Set DOSType and some defaults according to it */
214 void setDosType(struct DosEnvec
*de
, ULONG type
)
216 de
->de_TableSize
= DE_DOSTYPE
;
217 de
->de_SectorPerBlock
= 1;
218 de
->de_DosType
= type
;
220 * These two are actually device-dependent. However there's no way
221 * to obtain them, so just fill in defaults.
223 de
->de_MaxTransfer
= 0x00200000;
224 de
->de_Mask
= 0x7ffffffe;
226 /* Some more filesystem-specific defaults */
231 case ID_INTER_FFS_DISK
:
233 de
->de_TableSize
= DE_BOOTBLOCKS
;
235 de
->de_BootBlocks
= 2;