2 * NEC PC-9800 series partition supports
4 * Copyright (C) 1999 Kyoto University Microcomputer Club
7 #include <linux/config.h>
9 #include <linux/genhd.h>
10 #include <linux/kernel.h>
11 #include <linux/hdreg.h>
16 struct nec98_partition {
17 __u8 mid; /* 0x80 - active */
18 __u8 sid; /* 0x80 - bootable */
19 __u16 pad1; /* dummy for padding */
20 __u8 ipl_sector; /* IPL sector */
21 __u8 ipl_head; /* IPL head */
22 __u16 ipl_cyl; /* IPL cylinder */
23 __u8 sector; /* starting sector */
24 __u8 head; /* starting head */
25 __u16 cyl; /* starting cylinder */
26 __u8 end_sector; /* end sector */
27 __u8 end_head; /* end head */
28 __u16 end_cyl; /* end cylinder */
29 unsigned char name[16];
30 } __attribute__((__packed__));
32 #define NEC98_BSD_PARTITION_MID 0x14
33 #define NEC98_BSD_PARTITION_SID 0x44
34 #define MID_SID_16(mid, sid) (((mid) & 0xFF) | (((sid) & 0xFF) << 8))
35 #define NEC98_BSD_PARTITION_MID_SID \
36 MID_SID_16(NEC98_BSD_PARTITION_MID, NEC98_BSD_PARTITION_SID)
37 #define NEC98_VALID_PTABLE_ENTRY(P) \
38 (!(P)->pad1 && (P)->cyl <= (P)->end_cyl)
40 extern int pc98_bios_param(struct block_device *bdev, int *ip);
43 is_valid_nec98_partition_table(const struct nec98_partition *ptable,
44 __u8 nsectors, __u8 nheads)
49 for (i = 0; i < 16; i++) {
50 if (!*(__u16 *)&ptable[i])
51 continue; /* empty slot */
52 if (ptable[i].pad1 /* `pad1' contains junk */
53 || ptable[i].ipl_sector >= nsectors
54 || ptable[i].sector >= nsectors
55 || ptable[i].end_sector >= nsectors
56 || ptable[i].ipl_head >= nheads
57 || ptable[i].head >= nheads
58 || ptable[i].end_head >= nheads
59 || ptable[i].cyl > ptable[i].end_cyl)
61 valid = 1; /* We have a valid partition. */
63 /* If no valid PC-9800-style partitions found,
64 the disk may have other type of partition table. */
68 int nec98_partition(struct parsed_partitions *state, struct block_device *bdev)
71 struct hd_geometry geo;
73 const struct nec98_partition *part;
75 int sector_size = bdev_hardsect_size(bdev);
77 if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)&geo) != 0) {
78 printk(" unsupported disk (%s)\n", bdev->bd_disk->disk_name);
82 #ifdef NEC98_PARTITION_DEBUG
83 printk("ioctl_by_bdev head=%d sect=%d\n", geo.heads, geo.sectors);
85 data = read_dev_sector(bdev, 0, §);
88 printk(" unable to read partition table\n");
93 if (*(__u16 *)(data + sector_size - 2) != NEC98_PTABLE_MAGIC) {
99 data = read_dev_sector(bdev, 1, §);
102 printk(" unable to read partition table\n");
106 if (!is_valid_nec98_partition_table((struct nec98_partition *)data,
107 geo.sectors, geo.heads)) {
108 #ifdef NEC98_PARTITION_DEBUG
110 printk(" partition table consistency check failed"
111 " (not PC-9800 disk?)\n");
113 put_dev_sector(sect);
117 part = (const struct nec98_partition *)data;
118 for (nr = 0; nr < 16; nr++, part++) {
119 unsigned int start_sect, end_sect;
121 if (part->mid == 0 || part->sid == 0)
127 { /* Print partition name. Fdisk98 might put NUL
128 characters in partition name... */
132 unsigned char buf[sizeof (part->name) * 2 + 1];
134 for (p = buf, j = 0; j < sizeof (part->name); j++, p++)
135 if ((*p = part->name[j]) < ' ') {
137 *p = part->name[j] + '@';
141 printk(" <%s>", buf);
143 start_sect = (part->cyl * geo.heads + part->head) * geo.sectors
145 end_sect = (part->end_cyl + 1) * geo.heads * geo.sectors;
146 if (end_sect <= start_sect) {
147 printk(" (invalid partition info)\n");
151 put_partition(state, nr + 1, start_sect, end_sect - start_sect);
152 #ifdef CONFIG_BSD_DISKLABEL
153 if ((*(__u16 *)&part->mid & 0x7F7F)
154 == NEC98_BSD_PARTITION_MID_SID) {
156 /* NEC98_BSD_PARTITION_MID_SID is not valid SYSIND for
157 IBM PC's MS-DOS partition table, so we simply pass
158 it to bsd_disklabel_partition;
159 it will just print `<bsd: ... >'. */
160 parse_bsd(state, bdev, start_sect,
161 end_sect - start_sect, nr + 1,
162 "bsd98", BSD_MAXPARTITIONS);
165 { /* Pretty size printing. */
166 /* XXX sector size? */
167 unsigned int psize = (end_sect - start_sect) / 2;
174 printk(" %5d%cB (%5d-%5d)\n",
175 psize, unit_char, part->cyl, part->end_cyl);
179 put_dev_sector(sect);