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