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