mscp_disk.c revision 1.73 1 1.73 abs /* $NetBSD: mscp_disk.c,v 1.73 2012/07/10 22:30:23 abs Exp $ */
2 1.1 ragge /*
3 1.1 ragge * Copyright (c) 1988 Regents of the University of California.
4 1.1 ragge * All rights reserved.
5 1.1 ragge *
6 1.1 ragge * This code is derived from software contributed to Berkeley by
7 1.1 ragge * Chris Torek.
8 1.1 ragge *
9 1.1 ragge * Redistribution and use in source and binary forms, with or without
10 1.1 ragge * modification, are permitted provided that the following conditions
11 1.1 ragge * are met:
12 1.1 ragge * 1. Redistributions of source code must retain the above copyright
13 1.1 ragge * notice, this list of conditions and the following disclaimer.
14 1.1 ragge * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 ragge * notice, this list of conditions and the following disclaimer in the
16 1.1 ragge * documentation and/or other materials provided with the distribution.
17 1.42 agc * 3. Neither the name of the University nor the names of its contributors
18 1.42 agc * may be used to endorse or promote products derived from this software
19 1.42 agc * without specific prior written permission.
20 1.42 agc *
21 1.42 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.42 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.42 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.42 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.42 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.42 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.42 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.42 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.42 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.42 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.42 agc * SUCH DAMAGE.
32 1.42 agc *
33 1.42 agc * @(#)uda.c 7.32 (Berkeley) 2/13/91
34 1.42 agc */
35 1.42 agc
36 1.42 agc /*
37 1.42 agc * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
38 1.42 agc *
39 1.42 agc * This code is derived from software contributed to Berkeley by
40 1.42 agc * Chris Torek.
41 1.42 agc *
42 1.42 agc * Redistribution and use in source and binary forms, with or without
43 1.42 agc * modification, are permitted provided that the following conditions
44 1.42 agc * are met:
45 1.42 agc * 1. Redistributions of source code must retain the above copyright
46 1.42 agc * notice, this list of conditions and the following disclaimer.
47 1.42 agc * 2. Redistributions in binary form must reproduce the above copyright
48 1.42 agc * notice, this list of conditions and the following disclaimer in the
49 1.42 agc * documentation and/or other materials provided with the distribution.
50 1.1 ragge * 3. All advertising materials mentioning features or use of this software
51 1.1 ragge * must display the following acknowledgement:
52 1.1 ragge * This product includes software developed by the University of
53 1.1 ragge * California, Berkeley and its contributors.
54 1.1 ragge * 4. Neither the name of the University nor the names of its contributors
55 1.1 ragge * may be used to endorse or promote products derived from this software
56 1.1 ragge * without specific prior written permission.
57 1.1 ragge *
58 1.1 ragge * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 1.1 ragge * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 1.1 ragge * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 1.1 ragge * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 1.1 ragge * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 1.1 ragge * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 1.1 ragge * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 1.1 ragge * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 1.1 ragge * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 1.1 ragge * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 1.1 ragge * SUCH DAMAGE.
69 1.1 ragge *
70 1.1 ragge * @(#)uda.c 7.32 (Berkeley) 2/13/91
71 1.1 ragge */
72 1.1 ragge
73 1.1 ragge /*
74 1.1 ragge * RA disk device driver
75 1.17 ragge * RX MSCP floppy disk device driver
76 1.72 abs * RRD MSCP CD device driver
77 1.1 ragge */
78 1.1 ragge
79 1.1 ragge /*
80 1.1 ragge * TODO
81 1.1 ragge * write bad block forwarding code
82 1.1 ragge */
83 1.30 lukem
84 1.30 lukem #include <sys/cdefs.h>
85 1.73 abs __KERNEL_RCSID(0, "$NetBSD: mscp_disk.c,v 1.73 2012/07/10 22:30:23 abs Exp $");
86 1.1 ragge
87 1.1 ragge #include <sys/param.h>
88 1.1 ragge #include <sys/buf.h>
89 1.44 he #include <sys/bufq.h>
90 1.73 abs #include <sys/cdio.h>
91 1.1 ragge #include <sys/device.h>
92 1.2 ragge #include <sys/disk.h>
93 1.1 ragge #include <sys/disklabel.h>
94 1.2 ragge #include <sys/ioctl.h>
95 1.1 ragge #include <sys/stat.h>
96 1.2 ragge #include <sys/fcntl.h>
97 1.17 ragge #include <sys/reboot.h>
98 1.2 ragge #include <sys/proc.h>
99 1.2 ragge #include <sys/systm.h>
100 1.33 gehenna #include <sys/conf.h>
101 1.17 ragge
102 1.18 ragge #include <ufs/ufs/dinode.h>
103 1.17 ragge #include <ufs/ffs/fs.h>
104 1.10 ragge
105 1.58 ad #include <sys/bus.h>
106 1.58 ad #include <sys/cpu.h>
107 1.1 ragge
108 1.21 ragge #include <dev/mscp/mscp.h>
109 1.21 ragge #include <dev/mscp/mscpreg.h>
110 1.21 ragge #include <dev/mscp/mscpvar.h>
111 1.1 ragge
112 1.14 jtk #include "locators.h"
113 1.17 ragge #include "ioconf.h"
114 1.17 ragge #include "ra.h"
115 1.17 ragge
116 1.1 ragge /*
117 1.1 ragge * Drive status, per drive
118 1.1 ragge */
119 1.1 ragge struct ra_softc {
120 1.1 ragge struct device ra_dev; /* Autoconf struct */
121 1.1 ragge struct disk ra_disk;
122 1.1 ragge int ra_state; /* open/closed state */
123 1.1 ragge u_long ra_mediaid; /* media id */
124 1.1 ragge int ra_hwunit; /* Hardware unit number */
125 1.1 ragge int ra_havelabel; /* true if we have a label */
126 1.1 ragge int ra_wlabel; /* label sector is currently writable */
127 1.1 ragge };
128 1.1 ragge
129 1.17 ragge #define rx_softc ra_softc
130 1.72 abs #define racd_softc ra_softc
131 1.17 ragge
132 1.72 abs void raattach(device_t, device_t, void *);
133 1.46 perry int rx_putonline(struct rx_softc *);
134 1.46 perry void rrmakelabel(struct disklabel *, long);
135 1.72 abs int ra_putonline(dev_t, struct ra_softc *);
136 1.72 abs static inline struct ra_softc *mscp_device_lookup(dev_t);
137 1.17 ragge
138 1.17 ragge #if NRA
139 1.17 ragge
140 1.70 cegger int ramatch(device_t, cfdata_t, void *);
141 1.2 ragge
142 1.35 thorpej CFATTACH_DECL(ra, sizeof(struct ra_softc),
143 1.72 abs ramatch, raattach, NULL, NULL);
144 1.72 abs
145 1.72 abs #endif /* NRA */
146 1.72 abs
147 1.72 abs #if NRA || NRACD || NRX
148 1.15 thorpej
149 1.33 gehenna dev_type_open(raopen);
150 1.33 gehenna dev_type_close(raclose);
151 1.33 gehenna dev_type_read(raread);
152 1.33 gehenna dev_type_write(rawrite);
153 1.33 gehenna dev_type_ioctl(raioctl);
154 1.33 gehenna dev_type_strategy(rastrategy);
155 1.33 gehenna dev_type_dump(radump);
156 1.33 gehenna dev_type_size(rasize);
157 1.33 gehenna
158 1.72 abs #if NRA
159 1.72 abs
160 1.33 gehenna const struct bdevsw ra_bdevsw = {
161 1.33 gehenna raopen, raclose, rastrategy, raioctl, radump, rasize, D_DISK
162 1.33 gehenna };
163 1.33 gehenna
164 1.33 gehenna const struct cdevsw ra_cdevsw = {
165 1.33 gehenna raopen, raclose, raread, rawrite, raioctl,
166 1.37 jdolecek nostop, notty, nopoll, nommap, nokqfilter, D_DISK
167 1.33 gehenna };
168 1.33 gehenna
169 1.43 thorpej static struct dkdriver radkdriver = {
170 1.43 thorpej rastrategy, minphys
171 1.43 thorpej };
172 1.43 thorpej
173 1.1 ragge /*
174 1.1 ragge * More driver definitions, for generic MSCP code.
175 1.1 ragge */
176 1.1 ragge
177 1.1 ragge int
178 1.70 cegger ramatch(device_t parent, cfdata_t cf, void *aux)
179 1.1 ragge {
180 1.2 ragge struct drive_attach_args *da = aux;
181 1.2 ragge struct mscp *mp = da->da_mp;
182 1.1 ragge
183 1.2 ragge if ((da->da_typ & MSCPBUS_DISK) == 0)
184 1.2 ragge return 0;
185 1.14 jtk if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
186 1.14 jtk cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
187 1.1 ragge return 0;
188 1.17 ragge /*
189 1.72 abs * Check if this disk is a floppy (RX) or cd (RRD)
190 1.17 ragge * Seems to be a safe way to test it per Chris Torek.
191 1.17 ragge */
192 1.17 ragge if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
193 1.17 ragge return 0;
194 1.72 abs if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'R' - '@')
195 1.72 abs return 0;
196 1.1 ragge return 1;
197 1.1 ragge }
198 1.1 ragge
199 1.72 abs #endif /* NRA */
200 1.17 ragge
201 1.1 ragge /*
202 1.1 ragge * Open a drive.
203 1.1 ragge */
204 1.1 ragge /*ARGSUSED*/
205 1.1 ragge int
206 1.65 dsl raopen(dev_t dev, int flag, int fmt, struct lwp *l)
207 1.1 ragge {
208 1.72 abs struct ra_softc *ra = mscp_device_lookup(dev);
209 1.72 abs int error, part, mask;
210 1.1 ragge /*
211 1.1 ragge * Make sure this is a reasonable open request.
212 1.1 ragge */
213 1.60 drochner if (!ra)
214 1.1 ragge return ENXIO;
215 1.1 ragge
216 1.43 thorpej part = DISKPART(dev);
217 1.43 thorpej
218 1.55 ad mutex_enter(&ra->ra_disk.dk_openlock);
219 1.43 thorpej
220 1.43 thorpej /*
221 1.43 thorpej * If there are wedges, and this is not RAW_PART, then we
222 1.43 thorpej * need to fail.
223 1.43 thorpej */
224 1.43 thorpej if (ra->ra_disk.dk_nwedges != 0 && part != RAW_PART) {
225 1.43 thorpej error = EBUSY;
226 1.43 thorpej goto bad1;
227 1.43 thorpej }
228 1.43 thorpej
229 1.1 ragge /*
230 1.1 ragge * If this is the first open; we must first try to put
231 1.1 ragge * the disk online (and read the label).
232 1.1 ragge */
233 1.43 thorpej if (ra->ra_state == DK_CLOSED) {
234 1.72 abs if (ra_putonline(dev, ra) == MSCP_FAILED) {
235 1.43 thorpej error = ENXIO;
236 1.43 thorpej goto bad1;
237 1.43 thorpej }
238 1.43 thorpej }
239 1.1 ragge
240 1.11 ragge /* If the disk has no label; allow writing everywhere */
241 1.11 ragge if (ra->ra_havelabel == 0)
242 1.11 ragge ra->ra_wlabel = 1;
243 1.11 ragge
244 1.43 thorpej if (part >= ra->ra_disk.dk_label->d_npartitions) {
245 1.43 thorpej error = ENXIO;
246 1.43 thorpej goto bad1;
247 1.43 thorpej }
248 1.1 ragge
249 1.1 ragge /*
250 1.1 ragge * Wait for the state to settle
251 1.1 ragge */
252 1.1 ragge #if notyet
253 1.17 ragge while (ra->ra_state != DK_OPEN)
254 1.54 christos if ((error = tsleep((void *)ra, (PZERO + 1) | PCATCH,
255 1.1 ragge devopn, 0))) {
256 1.1 ragge splx(s);
257 1.1 ragge return (error);
258 1.1 ragge }
259 1.1 ragge #endif
260 1.1 ragge
261 1.1 ragge mask = 1 << part;
262 1.1 ragge
263 1.1 ragge switch (fmt) {
264 1.1 ragge case S_IFCHR:
265 1.1 ragge ra->ra_disk.dk_copenmask |= mask;
266 1.1 ragge break;
267 1.1 ragge case S_IFBLK:
268 1.1 ragge ra->ra_disk.dk_bopenmask |= mask;
269 1.1 ragge break;
270 1.1 ragge }
271 1.1 ragge ra->ra_disk.dk_openmask |= mask;
272 1.55 ad error = 0;
273 1.43 thorpej bad1:
274 1.55 ad mutex_exit(&ra->ra_disk.dk_openlock);
275 1.43 thorpej return (error);
276 1.1 ragge }
277 1.1 ragge
278 1.1 ragge /* ARGSUSED */
279 1.1 ragge int
280 1.65 dsl raclose(dev_t dev, int flags, int fmt, struct lwp *l)
281 1.1 ragge {
282 1.72 abs struct ra_softc *ra = mscp_device_lookup(dev);
283 1.55 ad int mask = (1 << DISKPART(dev));
284 1.43 thorpej
285 1.55 ad mutex_enter(&ra->ra_disk.dk_openlock);
286 1.1 ragge
287 1.1 ragge switch (fmt) {
288 1.1 ragge case S_IFCHR:
289 1.1 ragge ra->ra_disk.dk_copenmask &= ~mask;
290 1.1 ragge break;
291 1.1 ragge case S_IFBLK:
292 1.1 ragge ra->ra_disk.dk_bopenmask &= ~mask;
293 1.1 ragge break;
294 1.1 ragge }
295 1.1 ragge ra->ra_disk.dk_openmask =
296 1.1 ragge ra->ra_disk.dk_copenmask | ra->ra_disk.dk_bopenmask;
297 1.1 ragge
298 1.1 ragge /*
299 1.1 ragge * Should wait for I/O to complete on this partition even if
300 1.1 ragge * others are open, but wait for work on blkflush().
301 1.1 ragge */
302 1.11 ragge #if notyet
303 1.1 ragge if (ra->ra_openpart == 0) {
304 1.29 thorpej s = spluba();
305 1.62 yamt while (bufq_peek(udautab[unit]) != NULL)
306 1.25 thorpej (void) tsleep(&udautab[unit], PZERO - 1,
307 1.25 thorpej "raclose", 0);
308 1.1 ragge splx(s);
309 1.73 abs ra->ra_state = DK_CLOSED;
310 1.1 ragge ra->ra_wlabel = 0;
311 1.1 ragge }
312 1.1 ragge #endif
313 1.55 ad mutex_exit(&ra->ra_disk.dk_openlock);
314 1.1 ragge return (0);
315 1.1 ragge }
316 1.1 ragge
317 1.1 ragge /*
318 1.1 ragge * Queue a transfer request, and if possible, hand it to the controller.
319 1.1 ragge */
320 1.1 ragge void
321 1.64 dsl rastrategy(struct buf *bp)
322 1.1 ragge {
323 1.72 abs struct ra_softc *ra = mscp_device_lookup(bp->b_dev);
324 1.23 augustss int unit;
325 1.32 ragge int b;
326 1.32 ragge
327 1.1 ragge /*
328 1.1 ragge * Make sure this is a reasonable drive to use.
329 1.1 ragge */
330 1.17 ragge unit = DISKUNIT(bp->b_dev);
331 1.72 abs if (ra == NULL) {
332 1.1 ragge bp->b_error = ENXIO;
333 1.11 ragge goto done;
334 1.1 ragge }
335 1.1 ragge /*
336 1.1 ragge * If drive is open `raw' or reading label, let it at it.
337 1.1 ragge */
338 1.17 ragge if (ra->ra_state == DK_RDLABEL) {
339 1.32 ragge /* Make some statistics... /bqt */
340 1.32 ragge b = splbio();
341 1.32 ragge disk_busy(&ra->ra_disk);
342 1.32 ragge splx(b);
343 1.50 thorpej mscp_strategy(bp, device_parent(&ra->ra_dev));
344 1.1 ragge return;
345 1.1 ragge }
346 1.17 ragge
347 1.17 ragge /* If disk is not online, try to put it online */
348 1.17 ragge if (ra->ra_state == DK_CLOSED)
349 1.72 abs if (ra_putonline(bp->b_dev, ra) == MSCP_FAILED) {
350 1.17 ragge bp->b_error = EIO;
351 1.17 ragge goto done;
352 1.17 ragge }
353 1.1 ragge
354 1.1 ragge /*
355 1.1 ragge * Determine the size of the transfer, and make sure it is
356 1.1 ragge * within the boundaries of the partition.
357 1.1 ragge */
358 1.41 thorpej if (bounds_check_with_label(&ra->ra_disk, bp, ra->ra_wlabel) <= 0)
359 1.17 ragge goto done;
360 1.1 ragge
361 1.12 ragge /* Make some statistics... /bqt */
362 1.32 ragge b = splbio();
363 1.32 ragge disk_busy(&ra->ra_disk);
364 1.32 ragge splx(b);
365 1.50 thorpej mscp_strategy(bp, device_parent(&ra->ra_dev));
366 1.1 ragge return;
367 1.1 ragge
368 1.7 ragge done:
369 1.1 ragge biodone(bp);
370 1.1 ragge }
371 1.1 ragge
372 1.1 ragge int
373 1.64 dsl raread(dev_t dev, struct uio *uio, int flags)
374 1.1 ragge {
375 1.1 ragge
376 1.17 ragge return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
377 1.1 ragge }
378 1.1 ragge
379 1.1 ragge int
380 1.64 dsl rawrite(dev_t dev, struct uio *uio, int flags)
381 1.1 ragge {
382 1.1 ragge
383 1.17 ragge return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
384 1.1 ragge }
385 1.1 ragge
386 1.1 ragge /*
387 1.1 ragge * I/O controls.
388 1.1 ragge */
389 1.1 ragge int
390 1.64 dsl raioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
391 1.1 ragge {
392 1.23 augustss struct disklabel *lp, *tp;
393 1.72 abs struct ra_softc *ra = mscp_device_lookup(dev);
394 1.1 ragge int error = 0;
395 1.26 fvdl #ifdef __HAVE_OLD_DISKLABEL
396 1.26 fvdl struct disklabel newlabel;
397 1.26 fvdl #endif
398 1.1 ragge
399 1.1 ragge lp = ra->ra_disk.dk_label;
400 1.1 ragge
401 1.1 ragge switch (cmd) {
402 1.1 ragge
403 1.1 ragge case DIOCGDINFO:
404 1.68 tsutsui memcpy(data, lp, sizeof (struct disklabel));
405 1.1 ragge break;
406 1.26 fvdl #ifdef __HAVE_OLD_DISKLABEL
407 1.26 fvdl case ODIOCGDINFO:
408 1.71 tsutsui memcpy(&newlabel, lp, sizeof newlabel);
409 1.26 fvdl if (newlabel.d_npartitions > OLDMAXPARTITIONS)
410 1.27 fvdl return ENOTTY;
411 1.68 tsutsui memcpy(data, &newlabel, sizeof (struct olddisklabel));
412 1.26 fvdl break;
413 1.26 fvdl #endif
414 1.1 ragge
415 1.1 ragge case DIOCGPART:
416 1.1 ragge ((struct partinfo *)data)->disklab = lp;
417 1.1 ragge ((struct partinfo *)data)->part =
418 1.17 ragge &lp->d_partitions[DISKPART(dev)];
419 1.1 ragge break;
420 1.1 ragge
421 1.11 ragge case DIOCWDINFO:
422 1.1 ragge case DIOCSDINFO:
423 1.26 fvdl #ifdef __HAVE_OLD_DISKLABEL
424 1.26 fvdl case ODIOCWDINFO:
425 1.26 fvdl case ODIOCSDINFO:
426 1.71 tsutsui if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
427 1.26 fvdl memset(&newlabel, 0, sizeof newlabel);
428 1.26 fvdl memcpy(&newlabel, data, sizeof (struct olddisklabel));
429 1.26 fvdl tp = &newlabel;
430 1.26 fvdl } else
431 1.26 fvdl #endif
432 1.26 fvdl tp = (struct disklabel *)data;
433 1.26 fvdl
434 1.1 ragge if ((flag & FWRITE) == 0)
435 1.1 ragge error = EBADF;
436 1.11 ragge else {
437 1.55 ad mutex_enter(&ra->ra_disk.dk_openlock);
438 1.26 fvdl error = setdisklabel(lp, tp, 0, 0);
439 1.26 fvdl if ((error == 0) && (cmd == DIOCWDINFO
440 1.26 fvdl #ifdef __HAVE_OLD_DISKLABEL
441 1.26 fvdl || cmd == ODIOCWDINFO
442 1.71 tsutsui #endif
443 1.26 fvdl )) {
444 1.11 ragge ra->ra_wlabel = 1;
445 1.11 ragge error = writedisklabel(dev, rastrategy, lp,0);
446 1.11 ragge ra->ra_wlabel = 0;
447 1.11 ragge }
448 1.55 ad mutex_exit(&ra->ra_disk.dk_openlock);
449 1.11 ragge }
450 1.1 ragge break;
451 1.1 ragge
452 1.1 ragge case DIOCWLABEL:
453 1.1 ragge if ((flag & FWRITE) == 0)
454 1.1 ragge error = EBADF;
455 1.1 ragge else
456 1.1 ragge ra->ra_wlabel = 1;
457 1.1 ragge break;
458 1.1 ragge
459 1.17 ragge case DIOCGDEFLABEL:
460 1.26 fvdl #ifdef __HAVE_OLD_DISKLABEL
461 1.26 fvdl case ODIOCGDEFLABEL:
462 1.26 fvdl if (cmd == ODIOCGDEFLABEL)
463 1.26 fvdl tp = &newlabel;
464 1.26 fvdl else
465 1.73 abs #endif
466 1.18 ragge tp = (struct disklabel *)data;
467 1.66 cegger memset(tp, 0, sizeof(struct disklabel));
468 1.18 ragge tp->d_secsize = lp->d_secsize;
469 1.18 ragge tp->d_nsectors = lp->d_nsectors;
470 1.18 ragge tp->d_ntracks = lp->d_ntracks;
471 1.18 ragge tp->d_ncylinders = lp->d_ncylinders;
472 1.18 ragge tp->d_secpercyl = lp->d_secpercyl;
473 1.18 ragge tp->d_secperunit = lp->d_secperunit;
474 1.18 ragge tp->d_type = DTYPE_MSCP;
475 1.18 ragge tp->d_rpm = 3600;
476 1.18 ragge rrmakelabel(tp, ra->ra_mediaid);
477 1.26 fvdl #ifdef __HAVE_OLD_DISKLABEL
478 1.26 fvdl if (cmd == ODIOCGDEFLABEL) {
479 1.26 fvdl if (tp->d_npartitions > OLDMAXPARTITIONS)
480 1.27 fvdl return ENOTTY;
481 1.26 fvdl memcpy(data, tp, sizeof (struct olddisklabel));
482 1.26 fvdl }
483 1.26 fvdl #endif
484 1.18 ragge break;
485 1.18 ragge
486 1.43 thorpej case DIOCAWEDGE:
487 1.43 thorpej {
488 1.43 thorpej struct dkwedge_info *dkw = (void *) data;
489 1.43 thorpej
490 1.43 thorpej if ((flag & FWRITE) == 0)
491 1.43 thorpej return (EBADF);
492 1.43 thorpej
493 1.43 thorpej /* If the ioctl happens here, the parent is us. */
494 1.59 cegger strlcpy(dkw->dkw_parent, device_xname(&ra->ra_dev),
495 1.59 cegger sizeof(dkw->dkw_parent));
496 1.43 thorpej return (dkwedge_add(dkw));
497 1.43 thorpej }
498 1.47 perry
499 1.43 thorpej case DIOCDWEDGE:
500 1.43 thorpej {
501 1.43 thorpej struct dkwedge_info *dkw = (void *) data;
502 1.43 thorpej
503 1.43 thorpej if ((flag & FWRITE) == 0)
504 1.43 thorpej return (EBADF);
505 1.43 thorpej
506 1.43 thorpej /* If the ioctl happens here, the parent is us. */
507 1.59 cegger strlcpy(dkw->dkw_parent, device_xname(&ra->ra_dev),
508 1.59 cegger sizeof(dkw->dkw_parent));
509 1.43 thorpej return (dkwedge_del(dkw));
510 1.43 thorpej }
511 1.47 perry
512 1.43 thorpej case DIOCLWEDGES:
513 1.43 thorpej {
514 1.43 thorpej struct dkwedge_list *dkwl = (void *) data;
515 1.43 thorpej
516 1.49 christos return (dkwedge_list(&ra->ra_disk, dkwl, l));
517 1.43 thorpej }
518 1.43 thorpej
519 1.73 abs case DIOCTUR:
520 1.73 abs /* test unit ready */
521 1.73 abs if (ra->ra_state == DK_CLOSED &&
522 1.73 abs ra_putonline(dev, ra) == MSCP_FAILED)
523 1.73 abs error = ENXIO;
524 1.73 abs *((int*)data) = (ra->ra_state == DK_OPEN);
525 1.73 abs return error;
526 1.73 abs
527 1.1 ragge default:
528 1.1 ragge error = ENOTTY;
529 1.1 ragge break;
530 1.1 ragge }
531 1.73 abs return error;
532 1.1 ragge }
533 1.1 ragge
534 1.1 ragge int
535 1.64 dsl radump(dev_t dev, daddr_t blkno, void *va, size_t size)
536 1.1 ragge {
537 1.17 ragge return ENXIO;
538 1.1 ragge }
539 1.1 ragge
540 1.1 ragge /*
541 1.1 ragge * Return the size of a partition, if known, or -1 if not.
542 1.1 ragge */
543 1.1 ragge int
544 1.64 dsl rasize(dev_t dev)
545 1.1 ragge {
546 1.72 abs struct ra_softc *ra = mscp_device_lookup(dev);
547 1.1 ragge
548 1.60 drochner if (!ra)
549 1.1 ragge return -1;
550 1.1 ragge
551 1.17 ragge if (ra->ra_state == DK_CLOSED)
552 1.72 abs if (ra_putonline(dev, ra) == MSCP_FAILED)
553 1.17 ragge return -1;
554 1.1 ragge
555 1.17 ragge return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
556 1.13 thorpej (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE);
557 1.17 ragge }
558 1.17 ragge
559 1.72 abs #endif /* NRA || NRACD || NRX */
560 1.17 ragge
561 1.17 ragge #if NRX
562 1.17 ragge
563 1.70 cegger int rxmatch(device_t, cfdata_t, void *);
564 1.17 ragge
565 1.35 thorpej CFATTACH_DECL(rx, sizeof(struct rx_softc),
566 1.72 abs rxmatch, raattach, NULL, NULL);
567 1.17 ragge
568 1.33 gehenna dev_type_open(rxopen);
569 1.33 gehenna dev_type_read(rxread);
570 1.33 gehenna dev_type_write(rxwrite);
571 1.33 gehenna dev_type_ioctl(rxioctl);
572 1.33 gehenna dev_type_strategy(rxstrategy);
573 1.72 abs dev_type_dump(radump);
574 1.33 gehenna dev_type_size(rxsize);
575 1.33 gehenna
576 1.33 gehenna const struct bdevsw rx_bdevsw = {
577 1.72 abs rxopen, nullclose, rxstrategy, rxioctl, radump, rxsize, D_DISK
578 1.33 gehenna };
579 1.33 gehenna
580 1.33 gehenna const struct cdevsw rx_cdevsw = {
581 1.33 gehenna rxopen, nullclose, rxread, rxwrite, rxioctl,
582 1.37 jdolecek nostop, notty, nopoll, nommap, nokqfilter, D_DISK
583 1.33 gehenna };
584 1.33 gehenna
585 1.43 thorpej static struct dkdriver rxdkdriver = {
586 1.43 thorpej rxstrategy, minphys
587 1.43 thorpej };
588 1.43 thorpej
589 1.17 ragge /*
590 1.17 ragge * More driver definitions, for generic MSCP code.
591 1.17 ragge */
592 1.17 ragge
593 1.17 ragge int
594 1.70 cegger rxmatch(device_t parent, cfdata_t cf, void *aux)
595 1.17 ragge {
596 1.17 ragge struct drive_attach_args *da = aux;
597 1.17 ragge struct mscp *mp = da->da_mp;
598 1.17 ragge
599 1.17 ragge if ((da->da_typ & MSCPBUS_DISK) == 0)
600 1.17 ragge return 0;
601 1.17 ragge if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
602 1.17 ragge cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
603 1.17 ragge return 0;
604 1.17 ragge /*
605 1.72 abs * Check if this disk is a floppy (RX)
606 1.17 ragge * Seems to be a safe way to test it per Chris Torek.
607 1.17 ragge */
608 1.17 ragge if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
609 1.17 ragge return 1;
610 1.17 ragge return 0;
611 1.17 ragge }
612 1.17 ragge
613 1.17 ragge #endif /* NRX */
614 1.17 ragge
615 1.72 abs #if NRACD
616 1.72 abs
617 1.72 abs /* Use almost all ra* routines for racd */
618 1.72 abs
619 1.72 abs int racdmatch(device_t, cfdata_t, void *);
620 1.72 abs
621 1.72 abs CFATTACH_DECL(racd, sizeof(struct racd_softc),
622 1.72 abs racdmatch, raattach, NULL, NULL);
623 1.72 abs
624 1.72 abs dev_type_open(raopen);
625 1.72 abs dev_type_read(raread);
626 1.72 abs dev_type_write(rawrite);
627 1.72 abs dev_type_ioctl(raioctl);
628 1.72 abs dev_type_strategy(rastrategy);
629 1.72 abs dev_type_dump(radump);
630 1.72 abs dev_type_size(rasize);
631 1.72 abs
632 1.72 abs const struct bdevsw racd_bdevsw = {
633 1.72 abs raopen, nullclose, rastrategy, raioctl, radump, rasize, D_DISK
634 1.72 abs };
635 1.72 abs
636 1.72 abs const struct cdevsw racd_cdevsw = {
637 1.72 abs raopen, nullclose, raread, rawrite, raioctl,
638 1.72 abs nostop, notty, nopoll, nommap, nokqfilter, D_DISK
639 1.72 abs };
640 1.72 abs
641 1.72 abs static struct dkdriver racddkdriver = {
642 1.72 abs rastrategy, minphys
643 1.72 abs };
644 1.72 abs
645 1.72 abs /*
646 1.72 abs * More driver definitions, for generic MSCP code.
647 1.72 abs */
648 1.72 abs
649 1.72 abs int
650 1.72 abs racdmatch(device_t parent, cfdata_t cf, void *aux)
651 1.72 abs {
652 1.72 abs struct drive_attach_args *da = aux;
653 1.72 abs struct mscp *mp = da->da_mp;
654 1.72 abs
655 1.72 abs if ((da->da_typ & MSCPBUS_DISK) == 0)
656 1.72 abs return 0;
657 1.72 abs if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
658 1.72 abs cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
659 1.72 abs return 0;
660 1.72 abs /*
661 1.72 abs * Check if this disk is a CD (RRD)
662 1.72 abs */
663 1.72 abs if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'R' - '@')
664 1.72 abs return 1;
665 1.72 abs return 0;
666 1.72 abs }
667 1.72 abs
668 1.72 abs #endif /* NRACD */
669 1.72 abs
670 1.17 ragge /*
671 1.17 ragge * The attach routine only checks and prints drive type.
672 1.17 ragge * Bringing the disk online is done when the disk is accessed
673 1.47 perry * the first time.
674 1.17 ragge */
675 1.17 ragge void
676 1.72 abs raattach(device_t parent, device_t self, void *aux)
677 1.17 ragge {
678 1.53 thorpej struct rx_softc *rx = device_private(self);
679 1.17 ragge struct drive_attach_args *da = aux;
680 1.17 ragge struct mscp *mp = da->da_mp;
681 1.17 ragge struct mscp_softc *mi = (void *)parent;
682 1.17 ragge struct disklabel *dl;
683 1.17 ragge
684 1.17 ragge rx->ra_mediaid = mp->mscp_guse.guse_mediaid;
685 1.17 ragge rx->ra_state = DK_CLOSED;
686 1.17 ragge rx->ra_hwunit = mp->mscp_unit;
687 1.17 ragge mi->mi_dp[mp->mscp_unit] = self;
688 1.17 ragge
689 1.43 thorpej #if NRX
690 1.43 thorpej if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
691 1.59 cegger disk_init((struct disk *)&rx->ra_disk, device_xname(&rx->ra_dev),
692 1.57 ad &rxdkdriver);
693 1.43 thorpej #endif
694 1.72 abs #if NRACD
695 1.72 abs if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'R' - '@')
696 1.72 abs disk_init((struct disk *)&rx->ra_disk, device_xname(&rx->ra_dev),
697 1.72 abs &racddkdriver);
698 1.72 abs #endif
699 1.43 thorpej #if NRA
700 1.72 abs if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) != 'X' - '@' &&
701 1.72 abs MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) != 'R' - '@')
702 1.59 cegger disk_init((struct disk *)&rx->ra_disk, device_xname(&rx->ra_dev),
703 1.57 ad &radkdriver);
704 1.43 thorpej #endif
705 1.17 ragge disk_attach((struct disk *)&rx->ra_disk);
706 1.17 ragge
707 1.17 ragge /* Fill in what we know. The actual size is gotten later */
708 1.17 ragge dl = rx->ra_disk.dk_label;
709 1.17 ragge
710 1.17 ragge dl->d_secsize = DEV_BSIZE;
711 1.17 ragge dl->d_nsectors = mp->mscp_guse.guse_nspt;
712 1.19 ragge dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group;
713 1.17 ragge dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
714 1.17 ragge disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
715 1.19 ragge #ifdef DEBUG
716 1.19 ragge printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n",
717 1.59 cegger device_xname(self), mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group,
718 1.19 ragge mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize,
719 1.19 ragge mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct);
720 1.19 ragge #endif
721 1.43 thorpej if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) != 'X' - '@') {
722 1.43 thorpej /*
723 1.43 thorpej * XXX We should try to discover wedges here, but
724 1.43 thorpej * XXX that would mean being able to do I/O. Should
725 1.43 thorpej * XXX use config_defer() here.
726 1.43 thorpej */
727 1.43 thorpej }
728 1.17 ragge }
729 1.17 ragge
730 1.47 perry /*
731 1.17 ragge * (Try to) put the drive online. This is done the first time the
732 1.17 ragge * drive is opened, or if it har fallen offline.
733 1.17 ragge */
734 1.17 ragge int
735 1.64 dsl rx_putonline(struct rx_softc *rx)
736 1.17 ragge {
737 1.17 ragge struct mscp *mp;
738 1.50 thorpej struct mscp_softc *mi =
739 1.50 thorpej (struct mscp_softc *)device_parent(&rx->ra_dev);
740 1.17 ragge volatile int i;
741 1.17 ragge
742 1.17 ragge rx->ra_state = DK_CLOSED;
743 1.17 ragge mp = mscp_getcp(mi, MSCP_WAIT);
744 1.17 ragge mp->mscp_opcode = M_OP_ONLINE;
745 1.17 ragge mp->mscp_unit = rx->ra_hwunit;
746 1.17 ragge mp->mscp_cmdref = 1;
747 1.17 ragge *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
748 1.17 ragge
749 1.17 ragge /* Poll away */
750 1.21 ragge i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
751 1.52 thorpej if (tsleep(&rx->ra_state, PRIBIO, "rxonline", 100*100))
752 1.17 ragge rx->ra_state = DK_CLOSED;
753 1.17 ragge
754 1.17 ragge if (rx->ra_state == DK_CLOSED)
755 1.17 ragge return MSCP_FAILED;
756 1.17 ragge
757 1.17 ragge return MSCP_DONE;
758 1.17 ragge }
759 1.17 ragge
760 1.73 abs
761 1.17 ragge #if NRX
762 1.17 ragge
763 1.17 ragge /*
764 1.17 ragge * Open a drive.
765 1.17 ragge */
766 1.17 ragge /*ARGSUSED*/
767 1.17 ragge int
768 1.65 dsl rxopen(dev_t dev, int flag, int fmt, struct lwp *l)
769 1.17 ragge {
770 1.23 augustss struct rx_softc *rx;
771 1.17 ragge int unit;
772 1.17 ragge
773 1.17 ragge /*
774 1.17 ragge * Make sure this is a reasonable open request.
775 1.17 ragge */
776 1.17 ragge unit = DISKUNIT(dev);
777 1.60 drochner rx = device_lookup_private(&rx_cd, unit);
778 1.60 drochner if (!rx)
779 1.17 ragge return ENXIO;
780 1.17 ragge
781 1.17 ragge /*
782 1.17 ragge * If this is the first open; we must first try to put
783 1.17 ragge * the disk online (and read the label).
784 1.17 ragge */
785 1.17 ragge if (rx->ra_state == DK_CLOSED)
786 1.17 ragge if (rx_putonline(rx) == MSCP_FAILED)
787 1.17 ragge return ENXIO;
788 1.17 ragge
789 1.17 ragge return 0;
790 1.17 ragge }
791 1.17 ragge
792 1.17 ragge /*
793 1.17 ragge * Queue a transfer request, and if possible, hand it to the controller.
794 1.17 ragge *
795 1.17 ragge * This routine is broken into two so that the internal version
796 1.17 ragge * udastrat1() can be called by the (nonexistent, as yet) bad block
797 1.17 ragge * revectoring routine.
798 1.17 ragge */
799 1.17 ragge void
800 1.64 dsl rxstrategy(struct buf *bp)
801 1.17 ragge {
802 1.23 augustss int unit;
803 1.23 augustss struct rx_softc *rx;
804 1.32 ragge int b;
805 1.17 ragge
806 1.17 ragge /*
807 1.17 ragge * Make sure this is a reasonable drive to use.
808 1.17 ragge */
809 1.17 ragge unit = DISKUNIT(bp->b_dev);
810 1.60 drochner if ((rx = device_lookup_private(&rx_cd, unit)) == NULL) {
811 1.17 ragge bp->b_error = ENXIO;
812 1.17 ragge goto done;
813 1.17 ragge }
814 1.17 ragge
815 1.17 ragge /* If disk is not online, try to put it online */
816 1.17 ragge if (rx->ra_state == DK_CLOSED)
817 1.17 ragge if (rx_putonline(rx) == MSCP_FAILED) {
818 1.17 ragge bp->b_error = EIO;
819 1.17 ragge goto done;
820 1.17 ragge }
821 1.17 ragge
822 1.17 ragge /*
823 1.17 ragge * Determine the size of the transfer, and make sure it is
824 1.17 ragge * within the boundaries of the partition.
825 1.17 ragge */
826 1.17 ragge if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) {
827 1.17 ragge bp->b_resid = bp->b_bcount;
828 1.17 ragge goto done;
829 1.17 ragge }
830 1.17 ragge
831 1.17 ragge /* Make some statistics... /bqt */
832 1.32 ragge b = splbio();
833 1.32 ragge disk_busy(&rx->ra_disk);
834 1.32 ragge splx(b);
835 1.50 thorpej mscp_strategy(bp, device_parent(&rx->ra_dev));
836 1.17 ragge return;
837 1.17 ragge
838 1.17 ragge done:
839 1.17 ragge biodone(bp);
840 1.17 ragge }
841 1.17 ragge
842 1.17 ragge int
843 1.64 dsl rxread(dev_t dev, struct uio *uio, int flag)
844 1.17 ragge {
845 1.17 ragge
846 1.17 ragge return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio));
847 1.17 ragge }
848 1.17 ragge
849 1.17 ragge int
850 1.64 dsl rxwrite(dev_t dev, struct uio *uio, int flag)
851 1.17 ragge {
852 1.17 ragge
853 1.17 ragge return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio));
854 1.17 ragge }
855 1.17 ragge
856 1.17 ragge /*
857 1.17 ragge * I/O controls.
858 1.17 ragge */
859 1.17 ragge int
860 1.64 dsl rxioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
861 1.17 ragge {
862 1.23 augustss int unit = DISKUNIT(dev);
863 1.23 augustss struct disklabel *lp;
864 1.60 drochner struct rx_softc *rx = device_lookup_private(&rx_cd, unit);
865 1.17 ragge int error = 0;
866 1.17 ragge
867 1.17 ragge lp = rx->ra_disk.dk_label;
868 1.17 ragge
869 1.17 ragge switch (cmd) {
870 1.17 ragge
871 1.17 ragge case DIOCGDINFO:
872 1.68 tsutsui memcpy(data, lp, sizeof (struct disklabel));
873 1.17 ragge break;
874 1.17 ragge
875 1.17 ragge case DIOCGPART:
876 1.17 ragge ((struct partinfo *)data)->disklab = lp;
877 1.17 ragge ((struct partinfo *)data)->part =
878 1.17 ragge &lp->d_partitions[DISKPART(dev)];
879 1.17 ragge break;
880 1.17 ragge
881 1.17 ragge
882 1.17 ragge case DIOCWDINFO:
883 1.17 ragge case DIOCSDINFO:
884 1.17 ragge case DIOCWLABEL:
885 1.17 ragge break;
886 1.17 ragge
887 1.17 ragge default:
888 1.17 ragge error = ENOTTY;
889 1.17 ragge break;
890 1.17 ragge }
891 1.17 ragge return (error);
892 1.17 ragge }
893 1.17 ragge
894 1.17 ragge int
895 1.64 dsl rxsize(dev_t dev)
896 1.17 ragge {
897 1.17 ragge
898 1.17 ragge return -1;
899 1.17 ragge }
900 1.17 ragge
901 1.17 ragge #endif /* NRX */
902 1.17 ragge
903 1.70 cegger void rrdgram(device_t, struct mscp *, struct mscp_softc *);
904 1.70 cegger void rriodone(device_t, struct buf *);
905 1.70 cegger int rronline(device_t, struct mscp *);
906 1.70 cegger int rrgotstatus(device_t, struct mscp *);
907 1.70 cegger void rrreplace(device_t, struct mscp *);
908 1.70 cegger int rrioerror(device_t, struct mscp *, struct buf *);
909 1.46 perry void rrfillin(struct buf *, struct mscp *);
910 1.70 cegger void rrbb(device_t, struct mscp *, struct buf *);
911 1.17 ragge
912 1.17 ragge
913 1.17 ragge struct mscp_device ra_device = {
914 1.17 ragge rrdgram,
915 1.17 ragge rriodone,
916 1.17 ragge rronline,
917 1.17 ragge rrgotstatus,
918 1.17 ragge rrreplace,
919 1.17 ragge rrioerror,
920 1.17 ragge rrbb,
921 1.17 ragge rrfillin,
922 1.17 ragge };
923 1.17 ragge
924 1.17 ragge /*
925 1.17 ragge * Handle an error datagram.
926 1.17 ragge * This can come from an unconfigured drive as well.
927 1.47 perry */
928 1.47 perry void
929 1.70 cegger rrdgram(device_t usc, struct mscp *mp, struct mscp_softc *mi)
930 1.47 perry {
931 1.59 cegger if (mscp_decodeerror(usc == NULL?"unconf disk" : device_xname(usc), mp, mi))
932 1.47 perry return;
933 1.17 ragge /*
934 1.17 ragge * SDI status information bytes 10 and 11 are the microprocessor
935 1.17 ragge * error code and front panel code respectively. These vary per
936 1.17 ragge * drive type and are printed purely for field service information.
937 1.17 ragge */
938 1.47 perry if (mp->mscp_format == M_FM_SDI)
939 1.17 ragge printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
940 1.17 ragge mp->mscp_erd.erd_sdistat[10],
941 1.17 ragge mp->mscp_erd.erd_sdistat[11]);
942 1.17 ragge }
943 1.17 ragge
944 1.72 abs
945 1.47 perry void
946 1.70 cegger rriodone(device_t usc, struct buf *bp)
947 1.17 ragge {
948 1.72 abs struct ra_softc *ra = device_private(usc);
949 1.32 ragge
950 1.38 mrg disk_unbusy(&ra->ra_disk, bp->b_bcount, (bp->b_flags & B_READ));
951 1.17 ragge
952 1.17 ragge biodone(bp);
953 1.17 ragge }
954 1.17 ragge
955 1.17 ragge /*
956 1.17 ragge * A drive came on line. Check its type and size. Return DONE if
957 1.17 ragge * we think the drive is truly on line. In any case, awaken anyone
958 1.17 ragge * sleeping on the drive on-line-ness.
959 1.17 ragge */
960 1.17 ragge int
961 1.70 cegger rronline(device_t usc, struct mscp *mp)
962 1.17 ragge {
963 1.72 abs struct ra_softc *ra = device_private(usc);
964 1.17 ragge struct disklabel *dl;
965 1.17 ragge
966 1.72 abs wakeup((void *)&ra->ra_state);
967 1.17 ragge if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
968 1.59 cegger aprint_error_dev(usc, "attempt to bring on line failed: ");
969 1.17 ragge mscp_printevent(mp);
970 1.17 ragge return (MSCP_FAILED);
971 1.17 ragge }
972 1.17 ragge
973 1.72 abs ra->ra_state = DK_OPEN;
974 1.47 perry
975 1.72 abs dl = ra->ra_disk.dk_label;
976 1.17 ragge dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize;
977 1.17 ragge
978 1.17 ragge if (dl->d_secpercyl) {
979 1.17 ragge dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl;
980 1.17 ragge dl->d_type = DTYPE_MSCP;
981 1.17 ragge dl->d_rpm = 3600;
982 1.17 ragge } else {
983 1.17 ragge dl->d_type = DTYPE_FLOPPY;
984 1.17 ragge dl->d_rpm = 300;
985 1.17 ragge }
986 1.72 abs rrmakelabel(dl, ra->ra_mediaid);
987 1.17 ragge
988 1.17 ragge return (MSCP_DONE);
989 1.17 ragge }
990 1.17 ragge
991 1.17 ragge void
992 1.64 dsl rrmakelabel(struct disklabel *dl, long type)
993 1.17 ragge {
994 1.17 ragge int n, p = 0;
995 1.17 ragge
996 1.17 ragge dl->d_bbsize = BBSIZE;
997 1.39 he dl->d_sbsize = SBLOCKSIZE;
998 1.17 ragge
999 1.17 ragge /* Create the disk name for disklabel. Phew... */
1000 1.17 ragge dl->d_typename[p++] = MSCP_MID_CHAR(2, type);
1001 1.17 ragge dl->d_typename[p++] = MSCP_MID_CHAR(1, type);
1002 1.17 ragge if (MSCP_MID_ECH(0, type))
1003 1.17 ragge dl->d_typename[p++] = MSCP_MID_CHAR(0, type);
1004 1.17 ragge n = MSCP_MID_NUM(type);
1005 1.17 ragge if (n > 99) {
1006 1.17 ragge dl->d_typename[p++] = '1';
1007 1.17 ragge n -= 100;
1008 1.17 ragge }
1009 1.17 ragge if (n > 9) {
1010 1.17 ragge dl->d_typename[p++] = (n / 10) + '0';
1011 1.17 ragge n %= 10;
1012 1.17 ragge }
1013 1.17 ragge dl->d_typename[p++] = n + '0';
1014 1.17 ragge dl->d_typename[p] = 0;
1015 1.17 ragge dl->d_npartitions = MAXPARTITIONS;
1016 1.17 ragge dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
1017 1.17 ragge dl->d_secperunit;
1018 1.17 ragge dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
1019 1.17 ragge dl->d_interleave = dl->d_headswitch = 1;
1020 1.17 ragge dl->d_magic = dl->d_magic2 = DISKMAGIC;
1021 1.17 ragge dl->d_checksum = dkcksum(dl);
1022 1.17 ragge }
1023 1.17 ragge
1024 1.47 perry /*
1025 1.17 ragge * We got some (configured) unit's status. Return DONE if it succeeded.
1026 1.17 ragge */
1027 1.17 ragge int
1028 1.70 cegger rrgotstatus(device_t usc, struct mscp *mp)
1029 1.47 perry {
1030 1.17 ragge if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
1031 1.59 cegger aprint_error_dev(usc, "attempt to get status failed: ");
1032 1.17 ragge mscp_printevent(mp);
1033 1.17 ragge return (MSCP_FAILED);
1034 1.17 ragge }
1035 1.17 ragge /* record for (future) bad block forwarding and whatever else */
1036 1.17 ragge #ifdef notyet
1037 1.17 ragge uda_rasave(ui->ui_unit, mp, 1);
1038 1.17 ragge #endif
1039 1.17 ragge return (MSCP_DONE);
1040 1.17 ragge }
1041 1.17 ragge
1042 1.47 perry /*
1043 1.17 ragge * A replace operation finished.
1044 1.17 ragge */
1045 1.17 ragge /*ARGSUSED*/
1046 1.47 perry void
1047 1.70 cegger rrreplace(device_t usc, struct mscp *mp)
1048 1.17 ragge {
1049 1.17 ragge
1050 1.17 ragge panic("udareplace");
1051 1.17 ragge }
1052 1.17 ragge
1053 1.17 ragge /*
1054 1.17 ragge * A transfer failed. We get a chance to fix or restart it.
1055 1.17 ragge * Need to write the bad block forwaring code first....
1056 1.17 ragge */
1057 1.17 ragge /*ARGSUSED*/
1058 1.47 perry int
1059 1.70 cegger rrioerror(device_t usc, struct mscp *mp, struct buf *bp)
1060 1.17 ragge {
1061 1.72 abs struct ra_softc *ra = device_private(usc);
1062 1.17 ragge int code = mp->mscp_event;
1063 1.17 ragge
1064 1.17 ragge switch (code & M_ST_MASK) {
1065 1.17 ragge /* The unit has fallen offline. Try to figure out why. */
1066 1.17 ragge case M_ST_OFFLINE:
1067 1.17 ragge bp->b_error = EIO;
1068 1.17 ragge ra->ra_state = DK_CLOSED;
1069 1.17 ragge if (code & M_OFFLINE_UNMOUNTED)
1070 1.59 cegger aprint_error_dev(usc, "not mounted/spun down\n");
1071 1.17 ragge if (code & M_OFFLINE_DUPLICATE)
1072 1.59 cegger aprint_error_dev(usc, "duplicate unit number!!!\n");
1073 1.17 ragge return MSCP_DONE;
1074 1.17 ragge
1075 1.17 ragge case M_ST_AVAILABLE:
1076 1.17 ragge ra->ra_state = DK_CLOSED; /* Force another online */
1077 1.17 ragge return MSCP_DONE;
1078 1.17 ragge
1079 1.17 ragge default:
1080 1.59 cegger printf("%s:", device_xname(usc));
1081 1.17 ragge break;
1082 1.17 ragge }
1083 1.17 ragge return (MSCP_FAILED);
1084 1.17 ragge }
1085 1.17 ragge
1086 1.17 ragge /*
1087 1.17 ragge * Fill in disk addresses in a mscp packet waiting for transfer.
1088 1.17 ragge */
1089 1.17 ragge void
1090 1.64 dsl rrfillin(struct buf *bp, struct mscp *mp)
1091 1.17 ragge {
1092 1.72 abs struct ra_softc *ra;
1093 1.17 ragge struct disklabel *lp;
1094 1.17 ragge int part = DISKPART(bp->b_dev);
1095 1.17 ragge
1096 1.72 abs ra = mscp_device_lookup(bp->b_dev);
1097 1.72 abs lp = ra->ra_disk.dk_label;
1098 1.17 ragge
1099 1.17 ragge mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno;
1100 1.72 abs mp->mscp_unit = ra->ra_hwunit;
1101 1.17 ragge mp->mscp_seq.seq_bytecount = bp->b_bcount;
1102 1.17 ragge }
1103 1.17 ragge
1104 1.17 ragge /*
1105 1.17 ragge * A bad block related operation finished.
1106 1.17 ragge */
1107 1.17 ragge /*ARGSUSED*/
1108 1.17 ragge void
1109 1.70 cegger rrbb(device_t usc, struct mscp *mp, struct buf *bp)
1110 1.17 ragge {
1111 1.17 ragge
1112 1.17 ragge panic("udabb");
1113 1.1 ragge }
1114 1.72 abs
1115 1.72 abs /*
1116 1.72 abs * (Try to) put the drive online. This is done the first time the
1117 1.72 abs * drive is opened, or if it has fallen offline.
1118 1.72 abs */
1119 1.72 abs int
1120 1.72 abs ra_putonline(dev_t dev, struct ra_softc *ra)
1121 1.72 abs {
1122 1.72 abs struct disklabel *dl;
1123 1.72 abs const char *msg;
1124 1.72 abs
1125 1.72 abs if (rx_putonline(ra) != MSCP_DONE)
1126 1.72 abs return MSCP_FAILED;
1127 1.72 abs
1128 1.72 abs dl = ra->ra_disk.dk_label;
1129 1.72 abs
1130 1.72 abs ra->ra_state = DK_RDLABEL;
1131 1.72 abs printf("%s", device_xname(&ra->ra_dev));
1132 1.72 abs if ((msg = readdisklabel(
1133 1.72 abs MAKEDISKDEV(major(dev), device_unit(&ra->ra_dev), RAW_PART),
1134 1.72 abs rastrategy, dl, NULL)) == NULL) {
1135 1.72 abs ra->ra_havelabel = 1;
1136 1.72 abs ra->ra_state = DK_OPEN;
1137 1.72 abs }
1138 1.72 abs #if NRACD
1139 1.72 abs else if (cdevsw_lookup(dev) == &racd_cdevsw) {
1140 1.72 abs dl->d_partitions[0].p_offset = 0;
1141 1.72 abs dl->d_partitions[0].p_size = dl->d_secperunit;
1142 1.72 abs dl->d_partitions[0].p_fstype = FS_ISO9660;
1143 1.72 abs }
1144 1.72 abs #endif /* NRACD */
1145 1.72 abs else {
1146 1.72 abs printf(": %s", msg);
1147 1.72 abs }
1148 1.72 abs
1149 1.72 abs printf(": size %d sectors\n", dl->d_secperunit);
1150 1.72 abs
1151 1.72 abs return MSCP_DONE;
1152 1.72 abs }
1153 1.72 abs
1154 1.72 abs
1155 1.72 abs static inline struct ra_softc *
1156 1.72 abs mscp_device_lookup(dev_t dev)
1157 1.72 abs {
1158 1.72 abs struct ra_softc *ra;
1159 1.72 abs int unit;
1160 1.72 abs
1161 1.72 abs unit = DISKUNIT(dev);
1162 1.72 abs #if NRA
1163 1.72 abs if (cdevsw_lookup(dev) == &ra_cdevsw)
1164 1.72 abs ra = device_lookup_private(&ra_cd, unit);
1165 1.72 abs else
1166 1.72 abs #endif
1167 1.72 abs #if NRACD
1168 1.72 abs if (cdevsw_lookup(dev) == &racd_cdevsw)
1169 1.72 abs ra = device_lookup_private(&racd_cd, unit);
1170 1.72 abs else
1171 1.72 abs #endif
1172 1.72 abs #if NRX
1173 1.72 abs if (cdevsw_lookup(dev) == &rx_cdevsw)
1174 1.72 abs ra = device_lookup_private(&rx_cd, unit);
1175 1.72 abs else
1176 1.72 abs #endif
1177 1.72 abs panic("mscp_device_lookup: unexpected major %"PRIu32" unit %u",
1178 1.72 abs major(dev), unit);
1179 1.72 abs return ra;
1180 1.72 abs }
1181