Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / libs / partition / partitionebr.c
blob63a17b5f2b5adfbeea005da1120200db44c44c5e
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 */
7 #include <proto/exec.h>
8 #include <proto/partition.h>
10 #include <exec/memory.h>
11 #include <exec/types.h>
12 #include <libraries/partition.h>
14 #include "partition_support.h"
15 #include "partitionmbr.h"
16 #include "platform.h"
18 #ifndef DEBUG
19 #define DEBUG 0
20 #endif
21 #include "debug.h"
23 struct EBRData {
24 UBYTE type;
25 ULONG ebr_block_no;
28 static LONG PartitionEBRCheckPartitionTable
30 struct Library *PartitionBase,
31 struct PartitionHandle *root
34 union {
35 struct MBR mbr;
36 UBYTE space[root->de.de_SizeBlock << 2];
37 } sector;
39 struct PartitionType type;
40 struct TagItem tags[] = {{PT_TYPE, (IPTR)&type}, {TAG_DONE, 0}};
42 if (readBlock(PartitionBase, root, 0, &sector.mbr) == 0)
44 if (AROS_LE2WORD(sector.mbr.magic) == 0xAA55)
46 if (root->root != NULL)
48 GetPartitionAttrs(root, tags);
49 if (
50 (root->root->table->type == PHPTT_MBR) &&
51 (type.id[0] == MBRT_EXTENDED
52 || type.id[0] == MBRT_EXTENDED2)
55 return 1;
60 return 0;
63 static struct PartitionHandle *PartitionEBRNewHandle
65 struct Library *PartitionBase,
66 struct PartitionHandle *root,
67 UBYTE type,
68 ULONG block_no,
69 ULONG block_count,
70 ULONG ebr_block_no
73 struct PartitionHandle *ph;
74 ULONG cylsecs;
77 ph = AllocMem(sizeof(struct PartitionHandle), MEMF_PUBLIC | MEMF_CLEAR);
78 if (ph != NULL)
80 struct EBRData *data;
82 data = AllocMem(sizeof(struct EBRData), MEMF_PUBLIC);
83 if (data != NULL)
85 cylsecs = root->de.de_BlocksPerTrack*root->de.de_Surfaces;
86 data->type = type;
87 data->ebr_block_no = ebr_block_no;
88 ph->root = root;
89 ph->bd = root->bd;
90 ph->data = data;
92 /* Initialize DosEnvec */
94 /* Check if partition starts and ends on a cylinder boundary */
95 CopyMem(&root->de, &ph->de, sizeof(struct DosEnvec));
96 if (
97 block_no % cylsecs != 0 ||
98 block_count % cylsecs != 0
101 /* It doesn't. We could find the highest common factor of
102 first_sector and count_sector here, but currently we
103 simply use one block per cylinder */
104 ph->de.de_Surfaces = 1;
105 ph->de.de_BlocksPerTrack = 1;
106 cylsecs = ph->de.de_BlocksPerTrack*ph->de.de_Surfaces;
108 ph->de.de_LowCyl = block_no / cylsecs;
109 ph->de.de_HighCyl = ph->de.de_LowCyl + block_count/cylsecs - 1;
110 ph->de.de_TableSize = 10; // only until de_HighCyl
112 /* Initialize DriveGeometry */
113 ph->dg.dg_DeviceType = DG_DIRECT_ACCESS;
114 ph->dg.dg_SectorSize = ph->de.de_SizeBlock<<2;
115 ph->dg.dg_Heads = ph->de.de_Surfaces;
116 ph->dg.dg_TrackSectors = ph->de.de_BlocksPerTrack;
117 ph->dg.dg_Cylinders = ph->de.de_HighCyl - ph->de.de_LowCyl + 1;
118 ph->dg.dg_BufMemType = ph->de.de_BufMemType;
119 return ph;
121 FreeMem(ph, sizeof(struct PartitionHandle));
124 return NULL;
127 static LONG PartitionEBROpenPartitionTable
129 struct Library *PartitionBase,
130 struct PartitionHandle *root
133 LONG error = 0;
134 struct PartitionHandle *ph;
135 struct MBR *ebr;
136 UBYTE i;
137 ULONG block_no = 0;
138 BOOL atEnd = FALSE;
140 ebr = AllocMem(root->de.de_SizeBlock<<2, MEMF_PUBLIC);
141 if (ebr != NULL)
143 NEWLIST(&root->table->list);
144 for (i = 0; !atEnd && error == 0; i++)
146 if (readBlock(PartitionBase, root, block_no, ebr) == 0)
148 if (AROS_LE2WORD(ebr->magic) == 0xAA55)
150 /* Create handle for current EBR's logical partition */
152 if (AROS_LE2LONG(ebr->pcpt[0].count_sector) != 0)
154 ph = PartitionEBRNewHandle(PartitionBase, root,
155 ebr->pcpt[0].type,
156 block_no + AROS_LE2LONG(ebr->pcpt[0].first_sector),
157 AROS_LE2LONG(ebr->pcpt[0].count_sector),
158 block_no);
159 if (ph != NULL)
161 Enqueue(&root->table->list, &ph->ln);
163 else
164 error = 1;
167 /* Get location of next EBR in chain */
169 block_no = AROS_LE2LONG(ebr->pcpt[1].first_sector);
170 if (block_no == 0)
171 atEnd = TRUE;
173 else
174 error = 1;
176 else
177 error = 1;
179 FreeMem(ebr, root->de.de_SizeBlock<<2);
181 else
182 error = 1;
183 return error;
186 static void PartitionEBRFreeHandle
188 struct Library *PartitionBase,
189 struct PartitionHandle *ph
192 ClosePartitionTable(ph);
193 FreeMem(ph->data, sizeof(struct EBRData));
194 FreeMem(ph, sizeof(struct PartitionHandle));
197 static void PartitionEBRClosePartitionTable
199 struct Library *PartitionBase,
200 struct PartitionHandle *root
203 struct PartitionHandle *ph;
205 while ((ph = (struct PartitionHandle *)RemTail(&root->table->list)))
206 PartitionEBRFreeHandle(PartitionBase, ph);
209 static LONG PartitionEBRWritePartitionTable
211 struct Library *PartitionBase,
212 struct PartitionHandle *root
215 ULONG block_no, block_count;
216 struct PartitionHandle *ph, *next_ph, *tail;
217 struct EBRData *data, *next_data;
218 struct DosEnvec *de;
219 struct MBR *ebr;
220 LONG error = 0;
222 ebr = AllocMem(root->de.de_SizeBlock << 2, MEMF_PUBLIC | MEMF_CLEAR);
223 if (ebr != NULL)
225 ph = (struct PartitionHandle *)root->table->list.lh_Head;
226 tail = (struct PartitionHandle *)&root->table->list.lh_Tail;
228 if (ph == tail)
230 /* Write an empty EBR block for empty partition table */
232 ebr->magic = AROS_WORD2LE(0xAA55);
233 if (writeBlock(PartitionBase, root, 0, ebr))
234 error = 1;
237 else
239 /* First EBR must be at extended partition's first block */
240 data = (struct EBRData *)ph->data;
241 data->ebr_block_no = 0;
243 /* Write an EBR block for every partition in the list */
245 while (ph != tail)
247 data = (struct EBRData *)ph->data;
248 next_ph = (struct PartitionHandle *)ph->ln.ln_Succ;
250 /* Write table entry for current EBR's logical partition */
252 de = &ph->de;
253 block_no = de->de_LowCyl * de->de_Surfaces * de->de_BlocksPerTrack;
254 block_count = (de->de_HighCyl - de->de_LowCyl + 1) *
255 de->de_Surfaces * de->de_BlocksPerTrack;
257 PartitionMBRSetGeometry(root, &ebr->pcpt[0], block_no,
258 block_count, data->ebr_block_no);
259 ebr->pcpt[0].status = 0;
260 ebr->pcpt[0].type = data->type;
262 /* Write table entry that points to next EBR in chain */
264 if (next_ph != tail)
266 de = &root->de;
267 next_data = (struct EBRData *)next_ph->data;
268 block_no = next_data->ebr_block_no;
269 block_count = (de->de_HighCyl - de->de_LowCyl + 1) *
270 de->de_Surfaces * de->de_BlocksPerTrack - block_no;
271 ebr->pcpt[1].type = MBRT_EXTENDED;
273 else
275 block_no = 0;
276 block_count = 0;
277 ebr->pcpt[1].type = 0;
279 PartitionMBRSetGeometry(root, &ebr->pcpt[1], block_no, block_count, 0);
280 ebr->pcpt[1].status = 0;
282 /* Write EBR */
284 ebr->magic = AROS_WORD2LE(0xAA55);
285 if (writeBlock(PartitionBase, root, data->ebr_block_no, ebr))
286 error = 1;
288 ph = next_ph;
292 FreeMem(ebr, root->de.de_SizeBlock << 2);
294 else
295 error = 1;
297 return error;
300 static LONG PartitionEBRCreatePartitionTable
302 struct Library *PartitionBase,
303 struct PartitionHandle *ph
306 NEWLIST(&ph->table->list);
307 return 0;
310 static struct PartitionHandle *PartitionEBRAddPartition
312 struct Library *PartitionBase,
313 struct PartitionHandle *root,
314 struct TagItem *taglist
317 struct TagItem *tag;
318 struct EBRData *data;
319 ULONG block_no = 0, new_block_no, new_block_count, ebr_track_no, ebr_block_no;
320 struct PartitionHandle *ph, *new_ph, *head;
321 struct DosEnvec *de;
322 BOOL found = FALSE;
323 struct PartitionType *ptype;
324 LONG error = 0;
326 tag = findTagItem(PT_DOSENVEC, taglist);
327 if (tag == NULL)
328 error = 1;
330 if (error == 0)
332 de = (struct DosEnvec *)tag->ti_Data;
334 tag = findTagItem(PT_TYPE, taglist);
335 if (tag == NULL)
336 error = 1;
339 if (error == 0)
341 ptype = (struct PartitionType *)tag->ti_Data;
343 new_block_no =
344 de->de_LowCyl * de->de_Surfaces * de->de_BlocksPerTrack;
345 new_block_count = (de->de_HighCyl - de->de_LowCyl + 1) *
346 de->de_Surfaces * de->de_BlocksPerTrack;
348 /* Find the position in the chain/list of EBRs at which to insert
349 new EBR */
351 ph = (struct PartitionHandle *)root->table->list.lh_TailPred;
352 head = (struct PartitionHandle *)&root->table->list;
354 while (ph != head && !found)
356 data = (struct EBRData *)ph->data;
357 de = &ph->de;
358 block_no = de->de_LowCyl * de->de_Surfaces * de->de_BlocksPerTrack;
359 if (block_no < new_block_no)
360 found = TRUE;
361 else
362 ph = (struct PartitionHandle *)ph->ln.ln_Pred;
365 /* Calculate appropriate location for new EBR */
367 de = &root->de;
368 ebr_track_no = (new_block_no - 1) / de->de_BlocksPerTrack;
369 ebr_block_no = ebr_track_no * de->de_BlocksPerTrack;
371 /* Create new handle and add it to list */
373 new_ph = PartitionEBRNewHandle(PartitionBase, root, ptype->id[0],
374 new_block_no, new_block_count, ebr_block_no);
375 Insert(&root->table->list, &new_ph->ln, &ph->ln);
377 return new_ph;
379 return NULL;
382 static void PartitionEBRDeletePartition
384 struct Library *PartitionBase,
385 struct PartitionHandle *ph
388 Remove(&ph->ln);
389 PartitionEBRFreeHandle(PartitionBase, ph);
392 static LONG PartitionEBRGetPartitionTableAttrs
394 struct Library *PartitionBase,
395 struct PartitionHandle *root,
396 struct TagItem *taglist
399 while (taglist[0].ti_Tag != TAG_DONE)
401 switch (taglist[0].ti_Tag)
403 case PTT_TYPE:
404 *((LONG *)taglist[0].ti_Data) = root->table->type;
405 break;
406 case PTT_MAXLEADIN:
407 *((LONG *)taglist[0].ti_Data) = root->de.de_BlocksPerTrack;
408 break;
410 taglist++;
412 return 0;
415 static LONG PartitionEBRSetPartitionTableAttrs
417 struct Library *PartitionBase,
418 struct PartitionHandle *root,
419 struct TagItem *taglist
422 while (taglist[0].ti_Tag != TAG_DONE)
424 switch (taglist[0].ti_Tag)
427 taglist++;
429 return 0;
432 static LONG PartitionEBRGetPartitionAttrs
434 struct Library *PartitionBase,
435 struct PartitionHandle *ph,
436 struct TagItem *taglist
439 ULONG i;
440 struct PartitionHandle *list_ph;
442 while (taglist[0].ti_Tag != TAG_DONE)
444 struct EBRData *data = (struct EBRData *)ph->data;
446 switch (taglist[0].ti_Tag)
448 case PT_GEOMETRY:
450 struct DriveGeometry *dg = (struct DriveGeometry *)taglist[0].ti_Data;
451 CopyMem(&ph->dg, dg, sizeof(struct DriveGeometry));
453 break;
454 case PT_DOSENVEC:
455 CopyMem(&ph->de, (struct DosEnvec *)taglist[0].ti_Data, sizeof(struct DosEnvec));
456 break;
457 case PT_TYPE:
459 struct PartitionType *ptype=(struct PartitionType *)taglist[0].ti_Data;
461 ptype->id[0] = data->type;
462 ptype->id_len = 1;
464 break;
465 case PT_POSITION:
466 i = 0;
467 ForeachNode(&ph->root->table->list, list_ph)
469 if (list_ph == ph)
470 *((LONG *)taglist[0].ti_Data) = i;
471 i++;
473 break;
475 taglist++;
477 return 0;
480 static LONG PartitionEBRSetPartitionAttrs
482 struct Library *PartitionBase,
483 struct PartitionHandle *ph,
484 struct TagItem *taglist
487 while (taglist[0].ti_Tag != TAG_DONE)
489 struct EBRData *data = (struct EBRData *)ph->data;
491 switch (taglist[0].ti_Tag)
493 case PT_DOSENVEC:
495 // TO DO: move handle to new position in list
496 struct DosEnvec *de;
497 de = (struct DosEnvec *)taglist[0].ti_Data;
498 CopyMem(de, &ph->de, sizeof(struct DosEnvec));
500 break;
501 case PT_TYPE:
503 struct PartitionType *ptype=(struct PartitionType *)taglist[0].ti_Data;
505 data->type = ptype->id[0]; // fix
507 break;
509 taglist++;
511 return 0;
514 static struct PartitionAttribute PartitionEBRPartitionTableAttrs[]=
516 {PTTA_TYPE, PLAM_READ},
517 {PTTA_RESERVED, PLAM_READ},
518 {PTTA_MAXLEADIN, PLAM_READ},
519 {PTTA_DONE, 0}
522 static struct PartitionAttribute *PartitionEBRQueryPartitionTableAttrs(
523 struct Library *PartitionBase)
525 return PartitionEBRPartitionTableAttrs;
528 static struct PartitionAttribute PartitionEBRPartitionAttrs[]=
530 {PTA_GEOMETRY, PLAM_READ},
531 {PTA_TYPE, PLAM_READ | PLAM_WRITE},
532 {PTA_DOSENVEC, PLAM_READ | PLAM_WRITE},
533 {PTA_POSITION, PLAM_READ},
534 {PTA_LEADIN, PLAM_READ},
535 {PTA_DONE, 0}
538 static struct PartitionAttribute *PartitionEBRQueryPartitionAttrs(
539 struct Library *PartitionBase)
541 return PartitionEBRPartitionAttrs;
544 static ULONG PartitionEBRDestroyPartitionTable
546 struct Library *PartitionBase,
547 struct PartitionHandle *root
550 struct PartitionHandle *ph;
553 while ((ph = (struct PartitionHandle *)RemHead(&root->table->list))
554 != NULL)
556 PartitionEBRDeletePartition(PartitionBase, ph);
558 PartitionEBRWritePartitionTable(PartitionBase, root);
560 return 0;
563 struct PTFunctionTable PartitionEBR =
565 PHPTT_EBR,
566 "PC-EBR",
567 PartitionEBRCheckPartitionTable,
568 PartitionEBROpenPartitionTable,
569 PartitionEBRClosePartitionTable,
570 PartitionEBRWritePartitionTable,
571 PartitionEBRCreatePartitionTable,
572 PartitionEBRAddPartition,
573 PartitionEBRDeletePartition,
574 PartitionEBRGetPartitionTableAttrs,
575 PartitionEBRSetPartitionTableAttrs,
576 PartitionEBRGetPartitionAttrs,
577 PartitionEBRSetPartitionAttrs,
578 PartitionEBRQueryPartitionTableAttrs,
579 PartitionEBRQueryPartitionAttrs,
580 PartitionEBRDestroyPartitionTable