1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,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: pc_scsi_label.c,v $
29 * Revision 2.9 93/11/17 18:42:05 dbg
30 * Delinted. Added ANSI function prototypes.
31 * [93/09/28 dbg]
32 *
33 * Revision 2.8 93/08/10 16:02:19 mrt
34 * Moved here from i386at/grab_bob_label.c as the code now works
35 * on scsi disks on many platforms.
36 * We now use bsd labels internally and convert from "local labels"
37 * if we find them on the disk.
38 * [93/08/05 rvb]
39 *
40 * Revision 2.7 93/03/09 11:18:39 danner
41 * If there is no recognizable label, we must return sensible
42 * defaults for getstatus or freak out diskutil. Alternatively,
43 * we could ship a new diskutil.
44 * [93/02/23 rvb]
45 *
46 * Revision 2.6 92/07/09 22:53:52 rvb
47 * No need to print out the relation between capacity and stated geometry.
48 * Also adjust GETPARMS answer's to the adaptec's view of reality.
49 * [92/06/18 rvb]
50 * tgt->unit_no is not set up correctly now; should use masterno instead
51 * [92/05/22 17:31:10 rvb]
52 *
53 * Fixed by Jukka Virtanen <jtv@kampi.hut.fi>
54 *
55 * Revision 2.5 92/04/03 12:08:41 rpd
56 * Reviewed with and blessed (?) by af.
57 * [92/04/01 rvb]
58 * Merged bernadat's change to mainline. Made conditional
59 * on i386 vs AT386.
60 * [92/03/16 rvb]
61 * Add AT specific setstatus/getstatus flavors
62 * to support vtoc, diskutil, verify ...
63 * [92/03/04 bernadat]
64 *
65 * Revision 2.4 92/02/23 22:43:04 elf
66 * Dropped first scsi_softc argument.
67 * [92/02/22 19:58:21 af]
68 *
69 * Revision 2.3 92/02/19 16:29:46 elf
70 * On 25-Jan, did not consider NO ACTIVE mach parition.
71 * [92/01/31 rvb]
72 *
73 * Add "BIOS" support -- always boot mach partition NOT active one.
74 * [92/01/25 rvb]
75 *
76 * Revision 2.2 91/08/24 11:57:41 af
77 * Temporarily created, till we evaporate the religious issues.
78 * [91/08/02 af]
79 *
80 */
81 /* This goes away as soon as we move it in the Ux server */
82
83 #include <mach/std_types.h>
84 #include <kern/kern_io.h>
85 #include <kern/memory.h>
86 #include <vm/vm_kern.h>
87 #include <scsi/compat_30.h>
88 #include <scsi/scsi.h>
89 #include <scsi/scsi_defs.h>
90 #include <scsi/rz.h>
91 #include <scsi/rz_labels.h>
92 #include <sys/types.h>
93 #include <sys/ioctl.h>
94
95 #define LABEL_DEBUG(x,y) if (label_flag&x) y
96
97 #include <i386at/disk.h>
98 #include <i386at/hdreg.h>
99 #include <device/device_types.h>
100 #include <device/disk_status.h>
101
102 int grab_bob_label(
103 target_info_t *tgt,
104 struct disklabel *label,
105 io_req_t ior,
106 struct bios_partition_info *bpart)
107 {
108 register int i, n;
109 struct evtoc *evp;
110 struct bios_partition_info *ospart = (struct bios_partition_info *)0;
111 struct bios_partition_info *first_part = bpart;
112 int upart;
113 int dev_bsize = tgt->block_size;
114 extern int label_flag;
115
116 #ifdef old
117 {
118 int nmach = 0;
119 int mabr = 0,
120 mbr = 0;
121
122 for (i = 0; i < 4; i++) {
123 if (bpart[i].systid == UNIXOS) {
124 if (!nmach++)
125 mbr = i;
126 if (bpart[i].bootid == BIOS_BOOTABLE)
127 mabr = i;
128 }
129 }
130 if (mabr)
131 i = mabr;
132 else if (nmach == 1)
133 i = mbr;
134 else if (nmach == 0)
135 return 0; /* DOS, no Mach */
136 else {
137 printf("Warning: More than one Mach partition and none active.\n");
138 printf("Using DOS partition #%d\n", mbr);
139 i = mbr;
140 }
141 }
142 #else /* old */
143 for (i = 0; i < 4; i++, bpart++) {
144 LABEL_DEBUG(1, print_dos_partition(i, bpart));
145 if (bpart->systid == UNIXOS || bpart->systid == BSDOS) {
146 if (ospart != 0) {
147 if (bpart->bootid == ACTIVE)
148 ospart = bpart;
149 } else
150 ospart = bpart;
151 }
152 }
153 if (ospart == 0)
154 return 0;
155 #endif /* old */
156 OS = ospart->systid;
157 if (OS == UNIXOS)
158 printf("sd%d: MACH OS ", tgt->target_id);
159 if (OS == BSDOS)
160 printf("sd%d: XXXBSD OS ", tgt->target_id);
161 upart = ospart - first_part;
162 tgt->dev_info.disk.labeloffset = 0;
163 tgt->dev_info.disk.labelsector = (ospart->offset + LBLLOC) * 512 / dev_bsize;
164 /*
165 * In rz_labels:rz_bios_label(), we have set up DOS partitions 0-3 to correspond
166 * to the parittions 0-3 in the label. Hence we use the "upart" above, in
167 * the line below.
168 */
169 ior->io_unit = (tgt->masterno<<6) + (tgt->target_id<<3) + (upart);
170 ior->io_count = DEV_BSIZE;
171 ior->io_error = 0;
172 ior->io_op = IO_READ;
173 ior->io_recnum = 29; /* that's where the vtoc is */
174 scdisk_strategy(ior);
175 iowait(ior);
176 evp = (struct evtoc *)ior->io_data;
177
178 if (evp->sanity != VTOC_SANE) {
179 printf("vtoc insane\n");
180 return 0;
181 }
182
183 printf("LOCAL LABEL ");
184 LABEL_DEBUG(4,print_local_label(evp, "ev:"));
185
186 bcopy(evp->label, label->d_packname, 16);/* truncates, too bad */
187 n = evp->nparts;
188 if (n >= MAXPARTITIONS)
189 n = MAXPARTITIONS;
190 fudge_bsd_label(label, DTYPE_SCSI, evp->cyls, evp->tracks, evp->sectors, n);
191 #ifdef you_care
192 if (label->d_secperunit != evp->tracks * evp->sectors * evp->cyls)
193 printf("sd%d: capacity (%d) != S*H*C (%d)\n", tgt->target_id,
194 label->d_secperunit, evp->tracks * evp->sectors * evp->cyls);
195 #endif
196 /* copy info on first MAXPARTITIONS */
197 /* "c" is never read; always calculated */
198 label->d_partitions[2].p_size = label->d_partitions[upart].p_size;
199 label->d_partitions[2].p_offset = label->d_partitions[upart].p_offset;
200 for (i = 0; i < n ; i++) {
201 if (i == 2)
202 continue;
203 bzero(&(label->d_partitions[i]), sizeof (struct partition));
204 label->d_partitions[i].p_size = evp->part[i].p_size;
205 label->d_partitions[i].p_offset = evp->part[i].p_start;
206 label->d_partitions[i].p_fstype = FS_BSDFFS;
207 }
208 for ( ; i < MAXPARTITIONS; i++) {
209 if (i == 2)
210 continue;
211 bzero(&(label->d_partitions[i]), sizeof (struct partition));
212 }
213 /* whole disk */
214 label->d_partitions[MAXPARTITIONS].p_size = -1;
215 label->d_partitions[MAXPARTITIONS].p_offset = 0;
216 label->d_checksum = dkcksum(label);
217 LABEL_DEBUG(0x20,print_bsd_label(label, " "));
218 return 1;
219 }
220
221 int scsi_abs_sec = -1;
222 int scsi_abs_count = -1;
223
224 io_return_t
225 scsi_rw_abs(
226 dev_t dev,
227 io_buf_ptr_t data,
228 int rw,
229 int sec,
230 natural_t count)
231
232 {
233 io_req_t ior;
234 io_return_t error;
235
236 io_req_alloc(ior,0);
237 ior->io_next = 0;
238 ior->io_unit = dev & (~(MAXPARTITIONS-1)); /* sort of */
239 ior->io_unit |= PARTITION_ABSOLUTE;
240 ior->io_data = data;
241 ior->io_count = count;
242 ior->io_recnum = sec;
243 ior->io_error = 0;
244 if (rw == IO_READ)
245 ior->io_op = IO_READ;
246 else
247 ior->io_op = IO_WRITE;
248 scdisk_strategy(ior);
249 iowait(ior);
250 error = ior->io_error;
251 io_req_free(ior);
252 return error;
253 }
254
255 io_return_t
256 scsi_i386_get_status(
257 int dev,
258 target_info_t *tgt,
259 int flavor,
260 dev_status_t status,
261 natural_t *status_count)
262 {
263
264 switch (flavor) {
265 case V_GETPARMS: {
266 struct disklabel *lp = &tgt->dev_info.disk.l;
267 struct disk_parms *dp = (struct disk_parms *)status;
268 extern struct disklabel scsi_default_label;
269 int part = rzpartition(dev);
270
271 if (*status_count < sizeof (struct disk_parms)/sizeof(int))
272 return D_INVALID_OPERATION;
273 dp->dp_type = DPT_WINI;
274 dp->dp_secsiz = lp->d_secsize;
275 if (lp->d_nsectors == scsi_default_label.d_nsectors &&
276 lp->d_ntracks == scsi_default_label.d_ntracks &&
277 lp->d_ncylinders == scsi_default_label.d_ncylinders) {
278 /* I guess there is nothing there */
279 /* Well, then, Adaptecs like ... */
280 dp->dp_sectors = 32;
281 dp->dp_heads = 64;
282 dp->dp_cyls = lp->d_secperunit / 64 / 32 ;
283 } else {
284 dp->dp_sectors = lp->d_nsectors;
285 dp->dp_heads = lp->d_ntracks;
286 dp->dp_cyls = lp->d_ncylinders;
287 }
288
289 dp->dp_dossectors = 32;
290 dp->dp_dosheads = 64;
291 dp->dp_doscyls = lp->d_secperunit / 64 / 32;
292 dp->dp_ptag = 0;
293 dp->dp_pflag = 0;
294 dp->dp_pstartsec = lp->d_partitions[part].p_offset;
295 dp->dp_pnumsec = lp->d_partitions[part].p_size;
296 *status_count = sizeof(struct disk_parms)/sizeof(int);
297 break;
298 }
299 case V_RDABS:
300 if (*status_count < DEV_BSIZE/sizeof (int)) {
301 printf("RDABS bad size %x", *status_count);
302 return D_INVALID_OPERATION;
303 }
304 if (scsi_rw_abs(dev,
305 (io_buf_ptr_t) status,
306 IO_READ,
307 scsi_abs_sec,
308 DEV_BSIZE) != D_SUCCESS)
309 return D_INVALID_OPERATION;
310 *status_count = DEV_BSIZE/sizeof(int);
311 break;
312 case V_VERIFY: {
313 int count = scsi_abs_count * DEV_BSIZE;
314 int sec = scsi_abs_sec;
315 char *scsi_verify_buf;
316
317 (void) kmem_alloc(kernel_map,
318 (vm_offset_t *) &scsi_verify_buf,
319 PAGE_SIZE);
320
321 *status = 0;
322 while (count > 0) {
323 int xcount = (count < PAGE_SIZE) ? count : PAGE_SIZE;
324 if (scsi_rw_abs(dev, scsi_verify_buf, IO_READ,
325 sec, xcount) != D_SUCCESS)
326 {
327 *status = BAD_BLK;
328 break;
329 } else {
330 count -= xcount;
331 sec += xcount / DEV_BSIZE;
332 }
333 }
334 (void) kmem_free(kernel_map,
335 (vm_offset_t) scsi_verify_buf,
336 PAGE_SIZE);
337 *status_count = 1;
338 break;
339 }
340 default:
341 return D_INVALID_OPERATION;
342 }
343 return D_SUCCESS;
344 }
345
346 io_return_t
347 scsi_i386_set_status(
348 int dev,
349 target_info_t *tgt,
350 int flavor,
351 dev_status_t status,
352 natural_t status_count)
353 {
354 switch (flavor) {
355 case V_SETPARMS:
356 printf("scsdisk_set_status: invalid flavor V_SETPARMS\n");
357 return D_INVALID_OPERATION;
358 break;
359 case V_REMOUNT:
360 tgt->flags &= ~TGT_ONLINE;
361 break;
362 case V_ABS:
363 scsi_abs_sec = status[0];
364 if (status_count == 2)
365 scsi_abs_count = status[1];
366 break;
367 case V_WRABS:
368 if (status_count < DEV_BSIZE/sizeof (int)) {
369 printf("RDABS bad size %x", status_count);
370 return D_INVALID_OPERATION;
371 }
372 if (scsi_rw_abs(dev,
373 (io_buf_ptr_t) status,
374 IO_WRITE,
375 scsi_abs_sec,
376 DEV_BSIZE) != D_SUCCESS)
377 return D_INVALID_OPERATION;
378 break;
379 default:
380 return D_INVALID_OPERATION;
381 }
382 return D_SUCCESS;
383 }
Cache object: 6f2481423d04eb544a6da03cdfbc0e60
|