1 /* $NetBSD: rl.c,v 1.50 2015/04/26 15:15:20 mlelstv Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed at Ludd, University of 17 * Lule}, Sweden and its contributors. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * RL11/RLV11/RLV12 disk controller driver and 35 * RL01/RL02 disk device driver. 36 * 37 * TODO: 38 * Handle disk errors more gracefully 39 * Do overlapping seeks on multiple drives 40 * 41 * Implementation comments: 42 * 43 */ 44 45 #include <sys/cdefs.h> 46 __KERNEL_RCSID(0, "$NetBSD: rl.c,v 1.50 2015/04/26 15:15:20 mlelstv Exp $"); 47 48 #include <sys/param.h> 49 #include <sys/device.h> 50 #include <sys/systm.h> 51 #include <sys/conf.h> 52 #include <sys/disk.h> 53 #include <sys/disklabel.h> 54 #include <sys/buf.h> 55 #include <sys/bufq.h> 56 #include <sys/stat.h> 57 #include <sys/dkio.h> 58 #include <sys/fcntl.h> 59 #include <sys/event.h> 60 61 #include <ufs/ufs/dinode.h> 62 #include <ufs/ffs/fs.h> 63 64 #include <sys/bus.h> 65 66 #include <dev/qbus/ubavar.h> 67 #include <dev/qbus/rlreg.h> 68 #include <dev/qbus/rlvar.h> 69 70 #include "ioconf.h" 71 #include "locators.h" 72 73 static int rlcmatch(device_t, cfdata_t, void *); 74 static void rlcattach(device_t, device_t, void *); 75 static int rlcprint(void *, const char *); 76 static void rlcintr(void *); 77 static int rlmatch(device_t, cfdata_t, void *); 78 static void rlattach(device_t, device_t, void *); 79 static void rlcstart(struct rlc_softc *, struct buf *); 80 static void waitcrdy(struct rlc_softc *); 81 static void rlcreset(device_t); 82 83 CFATTACH_DECL_NEW(rlc, sizeof(struct rlc_softc), 84 rlcmatch, rlcattach, NULL, NULL); 85 86 CFATTACH_DECL_NEW(rl, sizeof(struct rl_softc), 87 rlmatch, rlattach, NULL, NULL); 88 89 static dev_type_open(rlopen); 90 static dev_type_close(rlclose); 91 static dev_type_read(rlread); 92 static dev_type_write(rlwrite); 93 static dev_type_ioctl(rlioctl); 94 static dev_type_strategy(rlstrategy); 95 static dev_type_dump(rldump); 96 static dev_type_size(rlpsize); 97 98 const struct bdevsw rl_bdevsw = { 99 .d_open = rlopen, 100 .d_close = rlclose, 101 .d_strategy = rlstrategy, 102 .d_ioctl = rlioctl, 103 .d_dump = rldump, 104 .d_psize = rlpsize, 105 .d_discard = nodiscard, 106 .d_flag = D_DISK 107 }; 108 109 const struct cdevsw rl_cdevsw = { 110 .d_open = rlopen, 111 .d_close = rlclose, 112 .d_read = rlread, 113 .d_write = rlwrite, 114 .d_ioctl = rlioctl, 115 .d_stop = nostop, 116 .d_tty = notty, 117 .d_poll = nopoll, 118 .d_mmap = nommap, 119 .d_kqfilter = nokqfilter, 120 .d_discard = nodiscard, 121 .d_flag = D_DISK 122 }; 123 124 #define MAXRLXFER (RL_BPS * RL_SPT) 125 126 #define RL_WREG(reg, val) \ 127 bus_space_write_2(sc->sc_iot, sc->sc_ioh, (reg), (val)) 128 #define RL_RREG(reg) \ 129 bus_space_read_2(sc->sc_iot, sc->sc_ioh, (reg)) 130 131 static const char * const rlstates[] = { 132 "drive not loaded", 133 "drive spinning up", 134 "drive brushes out", 135 "drive loading heads", 136 "drive seeking", 137 "drive ready", 138 "drive unloading heads", 139 "drive spun down", 140 }; 141 142 static const struct dkdriver rldkdriver = { 143 .d_strategy = rlstrategy, 144 .d_minphys = minphys 145 }; 146 147 static const char * 148 rlstate(struct rlc_softc *sc, int unit) 149 { 150 int i = 0; 151 152 do { 153 RL_WREG(RL_DA, RLDA_GS); 154 RL_WREG(RL_CS, RLCS_GS|(unit << RLCS_USHFT)); 155 waitcrdy(sc); 156 } while (((RL_RREG(RL_CS) & RLCS_ERR) != 0) && i++ < 10); 157 if (i == 10) 158 return NULL; 159 i = RL_RREG(RL_MP) & RLMP_STATUS; 160 return rlstates[i]; 161 } 162 163 void 164 waitcrdy(struct rlc_softc *sc) 165 { 166 int i; 167 168 for (i = 0; i < 1000; i++) { 169 DELAY(10000); 170 if (RL_RREG(RL_CS) & RLCS_CRDY) 171 return; 172 } 173 aprint_error_dev(sc->sc_dev, "never got ready\n"); /* ?panic? */ 174 } 175 176 int 177 rlcprint(void *aux, const char *name) 178 { 179 struct rlc_attach_args *ra = aux; 180 181 if (name) 182 aprint_normal("RL0%d at %s", 183 ra->type & RLMP_DT ? '2' : '1', name); 184 aprint_normal(" drive %d", ra->hwid); 185 return UNCONF; 186 } 187 188 /* 189 * Force the controller to interrupt. 190 */ 191 int 192 rlcmatch(device_t parent, cfdata_t cf, void *aux) 193 { 194 struct uba_attach_args *ua = aux; 195 struct rlc_softc ssc, *sc = &ssc; 196 int i; 197 198 sc->sc_iot = ua->ua_iot; 199 sc->sc_ioh = ua->ua_ioh; 200 /* Force interrupt by issuing a "Get Status" command */ 201 RL_WREG(RL_DA, RLDA_GS); 202 RL_WREG(RL_CS, RLCS_GS|RLCS_IE); 203 204 for (i = 0; i < 100; i++) { 205 DELAY(100000); 206 if (RL_RREG(RL_CS) & RLCS_CRDY) 207 return 1; 208 } 209 return 0; 210 } 211 212 void 213 rlcattach(device_t parent, device_t self, void *aux) 214 { 215 struct rlc_softc *sc = device_private(self); 216 struct uba_attach_args *ua = aux; 217 struct rlc_attach_args ra; 218 int i, error; 219 220 sc->sc_dev = self; 221 sc->sc_uh = device_private(parent); 222 sc->sc_iot = ua->ua_iot; 223 sc->sc_ioh = ua->ua_ioh; 224 sc->sc_dmat = ua->ua_dmat; 225 uba_intr_establish(ua->ua_icookie, ua->ua_cvec, 226 rlcintr, sc, &sc->sc_intrcnt); 227 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt, 228 device_xname(sc->sc_dev), "intr"); 229 uba_reset_establish(rlcreset, self); 230 231 printf("\n"); 232 233 /* 234 * The RL11 can only have one transfer going at a time, 235 * and max transfer size is one track, so only one dmamap 236 * is needed. 237 */ 238 error = bus_dmamap_create(sc->sc_dmat, MAXRLXFER, 1, MAXRLXFER, 0, 239 BUS_DMA_ALLOCNOW, &sc->sc_dmam); 240 if (error) { 241 aprint_error(": Failed to allocate DMA map, error %d\n", error); 242 return; 243 } 244 bufq_alloc(&sc->sc_q, "disksort", BUFQ_SORT_CYLINDER); 245 for (i = 0; i < RL_MAXDPC; i++) { 246 waitcrdy(sc); 247 RL_WREG(RL_DA, RLDA_GS|RLDA_RST); 248 RL_WREG(RL_CS, RLCS_GS|(i << RLCS_USHFT)); 249 waitcrdy(sc); 250 ra.type = RL_RREG(RL_MP); 251 ra.hwid = i; 252 if ((RL_RREG(RL_CS) & RLCS_ERR) == 0) 253 config_found(sc->sc_dev, &ra, rlcprint); 254 } 255 } 256 257 int 258 rlmatch(device_t parent, cfdata_t cf, void *aux) 259 { 260 struct rlc_attach_args *ra = aux; 261 262 if (cf->cf_loc[RLCCF_DRIVE] != RLCCF_DRIVE_DEFAULT && 263 cf->cf_loc[RLCCF_DRIVE] != ra->hwid) 264 return 0; 265 return 1; 266 } 267 268 void 269 rlattach(device_t parent, device_t self, void *aux) 270 { 271 struct rl_softc *rc = device_private(self); 272 struct rlc_attach_args *ra = aux; 273 struct disklabel *dl; 274 275 rc->rc_dev = self; 276 rc->rc_rlc = device_private(parent); 277 rc->rc_hwid = ra->hwid; 278 disk_init(&rc->rc_disk, device_xname(rc->rc_dev), &rldkdriver); 279 disk_attach(&rc->rc_disk); 280 dl = rc->rc_disk.dk_label; 281 dl->d_npartitions = 3; 282 strcpy(dl->d_typename, "RL01"); 283 if (ra->type & RLMP_DT) 284 dl->d_typename[3] = '2'; 285 dl->d_secsize = DEV_BSIZE; /* XXX - wrong, but OK for now */ 286 dl->d_nsectors = RL_SPT/2; 287 dl->d_ntracks = RL_SPD; 288 dl->d_ncylinders = ra->type & RLMP_DT ? RL_TPS02 : RL_TPS01; 289 dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; 290 dl->d_secperunit = dl->d_ncylinders * dl->d_secpercyl; 291 dl->d_partitions[0].p_size = dl->d_partitions[2].p_size = 292 dl->d_secperunit; 293 dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0; 294 dl->d_interleave = dl->d_headswitch = 1; 295 dl->d_bbsize = BBSIZE; 296 dl->d_sbsize = SBLOCKSIZE; 297 dl->d_rpm = 2400; 298 dl->d_type = DKTYPE_DEC; 299 printf(": %s, %s\n", dl->d_typename, rlstate(rc->rc_rlc, ra->hwid)); 300 301 /* 302 * XXX We should try to discovery wedges here, but 303 * XXX that would mean loading up the pack and being 304 * XXX able to do I/O. Should use config_defer() here. 305 */ 306 } 307 308 int 309 rlopen(dev_t dev, int flag, int fmt, struct lwp *l) 310 { 311 struct rl_softc * const rc = device_lookup_private(&rl_cd, DISKUNIT(dev)); 312 struct rlc_softc *sc; 313 int error, part, mask; 314 struct disklabel *dl; 315 const char *msg; 316 317 /* 318 * Make sure this is a reasonable open request. 319 */ 320 if (rc == NULL) 321 return ENXIO; 322 323 sc = rc->rc_rlc; 324 part = DISKPART(dev); 325 326 mutex_enter(&rc->rc_disk.dk_openlock); 327 328 /* 329 * If there are wedges, and this is not RAW_PART, then we 330 * need to fail. 331 */ 332 if (rc->rc_disk.dk_nwedges != 0 && part != RAW_PART) { 333 error = EBUSY; 334 goto bad1; 335 } 336 337 /* Check that the disk actually is useable */ 338 msg = rlstate(sc, rc->rc_hwid); 339 if (msg == NULL || msg == rlstates[RLMP_UNLOAD] || 340 msg == rlstates[RLMP_SPUNDOWN]) { 341 error = ENXIO; 342 goto bad1; 343 } 344 /* 345 * If this is the first open; read in where on the disk we are. 346 */ 347 dl = rc->rc_disk.dk_label; 348 if (rc->rc_state == DK_CLOSED) { 349 u_int16_t mp; 350 int maj; 351 RL_WREG(RL_CS, RLCS_RHDR|(rc->rc_hwid << RLCS_USHFT)); 352 waitcrdy(sc); 353 mp = RL_RREG(RL_MP); 354 rc->rc_head = ((mp & RLMP_HS) == RLMP_HS); 355 rc->rc_cyl = (mp >> 7) & 0777; 356 rc->rc_state = DK_OPEN; 357 /* Get disk label */ 358 maj = cdevsw_lookup_major(&rl_cdevsw); 359 if ((msg = readdisklabel(MAKEDISKDEV(maj, 360 device_unit(rc->rc_dev), RAW_PART), rlstrategy, dl, NULL))) 361 aprint_normal_dev(rc->rc_dev, "%s", msg); 362 aprint_normal_dev(rc->rc_dev, "size %d sectors\n", 363 dl->d_secperunit); 364 } 365 if (part >= dl->d_npartitions) { 366 error = ENXIO; 367 goto bad1; 368 } 369 370 mask = 1 << part; 371 switch (fmt) { 372 case S_IFCHR: 373 rc->rc_disk.dk_copenmask |= mask; 374 break; 375 case S_IFBLK: 376 rc->rc_disk.dk_bopenmask |= mask; 377 break; 378 } 379 rc->rc_disk.dk_openmask |= mask; 380 error = 0; 381 bad1: 382 mutex_exit(&rc->rc_disk.dk_openlock); 383 return (error); 384 } 385 386 int 387 rlclose(dev_t dev, int flag, int fmt, struct lwp *l) 388 { 389 int unit = DISKUNIT(dev); 390 struct rl_softc *rc = device_lookup_private(&rl_cd, unit); 391 int mask = (1 << DISKPART(dev)); 392 393 mutex_enter(&rc->rc_disk.dk_openlock); 394 395 switch (fmt) { 396 case S_IFCHR: 397 rc->rc_disk.dk_copenmask &= ~mask; 398 break; 399 case S_IFBLK: 400 rc->rc_disk.dk_bopenmask &= ~mask; 401 break; 402 } 403 rc->rc_disk.dk_openmask = 404 rc->rc_disk.dk_copenmask | rc->rc_disk.dk_bopenmask; 405 406 if (rc->rc_disk.dk_openmask == 0) 407 rc->rc_state = DK_CLOSED; /* May change pack */ 408 mutex_exit(&rc->rc_disk.dk_openlock); 409 return 0; 410 } 411 412 void 413 rlstrategy(struct buf *bp) 414 { 415 struct rl_softc * const rc = device_lookup_private(&rl_cd, DISKUNIT(bp->b_dev)); 416 struct disklabel *lp; 417 int s; 418 419 if (rc == NULL || rc->rc_state != DK_OPEN) /* How did we end up here at all? */ 420 panic("rlstrategy: state impossible"); 421 422 lp = rc->rc_disk.dk_label; 423 if (bounds_check_with_label(&rc->rc_disk, bp, 1) <= 0) 424 goto done; 425 426 if (bp->b_bcount == 0) 427 goto done; 428 429 bp->b_rawblkno = 430 bp->b_blkno + lp->d_partitions[DISKPART(bp->b_dev)].p_offset; 431 bp->b_cylinder = bp->b_rawblkno / lp->d_secpercyl; 432 433 s = splbio(); 434 bufq_put(rc->rc_rlc->sc_q, bp); 435 rlcstart(rc->rc_rlc, 0); 436 splx(s); 437 return; 438 439 done: biodone(bp); 440 } 441 442 int 443 rlioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 444 { 445 struct rl_softc *rc = device_lookup_private(&rl_cd, DISKUNIT(dev)); 446 struct disklabel *lp = rc->rc_disk.dk_label; 447 int error; 448 #ifdef __HAVE_OLD_DISKLABEL 449 struct disklabel newlabel; 450 #endif 451 452 error = disk_ioctl(&rc->rc_disk, dev, cmd, addr, flag, l); 453 if (error != EPASSTHROUGH) 454 return error; 455 else 456 error = 0; 457 458 switch (cmd) { 459 case DIOCSDINFO: 460 case DIOCWDINFO: 461 #ifdef __HAVE_OLD_DISKLABEL 462 case ODIOCWDINFO: 463 case ODIOCSDINFO: 464 #endif 465 { 466 struct disklabel *tp; 467 468 #ifdef __HAVE_OLD_DISKLABEL 469 if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) { 470 memset(&newlabel, 0, sizeof newlabel); 471 memcpy(&newlabel, addr, sizeof (struct olddisklabel)); 472 tp = &newlabel; 473 } else 474 #endif 475 tp = (struct disklabel *)addr; 476 477 if ((flag & FWRITE) == 0) 478 error = EBADF; 479 else { 480 mutex_enter(&rc->rc_disk.dk_openlock); 481 error = (( 482 #ifdef __HAVE_OLD_DISKLABEL 483 cmd == ODIOCSDINFO || 484 #endif 485 cmd == DIOCSDINFO) ? 486 setdisklabel(lp, tp, 0, 0) : 487 writedisklabel(dev, rlstrategy, lp, 0)); 488 mutex_exit(&rc->rc_disk.dk_openlock); 489 } 490 break; 491 } 492 493 case DIOCWLABEL: 494 if ((flag & FWRITE) == 0) 495 error = EBADF; 496 break; 497 498 default: 499 error = ENOTTY; 500 break; 501 } 502 return error; 503 } 504 505 int 506 rlpsize(dev_t dev) 507 { 508 struct rl_softc * const rc = device_lookup_private(&rl_cd, DISKUNIT(dev)); 509 struct disklabel *dl; 510 int size; 511 512 if (rc == NULL) 513 return -1; 514 dl = rc->rc_disk.dk_label; 515 size = dl->d_partitions[DISKPART(dev)].p_size * 516 (dl->d_secsize / DEV_BSIZE); 517 return size; 518 } 519 520 int 521 rldump(dev_t dev, daddr_t blkno, void *va, size_t size) 522 { 523 /* Not likely... */ 524 return 0; 525 } 526 527 int 528 rlread(dev_t dev, struct uio *uio, int ioflag) 529 { 530 return (physio(rlstrategy, NULL, dev, B_READ, minphys, uio)); 531 } 532 533 int 534 rlwrite(dev_t dev, struct uio *uio, int ioflag) 535 { 536 return (physio(rlstrategy, NULL, dev, B_WRITE, minphys, uio)); 537 } 538 539 static const char * const rlerr[] = { 540 "no", 541 "operation incomplete", 542 "read data CRC", 543 "header CRC", 544 "data late", 545 "header not found", 546 "", 547 "", 548 "non-existent memory", 549 "memory parity error", 550 "", 551 "", 552 "", 553 "", 554 "", 555 "", 556 }; 557 558 void 559 rlcintr(void *arg) 560 { 561 struct rlc_softc *sc = arg; 562 struct buf *bp; 563 u_int16_t cs; 564 565 bp = sc->sc_active; 566 if (bp == 0) { 567 aprint_error_dev(sc->sc_dev, "strange interrupt\n"); 568 return; 569 } 570 bus_dmamap_unload(sc->sc_dmat, sc->sc_dmam); 571 sc->sc_active = 0; 572 cs = RL_RREG(RL_CS); 573 if (cs & RLCS_ERR) { 574 int error = (cs & RLCS_ERRMSK) >> 10; 575 576 aprint_error_dev(sc->sc_dev, "%s\n", rlerr[error]); 577 bp->b_error = EIO; 578 bp->b_resid = bp->b_bcount; 579 sc->sc_bytecnt = 0; 580 } 581 if (sc->sc_bytecnt == 0) /* Finished transfer */ 582 biodone(bp); 583 rlcstart(sc, sc->sc_bytecnt ? bp : 0); 584 } 585 586 /* 587 * Start routine. First position the disk to the given position, 588 * then start reading/writing. An optimization would be to be able 589 * to handle overlapping seeks between disks. 590 */ 591 void 592 rlcstart(struct rlc_softc *sc, struct buf *ob) 593 { 594 struct disklabel *lp; 595 struct rl_softc *rc; 596 struct buf *bp; 597 int bn, cn, sn, tn, blks, err; 598 599 if (sc->sc_active) 600 return; /* Already doing something */ 601 602 if (ob == 0) { 603 bp = bufq_get(sc->sc_q); 604 if (bp == NULL) 605 return; /* Nothing to do */ 606 sc->sc_bufaddr = bp->b_data; 607 sc->sc_diskblk = bp->b_rawblkno; 608 sc->sc_bytecnt = bp->b_bcount; 609 bp->b_resid = 0; 610 } else 611 bp = ob; 612 sc->sc_active = bp; 613 614 rc = device_lookup_private(&rl_cd, DISKUNIT(bp->b_dev)); 615 bn = sc->sc_diskblk; 616 lp = rc->rc_disk.dk_label; 617 if (bn) { 618 cn = bn / lp->d_secpercyl; 619 sn = bn % lp->d_secpercyl; 620 tn = sn / lp->d_nsectors; 621 sn = sn % lp->d_nsectors; 622 } else 623 cn = sn = tn = 0; 624 625 /* 626 * Check if we have to position disk first. 627 */ 628 if (rc->rc_cyl != cn || rc->rc_head != tn) { 629 u_int16_t da = RLDA_SEEK; 630 if (cn > rc->rc_cyl) 631 da |= ((cn - rc->rc_cyl) << RLDA_CYLSHFT) | RLDA_DIR; 632 else 633 da |= ((rc->rc_cyl - cn) << RLDA_CYLSHFT); 634 if (tn) 635 da |= RLDA_HSSEEK; 636 waitcrdy(sc); 637 RL_WREG(RL_DA, da); 638 RL_WREG(RL_CS, RLCS_SEEK | (rc->rc_hwid << RLCS_USHFT)); 639 waitcrdy(sc); 640 rc->rc_cyl = cn; 641 rc->rc_head = tn; 642 } 643 RL_WREG(RL_DA, (cn << RLDA_CYLSHFT) | (tn ? RLDA_HSRW : 0) | (sn << 1)); 644 blks = sc->sc_bytecnt/DEV_BSIZE; 645 646 if (sn + blks > RL_SPT/2) 647 blks = RL_SPT/2 - sn; 648 RL_WREG(RL_MP, -(blks*DEV_BSIZE)/2); 649 err = bus_dmamap_load(sc->sc_dmat, sc->sc_dmam, sc->sc_bufaddr, 650 (blks*DEV_BSIZE), (bp->b_flags & B_PHYS ? bp->b_proc : 0), 651 BUS_DMA_NOWAIT); 652 if (err) 653 panic("%s: bus_dmamap_load failed: %d", 654 device_xname(sc->sc_dev), err); 655 RL_WREG(RL_BA, (sc->sc_dmam->dm_segs[0].ds_addr & 0xffff)); 656 657 /* Count up vars */ 658 sc->sc_bufaddr = (char *)sc->sc_bufaddr + (blks*DEV_BSIZE); 659 sc->sc_diskblk += blks; 660 sc->sc_bytecnt -= (blks*DEV_BSIZE); 661 662 if (bp->b_flags & B_READ) 663 RL_WREG(RL_CS, RLCS_IE|RLCS_RD|(rc->rc_hwid << RLCS_USHFT)); 664 else 665 RL_WREG(RL_CS, RLCS_IE|RLCS_WD|(rc->rc_hwid << RLCS_USHFT)); 666 } 667 668 /* 669 * Called once per controller when an ubareset occurs. 670 * Retracts all disks and restarts active transfers. 671 */ 672 void 673 rlcreset(device_t dev) 674 { 675 struct rlc_softc *sc = device_private(dev); 676 struct rl_softc *rc; 677 int i; 678 u_int16_t mp; 679 680 for (i = 0; i < rl_cd.cd_ndevs; i++) { 681 if ((rc = device_lookup_private(&rl_cd, i)) == NULL) 682 continue; 683 if (rc->rc_state != DK_OPEN) 684 continue; 685 if (rc->rc_rlc != sc) 686 continue; 687 688 RL_WREG(RL_CS, RLCS_RHDR|(rc->rc_hwid << RLCS_USHFT)); 689 waitcrdy(sc); 690 mp = RL_RREG(RL_MP); 691 rc->rc_head = ((mp & RLMP_HS) == RLMP_HS); 692 rc->rc_cyl = (mp >> 7) & 0777; 693 } 694 if (sc->sc_active == 0) 695 return; 696 697 bufq_put(sc->sc_q, sc->sc_active); 698 sc->sc_active = 0; 699 rlcstart(sc, 0); 700 } 701