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/blk.h>
12 #include <linux/hdreg.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
);
44 is_valid_nec98_partition_table(const struct nec98_partition
*ptable
,
45 __u8 nsectors
, __u8 nheads
)
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
)
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. */
69 int nec98_partition(struct parsed_partitions
*state
, struct block_device
*bdev
)
72 struct hd_geometry geo
;
74 const struct nec98_partition
*part
;
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
);
84 #ifdef NEC98_PARTITION_DEBUG
85 printk("ioctl_by_bdev head=%d sect=%d\n", geo
.heads
, geo
.sectors
);
87 data
= read_dev_sector(bdev
, 0, §
);
90 printk(" unable to read partition table\n");
95 if (*(__u16
*)(data
+ sector_size
- 2) != NEC98_PTABLE_MAGIC
) {
100 put_dev_sector(sect
);
101 data
= read_dev_sector(bdev
, 1, §
);
104 printk(" unable to read partition table\n");
108 if (!is_valid_nec98_partition_table((struct nec98_partition
*)data
,
109 geo
.sectors
, geo
.heads
)) {
110 #ifdef NEC98_PARTITION_DEBUG
112 printk(" partition table consistency check failed"
113 " (not PC-9800 disk?)\n");
115 put_dev_sector(sect
);
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)
129 { /* Print partition name. Fdisk98 might put NUL
130 characters in partition name... */
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
]) < ' ') {
139 *p
= part
->name
[j
] + '@';
143 printk(" <%s>", buf
);
145 start_sect
= (part
->cyl
* geo
.heads
+ part
->head
) * geo
.sectors
147 end_sect
= (part
->end_cyl
+ 1) * geo
.heads
* geo
.sectors
;
148 if (end_sect
<= start_sect
) {
149 printk(" (invalid partition info)\n");
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
) {
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
);
167 { /* Pretty size printing. */
168 /* XXX sector size? */
169 unsigned int psize
= (end_sect
- start_sect
) / 2;
176 printk(" %5d%cB (%5d-%5d)\n",
177 psize
, unit_char
, part
->cyl
, part
->end_cyl
);
181 put_dev_sector(sect
);