1 /* IBM device driver utility functions. Author: Kees J. Bot
4 * partition: partition a disk to the partition table(s) on it.
11 /* Extended partition? */
12 #define ext_part(s) ((s) == 0x05 || (s) == 0x0F)
14 FORWARD
_PROTOTYPE( void extpartition
, (struct driver
*dp
, int extdev
,
15 unsigned long extbase
) );
16 FORWARD
_PROTOTYPE( int get_part_table
, (struct driver
*dp
, int device
,
17 unsigned long offset
, struct part_entry
*table
));
18 FORWARD
_PROTOTYPE( void sort
, (struct part_entry
*table
) );
20 #ifndef CD_SECTOR_SIZE
21 #define CD_SECTOR_SIZE 2048
24 /*============================================================================*
26 *============================================================================*/
27 PUBLIC
void partition(dp
, device
, style
, atapi
)
28 struct driver
*dp
; /* device dependent entry points */
29 int device
; /* device to partition */
30 int style
; /* partitioning style: floppy, primary, sub. */
31 int atapi
; /* atapi device */
33 /* This routine is called on first open to initialize the partition tables
34 * of a device. It makes sure that each partition falls safely within the
35 * device's limits. Depending on the partition style we are either making
36 * floppy partitions, primary partitions or subpartitions. Only primary
37 * partitions are sorted, because they are shared with other operating
38 * systems that expect this.
40 struct part_entry table
[NR_PARTITIONS
], *pe
;
43 unsigned long base
, limit
, part_limit
;
45 /* Get the geometry of the device to partition */
46 if ((dv
= (*dp
->dr_prepare
)(device
)) == NIL_DEV
47 || cmp64u(dv
->dv_size
, 0) == 0) return;
48 base
= div64u(dv
->dv_base
, SECTOR_SIZE
);
49 limit
= base
+ div64u(dv
->dv_size
, SECTOR_SIZE
);
51 /* Read the partition table for the device. */
52 if(!get_part_table(dp
, device
, 0L, table
)) {
56 /* Compute the device number of the first partition. */
59 device
+= MINOR_fd0p0
;
62 sort(table
); /* sort a primary partition table */
66 disk
= device
/ DEV_PER_DRIVE
;
67 par
= device
% DEV_PER_DRIVE
- 1;
68 device
= MINOR_d0p0s0
+ (disk
* NR_PARTITIONS
+ par
) * NR_PARTITIONS
;
71 /* Find an array of devices. */
72 if ((dv
= (*dp
->dr_prepare
)(device
)) == NIL_DEV
) return;
74 /* Set the geometry of the partitions from the partition table. */
75 for (par
= 0; par
< NR_PARTITIONS
; par
++, dv
++) {
76 /* Shrink the partition to fit within the device. */
78 part_limit
= pe
->lowsec
+ pe
->size
;
79 if (part_limit
< pe
->lowsec
) part_limit
= limit
;
80 if (part_limit
> limit
) part_limit
= limit
;
81 if (pe
->lowsec
< base
) pe
->lowsec
= base
;
82 if (part_limit
< pe
->lowsec
) part_limit
= pe
->lowsec
;
84 dv
->dv_base
= mul64u(pe
->lowsec
, SECTOR_SIZE
);
85 dv
->dv_size
= mul64u(part_limit
- pe
->lowsec
, SECTOR_SIZE
);
87 if (style
== P_PRIMARY
) {
88 /* Each Minix primary partition can be subpartitioned. */
89 if (pe
->sysind
== MINIX_PART
)
90 partition(dp
, device
+ par
, P_SUB
, atapi
);
92 /* An extended partition has logical partitions. */
93 if (ext_part(pe
->sysind
))
94 extpartition(dp
, device
+ par
, pe
->lowsec
);
99 /*============================================================================*
101 *============================================================================*/
102 PRIVATE
void extpartition(dp
, extdev
, extbase
)
103 struct driver
*dp
; /* device dependent entry points */
104 int extdev
; /* extended partition to scan */
105 unsigned long extbase
; /* sector offset of the base extended partition */
107 /* Extended partitions cannot be ignored alas, because people like to move
108 * files to and from DOS partitions. Avoid reading this code, it's no fun.
110 struct part_entry table
[NR_PARTITIONS
], *pe
;
111 int subdev
, disk
, par
;
113 unsigned long offset
, nextoffset
;
115 disk
= extdev
/ DEV_PER_DRIVE
;
116 par
= extdev
% DEV_PER_DRIVE
- 1;
117 subdev
= MINOR_d0p0s0
+ (disk
* NR_PARTITIONS
+ par
) * NR_PARTITIONS
;
121 if (!get_part_table(dp
, extdev
, offset
, table
)) return;
124 /* The table should contain one logical partition and optionally
125 * another extended partition. (It's a linked list.)
128 for (par
= 0; par
< NR_PARTITIONS
; par
++) {
130 if (ext_part(pe
->sysind
)) {
131 nextoffset
= pe
->lowsec
;
133 if (pe
->sysind
!= NO_PART
) {
134 if ((dv
= (*dp
->dr_prepare
)(subdev
)) == NIL_DEV
) return;
136 dv
->dv_base
= mul64u(extbase
+ offset
+ pe
->lowsec
,
138 dv
->dv_size
= mul64u(pe
->size
, SECTOR_SIZE
);
140 /* Out of devices? */
141 if (++subdev
% NR_PARTITIONS
== 0) return;
144 } while ((offset
= nextoffset
) != 0);
147 /*============================================================================*
149 *============================================================================*/
150 PRIVATE
int get_part_table(dp
, device
, offset
, table
)
153 unsigned long offset
; /* sector offset to the table */
154 struct part_entry
*table
; /* four entries */
156 /* Read the partition table for the device, return true iff there were no
161 static unsigned char partbuf
[CD_SECTOR_SIZE
];
163 position
= mul64u(offset
, SECTOR_SIZE
);
164 iovec1
.iov_addr
= (vir_bytes
) partbuf
;
165 iovec1
.iov_size
= CD_SECTOR_SIZE
;
166 if ((*dp
->dr_prepare
)(device
) != NIL_DEV
) {
167 (void) (*dp
->dr_transfer
)(SELF
, DEV_GATHER_S
, position
, &iovec1
, 1);
169 if (iovec1
.iov_size
!= 0) {
172 if (partbuf
[510] != 0x55 || partbuf
[511] != 0xAA) {
173 /* Invalid partition table. */
176 memcpy(table
, (partbuf
+ PART_TABLE_OFF
), NR_PARTITIONS
* sizeof(table
[0]));
180 /*===========================================================================*
182 *===========================================================================*/
183 PRIVATE
void sort(table
)
184 struct part_entry
*table
;
186 /* Sort a partition table. */
187 struct part_entry
*pe
, tmp
;
188 int n
= NR_PARTITIONS
;
191 for (pe
= table
; pe
< table
+ NR_PARTITIONS
-1; pe
++) {
192 if (pe
[0].sysind
== NO_PART
193 || (pe
[0].lowsec
> pe
[1].lowsec
194 && pe
[1].sysind
!= NO_PART
)) {
195 tmp
= pe
[0]; pe
[0] = pe
[1]; pe
[1] = tmp
;