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