Partial rewrite.
[linux-2.6/linux-mips.git] / fs / partitions / nec98.c
blobcbd55789f4b23a3ecd0608751006f91af891ae18
1 /*
2 * NEC PC-9800 series partition supports
4 * Copyright (C) 1999 Kyoto University Microcomputer Club
5 */
7 #include <linux/config.h>
8 #include <linux/fs.h>
9 #include <linux/genhd.h>
10 #include <linux/kernel.h>
11 #include <linux/blk.h>
12 #include <linux/hdreg.h>
14 #include "check.h"
15 #include "nec98.h"
17 struct nec98_partition {
18 __u8 mid; /* 0x80 - active */
19 __u8 sid; /* 0x80 - bootable */
20 __u16 pad1; /* dummy for padding */
21 __u8 ipl_sector; /* IPL sector */
22 __u8 ipl_head; /* IPL head */
23 __u16 ipl_cyl; /* IPL cylinder */
24 __u8 sector; /* starting sector */
25 __u8 head; /* starting head */
26 __u16 cyl; /* starting cylinder */
27 __u8 end_sector; /* end sector */
28 __u8 end_head; /* end head */
29 __u16 end_cyl; /* end cylinder */
30 unsigned char name[16];
31 } __attribute__((__packed__));
33 #define NEC98_BSD_PARTITION_MID 0x14
34 #define NEC98_BSD_PARTITION_SID 0x44
35 #define MID_SID_16(mid, sid) (((mid) & 0xFF) | (((sid) & 0xFF) << 8))
36 #define NEC98_BSD_PARTITION_MID_SID \
37 MID_SID_16(NEC98_BSD_PARTITION_MID, NEC98_BSD_PARTITION_SID)
38 #define NEC98_VALID_PTABLE_ENTRY(P) \
39 (!(P)->pad1 && (P)->cyl <= (P)->end_cyl)
41 extern int pc98_bios_param(struct block_device *bdev, int *ip);
43 static inline int
44 is_valid_nec98_partition_table(const struct nec98_partition *ptable,
45 __u8 nsectors, __u8 nheads)
47 int i;
48 int valid = 0;
50 for (i = 0; i < 16; i++) {
51 if (!*(__u16 *)&ptable[i])
52 continue; /* empty slot */
53 if (ptable[i].pad1 /* `pad1' contains junk */
54 || ptable[i].ipl_sector >= nsectors
55 || ptable[i].sector >= nsectors
56 || ptable[i].end_sector >= nsectors
57 || ptable[i].ipl_head >= nheads
58 || ptable[i].head >= nheads
59 || ptable[i].end_head >= nheads
60 || ptable[i].cyl > ptable[i].end_cyl)
61 return 0;
62 valid = 1; /* We have a valid partition. */
64 /* If no valid PC-9800-style partitions found,
65 the disk may have other type of partition table. */
66 return valid;
69 int nec98_partition(struct parsed_partitions *state, struct block_device *bdev)
71 unsigned int nr;
72 struct hd_geometry geo;
73 Sector sect;
74 const struct nec98_partition *part;
75 unsigned char *data;
76 int sector_size = bdev_hardsect_size(bdev);
77 int major = MAJOR(bdev->bd_dev);
79 if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)&geo) != 0) {
80 printk(" unsupported disk (major = %u)\n", major);
81 return 0;
84 #ifdef NEC98_PARTITION_DEBUG
85 printk("ioctl_by_bdev head=%d sect=%d\n", geo.heads, geo.sectors);
86 #endif
87 data = read_dev_sector(bdev, 0, &sect);
88 if (!data) {
89 if (warn_no_part)
90 printk(" unable to read partition table\n");
91 return -1;
94 /* magic(?) check */
95 if (*(__u16 *)(data + sector_size - 2) != NEC98_PTABLE_MAGIC) {
96 put_dev_sector(sect);
97 return 0;
100 put_dev_sector(sect);
101 data = read_dev_sector(bdev, 1, &sect);
102 if (!data) {
103 if (warn_no_part)
104 printk(" unable to read partition table\n");
105 return -1;
108 if (!is_valid_nec98_partition_table((struct nec98_partition *)data,
109 geo.sectors, geo.heads)) {
110 #ifdef NEC98_PARTITION_DEBUG
111 if (warn_no_part)
112 printk(" partition table consistency check failed"
113 " (not PC-9800 disk?)\n");
114 #endif
115 put_dev_sector(sect);
116 return 0;
119 part = (const struct nec98_partition *)data;
120 for (nr = 0; nr < 16; nr++, part++) {
121 unsigned int start_sect, end_sect;
123 if (part->mid == 0 || part->sid == 0)
124 continue;
126 if (nr)
127 printk(" ");
129 { /* Print partition name. Fdisk98 might put NUL
130 characters in partition name... */
132 int j;
133 unsigned char *p;
134 unsigned char buf[sizeof (part->name) * 2 + 1];
136 for (p = buf, j = 0; j < sizeof (part->name); j++, p++)
137 if ((*p = part->name[j]) < ' ') {
138 *p++ = '^';
139 *p = part->name[j] + '@';
142 *p = 0;
143 printk(" <%s>", buf);
145 start_sect = (part->cyl * geo.heads + part->head) * geo.sectors
146 + part->sector;
147 end_sect = (part->end_cyl + 1) * geo.heads * geo.sectors;
148 if (end_sect <= start_sect) {
149 printk(" (invalid partition info)\n");
150 continue;
153 put_partition(state, nr + 1, start_sect, end_sect - start_sect);
154 #ifdef CONFIG_BSD_DISKLABEL
155 if ((*(__u16 *)&part->mid & 0x7F7F)
156 == NEC98_BSD_PARTITION_MID_SID) {
157 printk("!");
158 /* NEC98_BSD_PARTITION_MID_SID is not valid SYSIND for
159 IBM PC's MS-DOS partition table, so we simply pass
160 it to bsd_disklabel_partition;
161 it will just print `<bsd: ... >'. */
162 parse_bsd(state, bdev, start_sect,
163 end_sect - start_sect, nr + 1,
164 "bsd98", BSD_MAXPARTITIONS);
166 #endif
167 { /* Pretty size printing. */
168 /* XXX sector size? */
169 unsigned int psize = (end_sect - start_sect) / 2;
170 int unit_char = 'K';
172 if (psize > 99999) {
173 psize >>= 10;
174 unit_char = 'M';
176 printk(" %5d%cB (%5d-%5d)\n",
177 psize, unit_char, part->cyl, part->end_cyl);
181 put_dev_sector(sect);
183 return nr ? 1 : 0;
187 * Local variables:
188 * c-basic-offset: 8
189 * End: