FreeBSD/Linux Kernel Cross Reference
sys/scsi/rz_labels.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,1991,1990,1989 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: rz_labels.c,v $
29 * Revision 2.11 93/11/17 18:44:36 dbg
30 * Need to always keep d_partitions[MAXPARTITIONS] correct, so
31 * always reset it ourselves.
32 * [93/10/08 rvb]
33 *
34 * Revision 2.10 93/08/10 15:19:51 mrt
35 * We now use bsd labels internally and convert from "local labels"
36 * if we find them on the disk.
37 * [93/08/03 20:36:46 rvb]
38 *
39 * Revision 2.9 93/05/10 21:22:41 rvb
40 * Removed depends on DEV_BSIZE.
41 * [93/05/06 10:09:09 af]
42 *
43 * Revision 2.8 93/03/09 11:18:35 danner
44 * If there is no recognizable label, we must set p_size of the
45 * MAXPARTITION slice. We use MAXPARTITION to do ABSOLUTE reads.
46 * [93/02/23 rvb]
47 *
48 * Revision 2.7 92/08/03 17:53:58 jfriedl
49 * removed silly prototypes
50 * [92/08/02 jfriedl]
51 *
52 * Revision 2.6 92/05/21 17:23:47 jfriedl
53 * tried prototypes.
54 * [92/05/20 jfriedl]
55 *
56 * Revision 2.5 92/04/03 12:10:09 rpd
57 * Let "grab_bob_label" return failure so we take the default.
58 * [92/04/01 rvb]
59 *
60 * Revision 2.4 92/02/23 22:44:31 elf
61 * Actually, scan for all possible (bogus) label formats.
62 * This makes it possible to cross-mount disks even if
63 * they do not have the standard BSD label.
64 * [92/02/22 af]
65 *
66 * Revision 2.3 91/08/24 12:28:06 af
67 * Created, splitting out DEC-specific code from rz_disk.c and
68 * adding some more.
69 * [91/06/26 af]
70 *
71 */
72 /*
73 * File: rz_labels.c
74 * Author: Alessandro Forin, Carnegie Mellon University
75 * Date: 6/91
76 *
77 * Routines for various vendor's disk label formats.
78 */
79
80 #include <platforms.h>
81
82 #include <mach/std_types.h>
83 #include <kern/memory.h>
84 #include <scsi/compat_30.h>
85 #include <scsi/scsi_defs.h>
86 #include <scsi/rz_labels.h>
87
88 #define LABEL_DEBUG(x,y) if (label_flag&x) y
89
90
91 /*
92 * Find and convert from a DEC label to BSD
93 */
94 boolean_t
95 rz_dec_label(
96 target_info_t *tgt,
97 struct disklabel *label,
98 io_req_t ior)
99 {
100 /* here look for a DEC label */
101 register scsi_dec_label_t *part;
102 char *data;
103 int i, dev_bsize = tgt->block_size;
104
105 ior->io_count = dev_bsize;
106 ior->io_op = IO_READ;
107 tgt->ior = ior;
108 scdisk_read( tgt, DEC_LABEL_BYTE_OFFSET/dev_bsize, ior);
109 iowait(ior);
110 data = (char *)ior->io_data;
111 part = (scsi_dec_label_t*)&data[DEC_LABEL_BYTE_OFFSET%dev_bsize];
112 if (part->magic == DEC_LABEL_MAGIC) {
113 if (scsi_debug)
114 printf("{Using DEC label}");
115 for (i = 0; i < 8; i++) {
116 label->d_partitions[i].p_size = part->partitions[i].n_sectors;
117 label->d_partitions[i].p_offset = part->partitions[i].offset;
118 }
119 return TRUE;
120 }
121 return FALSE;
122 }
123
124 /*
125 * Find and convert from a Omron label to BSD
126 */
127 boolean_t
128 rz_omron_label(
129 target_info_t *tgt,
130 struct disklabel *label,
131 io_req_t ior)
132 {
133 /* here look for an Omron label */
134 register scsi_omron_label_t *part;
135 char *data;
136 int i, dev_bsize = tgt->block_size;
137
138 ior->io_count = dev_bsize;
139 ior->io_op = IO_READ;
140 tgt->ior = ior;
141 scdisk_read( tgt, OMRON_LABEL_BYTE_OFFSET/dev_bsize, ior);
142 iowait(ior);
143 data = (char *)ior->io_data;
144 part = (scsi_omron_label_t*)&data[OMRON_LABEL_BYTE_OFFSET%dev_bsize];
145 if (part->magic == OMRON_LABEL_MAGIC) {
146 if (scsi_debug)
147 printf("{Using OMRON label}");
148 for (i = 0; i < 8; i++) {
149 label->d_partitions[i].p_size = part->partitions[i].n_sectors;
150 label->d_partitions[i].p_offset = part->partitions[i].offset;
151 }
152 bcopy(part->packname, label->d_packname, 16);
153 label->d_ncylinders = part->ncyl;
154 label->d_acylinders = part->acyl;
155 label->d_ntracks = part->nhead;
156 label->d_nsectors = part->nsect;
157 /* Many disks have this wrong, therefore.. */
158 #if 0
159 label->d_secperunit = part->maxblk;
160 #else
161 label->d_secperunit = label->d_ncylinders * label->d_ntracks *
162 label->d_nsectors;
163 #endif
164 return TRUE;
165 }
166 return FALSE;
167 }
168
169 /*
170 * Find and convert from a Intel BIOS label to BSD
171 */
172 extern int label_flag;
173 extern int OS;
174 #define BSDOS 165
175 #define LBLLOC 1
176
177 boolean_t
178 rz_bios_bsd_label(
179 target_info_t *tgt,
180 struct disklabel *label,
181 io_req_t ior,
182 struct bios_partition_info *ospart)
183 {
184 struct disklabel *dlp;
185 int dev_bsize = tgt->block_size;
186 int i;
187 extern int allow_bsd_label;
188
189 ior->io_count = dev_bsize;
190 ior->io_op = IO_READ;
191 tgt->ior = ior;
192 scdisk_read( tgt, (ospart->offset + LBLLOC) * 512 / dev_bsize, ior);
193 iowait(ior);
194 dlp = (struct disklabel *)ior->io_data;
195
196 if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
197 if (OS == BSDOS) {
198 printf("NO BSD LABEL!!\n");
199 }
200 return FALSE;
201 }
202
203 printf("BSD LABEL ");
204 LABEL_DEBUG(2,print_bsd_label(dlp, "dk:"));
205 /*
206 * here's where we dump label
207 */
208 if (allow_bsd_label == 0)
209 return FALSE;
210
211 i = label->d_secperunit;
212 *label = *dlp;
213 label->d_secperunit = i;
214 /*
215 * The disklabel program should insure the invariant below
216 * when it writes a label. But it does not seem to.
217 */
218 label->d_partitions[MAXPARTITIONS].p_size = -1;
219 label->d_partitions[MAXPARTITIONS].p_offset = 0;
220 label->d_checksum = dkcksum(label);
221
222 tgt->dev_info.disk.labeloffset = 0;
223 tgt->dev_info.disk.labelsector = (ospart->offset + LBLLOC) * 512 / dev_bsize;
224
225 LABEL_DEBUG(0x20,print_bsd_label(dlp, " "));
226 return TRUE;
227 }
228
229 boolean_t
230 rz_bios_label(
231 target_info_t *tgt,
232 struct disklabel *label,
233 io_req_t ior)
234 {
235 /* here look for a BIOS label */
236 char *data;
237 int i, dev_bsize = tgt->block_size;
238 scsi_bios_label_t part;
239
240 ior->io_count = dev_bsize;
241 ior->io_op = IO_READ;
242 tgt->ior = ior;
243 scdisk_read( tgt, BIOS_LABEL_BYTE_OFFSET/dev_bsize, ior);
244 iowait(ior);
245 data = (char *)ior->io_data;
246 /*
247 * It's safer to just copy the data here and not worry about
248 * scdisk_read's down the line will clobber the buffer.
249 */
250 part = *(scsi_bios_label_t*)&data[BIOS_LABEL_BYTE_OFFSET%dev_bsize];
251 if (((scsi_bios_label_t*)&data[BIOS_LABEL_BYTE_OFFSET%dev_bsize])->magic
252 == BIOS_LABEL_MAGIC) {
253 struct bios_partition_info *bpart, *ospart = (struct bios_partition_info *)0;
254 if (scsi_debug)
255 printf("{Using BIOS label}");
256 for (i = 0; i < 4; i++) {
257 bpart = &(((struct bios_partition_info *)part.partitions)[i]);
258 LABEL_DEBUG(1,print_dos_partition(i, bpart));
259 label->d_partitions[i].p_size = bpart->n_sectors;
260 label->d_partitions[i].p_offset = bpart->offset;
261 if (bpart->systid == UNIXOS || bpart->systid == BSDOS) {
262 if (ospart != 0) {
263 if (bpart->bootid == BIOS_BOOTABLE)
264 ospart = bpart;
265 } else
266 ospart = bpart;
267 }
268 }
269 tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_offset= 0;
270 tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_size = -1;
271
272 if (ospart == 0)
273 return FALSE;
274 OS = ospart->systid;
275 if (OS == UNIXOS)
276 printf("sd%d: MACH OS ", tgt->target_id);
277 if (OS == BSDOS)
278 printf("sd%d: XXXBSD OS ", tgt->target_id);
279
280 if (rz_bios_bsd_label(tgt, label, ior, ospart))
281 return TRUE;
282
283 #ifdef AT386 /* this goes away real fast */
284 if (!grab_bob_label(tgt, label, ior,
285 ((struct bios_partition_info *)part.partitions)))
286 return FALSE; /* take default setup of "a" and "c" */
287 #else
288 label->d_npartitions = 4;
289 #endif
290 label->d_bbsize = BIOS_BOOT0_SIZE;
291 return TRUE;
292 }
293 return FALSE;
294 }
295
296 /*
297 * Try all of the above
298 */
299 boolean_t rz_vendor_label(
300 target_info_t *tgt,
301 struct disklabel *label,
302 io_req_t ior)
303 {
304 /* If for any reason there might be problems someday.. */
305 #ifdef VENDOR_LABEL
306 if (VENDOR_LABEL( tgt, label, ior)) return TRUE;
307 #endif /*VENDOR_LABEL*/
308
309 if (rz_dec_label( tgt, label, ior)) return TRUE;
310 if (rz_bios_label( tgt, label, ior)) return TRUE;
311 if (rz_omron_label( tgt, label, ior)) return TRUE;
312 return FALSE;
313 }
314
Cache object: ebea0e20fa8e34e288071e42ad0a8dc1
|