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