123336Smckusick /* 223336Smckusick * Copyright (c) 1982 Regents of the University of California. 323336Smckusick * All rights reserved. The Berkeley software License Agreement 423336Smckusick * specifies the terms and conditions for redistribution. 523336Smckusick * 6*25322Smckusick * @(#)rk.c 6.10 (Berkeley) 10/28/85 723336Smckusick */ 81899Swnj 91942Swnj #include "rk.h" 102648Swnj #if NHK > 0 113104Swnj int rkpip; /* DEBUG */ 123104Swnj int rknosval; /* DEBUG */ 133709Sroot #ifdef RKDEBUG 143293Swnj int rkdebug; 153709Sroot #endif 163709Sroot #ifdef RKBDEBUG 173709Sroot int rkbdebug; 183709Sroot #endif 191899Swnj /* 203293Swnj * RK611/RK0[67] disk driver 212622Swnj * 222622Swnj * This driver mimics up.c; see it for an explanation of common code. 232685Swnj * 242885Swnj * TODO: 253208Swnj * Learn why we lose an interrupt sometime when spinning drives down 261899Swnj */ 279777Ssam #include "../machine/pte.h" 289777Ssam 2917076Sbloom #include "param.h" 3017076Sbloom #include "systm.h" 3117076Sbloom #include "buf.h" 3217076Sbloom #include "conf.h" 3317076Sbloom #include "dir.h" 3417076Sbloom #include "user.h" 3517076Sbloom #include "map.h" 3617076Sbloom #include "vm.h" 3717076Sbloom #include "dk.h" 3817076Sbloom #include "cmap.h" 3917076Sbloom #include "dkbad.h" 4017076Sbloom #include "uio.h" 4117076Sbloom #include "kernel.h" 4218315Sralph #include "syslog.h" 431899Swnj 448478Sroot #include "../vax/cpu.h" 4517076Sbloom #include "ubareg.h" 4617076Sbloom #include "ubavar.h" 4717076Sbloom #include "rkreg.h" 481899Swnj 492618Swnj struct rk_softc { 502618Swnj int sc_softas; 512618Swnj int sc_ndrive; 522618Swnj int sc_wticks; 532618Swnj int sc_recal; 542648Swnj } rk_softc[NHK]; 551899Swnj 5624740Sbloom #define rkunit(dev) (minor(dev) >> 3) 5724740Sbloom 582618Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 592787Swnj struct size { 602618Swnj daddr_t nblocks; 612618Swnj int cyloff; 62*25322Smckusick } rk7_sizes[8] = { 632618Swnj 15884, 0, /* A=cyl 0 thru 240 */ 642665Swnj 10032, 241, /* B=cyl 241 thru 392 */ 652665Swnj 53790, 0, /* C=cyl 0 thru 814 */ 66*25322Smckusick 15884, 393, /* D=cyl 393 thru 633 */ 672618Swnj 0, 0, 68*25322Smckusick 11792, 634, /* F=cyl 634 thru 814 */ 69*25322Smckusick 27786, 393, /* G=cyl 393 thru 814, should be 27698 */ 702618Swnj 0, 0, 713709Sroot }, rk6_sizes[8] ={ 723709Sroot 15884, 0, /* A=cyl 0 thru 240 */ 733709Sroot 11154, 241, /* B=cyl 241 thru 409 */ 743709Sroot 27126, 0, /* C=cyl 0 thru 410 */ 753709Sroot 0, 0, 763709Sroot 0, 0, 773709Sroot 0, 0, 783709Sroot 0, 0, 793709Sroot 0, 0, 802618Swnj }; 812618Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 821899Swnj 833709Sroot short rktypes[] = { RK_CDT, 0 }; 843709Sroot 852618Swnj int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); 862981Swnj struct uba_ctlr *rkminfo[NHK]; 872981Swnj struct uba_device *rkdinfo[NRK]; 882981Swnj struct uba_device *rkip[NHK][4]; 891899Swnj 902618Swnj u_short rkstd[] = { 0777440, 0 }; 912618Swnj struct uba_driver hkdriver = 922622Swnj { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; 932648Swnj struct buf rkutab[NRK]; 942648Swnj short rkcyl[NRK]; 953709Sroot struct dkbad rkbad[NRK]; 963709Sroot struct buf brkbuf[NRK]; 971899Swnj 982618Swnj struct rkst { 992618Swnj short nsect; 1002618Swnj short ntrak; 1012618Swnj short nspc; 1022618Swnj short ncyl; 1032618Swnj struct size *sizes; 1042618Swnj } rkst[] = { 1052618Swnj NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, 1063709Sroot NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes, 1072618Swnj }; 1081899Swnj 1092618Swnj u_char rk_offset[16] = 1103293Swnj { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800, 1113293Swnj RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0 1123293Swnj }; 1131899Swnj 1142648Swnj struct buf rrkbuf[NRK]; 1152618Swnj 1162618Swnj #define b_cylin b_resid 1172618Swnj 1182618Swnj int rkwstart, rkwatch(); 1192618Swnj 1202618Swnj rkprobe(reg) 1212618Swnj caddr_t reg; 1221899Swnj { 1232618Swnj register int br, cvec; 1241899Swnj 1252618Swnj #ifdef lint 1262618Swnj br = 0; cvec = br; br = cvec; 1274935Swnj rkintr(0); 1282618Swnj #endif 1292618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; 1302618Swnj DELAY(10); 1312618Swnj ((struct rkdevice *)reg)->rkcs1 = RK_CDT; 1327416Skre return (sizeof (struct rkdevice)); 1332618Swnj } 1341899Swnj 1352618Swnj rkslave(ui, reg) 1362981Swnj struct uba_device *ui; 1372618Swnj caddr_t reg; 1382618Swnj { 1392618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)reg; 1401899Swnj 1413709Sroot ui->ui_type = 0; 1423709Sroot rkaddr->rkcs1 = RK_CCLR; 1432618Swnj rkaddr->rkcs2 = ui->ui_slave; 1442957Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; 1452622Swnj rkwait(rkaddr); 1462894Swnj DELAY(50); 1473293Swnj if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) { 1483709Sroot rkaddr->rkcs1 = RK_CCLR; 1492618Swnj return (0); 1502618Swnj } 1513709Sroot if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) { 1523709Sroot ui->ui_type = 1; 1533709Sroot rkaddr->rkcs1 = RK_CCLR; 1543709Sroot } 1552618Swnj return (1); 1562618Swnj } 1572618Swnj 1582618Swnj rkattach(ui) 1592981Swnj register struct uba_device *ui; 1602618Swnj { 1612618Swnj 1622618Swnj if (rkwstart == 0) { 1632758Swnj timeout(rkwatch, (caddr_t)0, hz); 1642618Swnj rkwstart++; 1652618Swnj } 1662618Swnj if (ui->ui_dk >= 0) 1672758Swnj dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); 1682618Swnj rkip[ui->ui_ctlr][ui->ui_slave] = ui; 1692618Swnj rk_softc[ui->ui_ctlr].sc_ndrive++; 1702618Swnj rkcyl[ui->ui_unit] = -1; 1713709Sroot ui->ui_flags = 0; 1722618Swnj } 1732618Swnj 1748573Sroot rkopen(dev) 1758573Sroot dev_t dev; 1768573Sroot { 17724785Skarels register int unit = rkunit(dev); 1788573Sroot register struct uba_device *ui; 1798573Sroot 1808573Sroot if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0) 1818573Sroot return (ENXIO); 1828573Sroot return (0); 1838573Sroot } 1848573Sroot 1851899Swnj rkstrategy(bp) 1862618Swnj register struct buf *bp; 1871899Swnj { 1882981Swnj register struct uba_device *ui; 1892618Swnj register struct rkst *st; 1902618Swnj register int unit; 1912618Swnj register struct buf *dp; 1922618Swnj int xunit = minor(bp->b_dev) & 07; 1932618Swnj long bn, sz; 1945433Sroot int s; 1951899Swnj 1962618Swnj sz = (bp->b_bcount+511) >> 9; 19724740Sbloom unit = rkunit(bp->b_dev); 19824740Sbloom if (unit >= NRK) { 19924740Sbloom bp->b_error = ENXIO; 2002618Swnj goto bad; 20124740Sbloom } 2022618Swnj ui = rkdinfo[unit]; 20324740Sbloom if (ui == 0 || ui->ui_alive == 0) { 20424740Sbloom bp->b_error = ENXIO; 2052618Swnj goto bad; 20624740Sbloom } 2072618Swnj st = &rkst[ui->ui_type]; 2082618Swnj if (bp->b_blkno < 0 || 20924740Sbloom (bn = bp->b_blkno)+sz > st->sizes[xunit].nblocks) { 21024785Skarels if (bp->b_blkno == st->sizes[xunit].nblocks) { 21124785Skarels bp->b_resid = bp->b_bcount; 21224740Sbloom goto done; 21324785Skarels } 21424740Sbloom bp->b_error = EINVAL; 2152618Swnj goto bad; 21624740Sbloom } 2172618Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 2185433Sroot s = spl5(); 2192618Swnj dp = &rkutab[ui->ui_unit]; 2202618Swnj disksort(dp, bp); 2212618Swnj if (dp->b_active == 0) { 2222618Swnj (void) rkustart(ui); 2232618Swnj bp = &ui->ui_mi->um_tab; 2242618Swnj if (bp->b_actf && bp->b_active == 0) 2252618Swnj (void) rkstart(ui->ui_mi); 2261899Swnj } 2275433Sroot splx(s); 2282618Swnj return; 2292618Swnj 2302618Swnj bad: 2312618Swnj bp->b_flags |= B_ERROR; 23224740Sbloom done: 2332618Swnj iodone(bp); 2342618Swnj return; 2351899Swnj } 2361899Swnj 2372618Swnj rkustart(ui) 2382981Swnj register struct uba_device *ui; 2392618Swnj { 2402618Swnj register struct buf *bp, *dp; 2412981Swnj register struct uba_ctlr *um; 2422618Swnj register struct rkdevice *rkaddr; 2431899Swnj 2442618Swnj if (ui == 0) 2456347Swnj return; 2462618Swnj dk_busy &= ~(1<<ui->ui_dk); 2472618Swnj dp = &rkutab[ui->ui_unit]; 2482618Swnj um = ui->ui_mi; 2492894Swnj rkaddr = (struct rkdevice *)um->um_addr; 2502618Swnj if (um->um_tab.b_active) { 2512618Swnj rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; 2526347Swnj return; 2532618Swnj } 2546347Swnj if ((bp = dp->b_actf) == NULL) 2556347Swnj return; 2563709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR; 2572618Swnj rkaddr->rkcs2 = ui->ui_slave; 2583709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 2592618Swnj rkwait(rkaddr); 2603709Sroot if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) { 2612618Swnj /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 2623709Sroot struct rkst *st = &rkst[ui->ui_type]; 2633709Sroot struct buf *bbp = &brkbuf[ui->ui_unit]; 2643709Sroot 2653709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO; 2663709Sroot ui->ui_flags = 1; 2673709Sroot bbp->b_flags = B_READ|B_BUSY; 2683709Sroot bbp->b_dev = bp->b_dev; 2693709Sroot bbp->b_bcount = 512; 2703709Sroot bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit]; 2713709Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 2723709Sroot bbp->b_cylin = st->ncyl - 1; 2733709Sroot dp->b_actf = bbp; 2743709Sroot bbp->av_forw = bp; 2753709Sroot bp = bbp; 2762618Swnj rkwait(rkaddr); 2772618Swnj } 2782903Swnj if (dp->b_active) 2792903Swnj goto done; 2802903Swnj dp->b_active = 1; 2813293Swnj if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY) 2822894Swnj goto done; 2832618Swnj if (rk_softc[um->um_ctlr].sc_ndrive == 1) 2842618Swnj goto done; 2852618Swnj if (bp->b_cylin == rkcyl[ui->ui_unit]) 2862618Swnj goto done; 2872618Swnj rkaddr->rkcyl = bp->b_cylin; 2882618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 2893709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 2902618Swnj if (ui->ui_dk >= 0) { 2912618Swnj dk_busy |= 1<<ui->ui_dk; 2922618Swnj dk_seek[ui->ui_dk]++; 2932618Swnj } 2942618Swnj goto out; 2952618Swnj done: 2962618Swnj if (dp->b_active != 2) { 2972618Swnj dp->b_forw = NULL; 2982618Swnj if (um->um_tab.b_actf == NULL) 2992618Swnj um->um_tab.b_actf = dp; 3002618Swnj else 3012618Swnj um->um_tab.b_actl->b_forw = dp; 3022618Swnj um->um_tab.b_actl = dp; 3032618Swnj dp->b_active = 2; 3042618Swnj } 3052618Swnj out: 3066347Swnj return; 3072618Swnj } 3082618Swnj 3092618Swnj rkstart(um) 3102981Swnj register struct uba_ctlr *um; 3111899Swnj { 3122618Swnj register struct buf *bp, *dp; 3132981Swnj register struct uba_device *ui; 3142618Swnj register struct rkdevice *rkaddr; 3152618Swnj struct rkst *st; 3161899Swnj daddr_t bn; 3172618Swnj int sn, tn, cmd; 3181899Swnj 3192618Swnj loop: 3202618Swnj if ((dp = um->um_tab.b_actf) == NULL) 3216347Swnj return; 3222618Swnj if ((bp = dp->b_actf) == NULL) { 3232618Swnj um->um_tab.b_actf = dp->b_forw; 3242618Swnj goto loop; 3251899Swnj } 3262618Swnj um->um_tab.b_active++; 32724740Sbloom ui = rkdinfo[rkunit(bp->b_dev)]; 32824740Sbloom bn = bp->b_blkno; 3292618Swnj st = &rkst[ui->ui_type]; 3302618Swnj sn = bn%st->nspc; 3312618Swnj tn = sn/st->nsect; 3322618Swnj sn %= st->nsect; 3332618Swnj rkaddr = (struct rkdevice *)ui->ui_addr; 3342957Swnj retry: 3353709Sroot rkaddr->rkcs1 = RK_CCLR; 3362618Swnj rkaddr->rkcs2 = ui->ui_slave; 3373709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3382618Swnj rkwait(rkaddr); 3393293Swnj if ((rkaddr->rkds&RKDS_SVAL) == 0) { 3402957Swnj rknosval++; 3412957Swnj goto nosval; 3422894Swnj } 3433293Swnj if (rkaddr->rkds&RKDS_PIP) { 3442957Swnj rkpip++; 3452957Swnj goto retry; 3462957Swnj } 3473293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 34824740Sbloom printf("rk%d: not ready", rkunit(bp->b_dev)); 3493293Swnj if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { 3502894Swnj printf("\n"); 3513709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 3522894Swnj rkwait(rkaddr); 3533709Sroot rkaddr->rkcs1 = RK_CCLR; 3542894Swnj rkwait(rkaddr); 3552894Swnj um->um_tab.b_active = 0; 3562894Swnj um->um_tab.b_errcnt = 0; 3572894Swnj dp->b_actf = bp->av_forw; 3582894Swnj dp->b_active = 0; 3592894Swnj bp->b_flags |= B_ERROR; 3602894Swnj iodone(bp); 3612894Swnj goto loop; 3622894Swnj } 3632894Swnj printf(" (came back!)\n"); 3642894Swnj } 3652957Swnj nosval: 3662618Swnj rkaddr->rkcyl = bp->b_cylin; 3672618Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 3682618Swnj rkaddr->rkda = (tn << 8) + sn; 3692618Swnj rkaddr->rkwc = -bp->b_bcount / sizeof (short); 3702618Swnj if (bp->b_flags & B_READ) 3713709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO; 3722618Swnj else 3733709Sroot cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO; 3742618Swnj um->um_cmd = cmd; 3753104Swnj (void) ubago(ui); 3761899Swnj } 3771899Swnj 3782618Swnj rkdgo(um) 3792981Swnj register struct uba_ctlr *um; 3801899Swnj { 3812618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3821899Swnj 3837031Swnj um->um_tab.b_active = 2; /* should now be 2 */ 3842618Swnj rkaddr->rkba = um->um_ubinfo; 3852618Swnj rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); 3862618Swnj } 3872618Swnj 3882710Swnj rkintr(rk11) 3892618Swnj int rk11; 3902618Swnj { 3912981Swnj register struct uba_ctlr *um = rkminfo[rk11]; 3922981Swnj register struct uba_device *ui; 3932618Swnj register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; 3942618Swnj register struct buf *bp, *dp; 3952618Swnj int unit; 3962618Swnj struct rk_softc *sc = &rk_softc[um->um_ctlr]; 3972618Swnj int as = (rkaddr->rkatt >> 8) | sc->sc_softas; 3982618Swnj 3992618Swnj sc->sc_wticks = 0; 4002618Swnj sc->sc_softas = 0; 4016347Swnj if (um->um_tab.b_active == 2 || sc->sc_recal) { 4027031Swnj um->um_tab.b_active = 1; 4032618Swnj dp = um->um_tab.b_actf; 4042618Swnj bp = dp->b_actf; 40524740Sbloom ui = rkdinfo[rkunit(bp->b_dev)]; 4062618Swnj dk_busy &= ~(1 << ui->ui_dk); 4073709Sroot if (bp->b_flags&B_BAD) 4083709Sroot if (rkecc(ui, CONT)) 4093709Sroot return; 4102618Swnj if (rkaddr->rkcs1 & RK_CERR) { 4112618Swnj int recal; 4122618Swnj u_short ds = rkaddr->rkds; 4132618Swnj u_short cs2 = rkaddr->rkcs2; 4142618Swnj u_short er = rkaddr->rker; 4153709Sroot #ifdef RKDEBUG 4163293Swnj if (rkdebug) { 4173293Swnj printf("cs2=%b ds=%b er=%b\n", 4183293Swnj cs2, RKCS2_BITS, ds, 4193293Swnj RKDS_BITS, er, RKER_BITS); 4203293Swnj } 4213709Sroot #endif 4223293Swnj if (er & RKER_WLE) { 42324740Sbloom printf("rk%d: write locked\n", 42424740Sbloom rkunit(bp->b_dev)); 4252685Swnj bp->b_flags |= B_ERROR; 4262685Swnj } else if (++um->um_tab.b_errcnt > 28 || 4272676Swnj ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { 4283709Sroot hard: 4292927Swnj harderr(bp, "rk"); 4302927Swnj printf("cs2=%b ds=%b er=%b\n", 4312894Swnj cs2, RKCS2_BITS, ds, 4322676Swnj RKDS_BITS, er, RKER_BITS); 4333145Swnj bp->b_flags |= B_ERROR; 4343145Swnj sc->sc_recal = 0; 4353709Sroot } else if (er & RKER_BSE) { 4363709Sroot if (rkecc(ui, BSE)) 4373709Sroot return; 4383709Sroot else 4393709Sroot goto hard; 4407182Sroot } else { 4417182Sroot if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) { 4427182Sroot if (rkecc(ui, ECC)) 4437182Sroot return; 4447182Sroot } else 4457182Sroot um->um_tab.b_active = 0; 4467182Sroot } 4473293Swnj if (cs2&RKCS2_MDS) { 4483293Swnj rkaddr->rkcs2 = RKCS2_SCLR; 4492618Swnj goto retry; 4501899Swnj } 4512618Swnj recal = 0; 4523293Swnj if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || 4532618Swnj (um->um_tab.b_errcnt&07) == 4) 4542618Swnj recal = 1; 4553709Sroot rkaddr->rkcs1 = RK_CCLR; 4562618Swnj rkaddr->rkcs2 = ui->ui_slave; 4573709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 4582618Swnj rkwait(rkaddr); 4592618Swnj if (recal && um->um_tab.b_active == 0) { 4603709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO; 4612618Swnj rkcyl[ui->ui_unit] = -1; 4622957Swnj sc->sc_recal = 0; 4632957Swnj goto nextrecal; 4642618Swnj } 4651899Swnj } 4662618Swnj retry: 4672957Swnj switch (sc->sc_recal) { 4682957Swnj 4692957Swnj case 1: 4702957Swnj rkaddr->rkcyl = bp->b_cylin; 4712957Swnj rkcyl[ui->ui_unit] = bp->b_cylin; 4723709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; 4732957Swnj goto nextrecal; 4742957Swnj case 2: 4752957Swnj if (um->um_tab.b_errcnt < 16 || 4763290Swnj (bp->b_flags&B_READ) == 0) 4773159Swnj goto donerecal; 4782957Swnj rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; 4793709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO; 4802957Swnj /* fall into ... */ 4812957Swnj nextrecal: 4822957Swnj sc->sc_recal++; 4832957Swnj rkwait(rkaddr); 4842957Swnj um->um_tab.b_active = 1; 4852957Swnj return; 4863159Swnj donerecal: 4872957Swnj case 3: 4882618Swnj sc->sc_recal = 0; 4892618Swnj um->um_tab.b_active = 0; 4902957Swnj break; 4911899Swnj } 4923709Sroot ubadone(um); 4932618Swnj if (um->um_tab.b_active) { 4942618Swnj um->um_tab.b_active = 0; 4952618Swnj um->um_tab.b_errcnt = 0; 4962618Swnj um->um_tab.b_actf = dp->b_forw; 4972618Swnj dp->b_active = 0; 4982618Swnj dp->b_errcnt = 0; 4992618Swnj dp->b_actf = bp->av_forw; 5002618Swnj bp->b_resid = -rkaddr->rkwc * sizeof(short); 5012618Swnj iodone(bp); 5022618Swnj if (dp->b_actf) 5036347Swnj rkustart(ui); 5041899Swnj } 5052618Swnj as &= ~(1<<ui->ui_slave); 5061899Swnj } 5072618Swnj for (unit = 0; as; as >>= 1, unit++) 5082981Swnj if (as & 1) { 5092981Swnj ui = rkip[rk11][unit]; 5102981Swnj if (ui) { 5116347Swnj rkustart(rkip[rk11][unit]); 5122981Swnj } else { 5133709Sroot rkaddr->rkcs1 = RK_CCLR; 5142981Swnj rkaddr->rkcs2 = unit; 5153709Sroot rkaddr->rkcs1 = RK_DCLR|RK_GO; 5162981Swnj rkwait(rkaddr); 5173709Sroot rkaddr->rkcs1 = RK_CCLR; 5182981Swnj } 5192981Swnj } 5202618Swnj if (um->um_tab.b_actf && um->um_tab.b_active == 0) 5216347Swnj rkstart(um); 5228609Sroot if (((rkaddr->rkcs1) & RK_IE) == 0) 5233709Sroot rkaddr->rkcs1 = RK_IE; 5241899Swnj } 5251899Swnj 5262618Swnj rkwait(addr) 5272618Swnj register struct rkdevice *addr; 5282618Swnj { 5291899Swnj 5302618Swnj while ((addr->rkcs1 & RK_CRDY) == 0) 5312618Swnj ; 5322618Swnj } 5332618Swnj 5347731Sroot rkread(dev, uio) 5352618Swnj dev_t dev; 5367731Sroot struct uio *uio; 5371899Swnj { 53824785Skarels register int unit = rkunit(dev); 5392618Swnj 5402648Swnj if (unit >= NRK) 5418162Sroot return (ENXIO); 5428162Sroot return (physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys, uio)); 5431899Swnj } 5441899Swnj 5457836Sroot rkwrite(dev, uio) 5462618Swnj dev_t dev; 5477836Sroot struct uio *uio; 5481899Swnj { 54924785Skarels register int unit = rkunit(dev); 5501899Swnj 5512648Swnj if (unit >= NRK) 5528493Sroot return (ENXIO); 5538493Sroot return (physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys, uio)); 5541899Swnj } 5551899Swnj 5563709Sroot rkecc(ui, flag) 5572981Swnj register struct uba_device *ui; 5581899Swnj { 5592618Swnj register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; 5602618Swnj register struct buf *bp = rkutab[ui->ui_unit].b_actf; 5612981Swnj register struct uba_ctlr *um = ui->ui_mi; 5622618Swnj register struct rkst *st; 5632618Swnj struct uba_regs *ubp = ui->ui_hd->uh_uba; 5642618Swnj caddr_t addr; 5653709Sroot int reg, npf, o, cmd, ubaddr; 5662618Swnj int bn, cn, tn, sn; 5671899Swnj 5683709Sroot if (flag == CONT) 5693709Sroot npf = bp->b_error; 5703709Sroot else 5713709Sroot npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount); 5722618Swnj reg = btop(um->um_ubinfo&0x3ffff) + npf; 5732618Swnj o = (int)bp->b_un.b_addr & PGOFSET; 57424740Sbloom bn = bp->b_blkno; 5752618Swnj st = &rkst[ui->ui_type]; 5762618Swnj cn = bp->b_cylin; 5773709Sroot sn = bn%st->nspc + npf; 5782618Swnj tn = sn/st->nsect; 5792618Swnj sn %= st->nsect; 5802618Swnj cn += tn/st->ntrak; 5812618Swnj tn %= st->ntrak; 5823709Sroot ubapurge(um); 5833709Sroot switch (flag) { 5843709Sroot case ECC: 5853709Sroot { 5863709Sroot register int i; 5873709Sroot int bit, byte, mask; 5883709Sroot 5893709Sroot npf--; 5903709Sroot reg--; 59124847Seric log(LOG_WARNING, "rk%d%c: soft ecc sn%d\n", rkunit(bp->b_dev), 5923709Sroot 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 5933709Sroot mask = rk->rkec2; 5943709Sroot i = rk->rkec1 - 1; /* -1 makes 0 origin */ 5953709Sroot bit = i&07; 5963709Sroot i = (i&~07)>>3; 5973709Sroot byte = i + o; 5983709Sroot while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 5993709Sroot addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ 6003709Sroot (byte & PGOFSET); 6013709Sroot putmemc(addr, getmemc(addr)^(mask<<bit)); 6023709Sroot byte++; 6033709Sroot i++; 6043709Sroot bit -= 8; 6053709Sroot } 6067182Sroot if (rk->rkwc == 0) { 6077182Sroot um->um_tab.b_active = 0; 6083709Sroot return (0); 6097182Sroot } 6103709Sroot npf++; 6113709Sroot reg++; 6123709Sroot break; 6133709Sroot } 6143709Sroot 6153709Sroot case BSE: 6163709Sroot #ifdef RKBDEBUG 6173709Sroot if (rkbdebug) 6183709Sroot printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 6193709Sroot #endif 6203709Sroot if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0) 6213709Sroot return(0); 6223709Sroot bp->b_flags |= B_BAD; 6233709Sroot bp->b_error = npf + 1; 6243709Sroot bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 6253709Sroot cn = bn/st->nspc; 6263709Sroot sn = bn%st->nspc; 6273709Sroot tn = sn/st->nsect; 6283709Sroot sn %= st->nsect; 6293709Sroot #ifdef RKBDEBUG 6303709Sroot if (rkbdebug) 6313709Sroot printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 6323709Sroot #endif 6333709Sroot rk->rkwc = -(512 / sizeof (short)); 6343709Sroot break; 6353709Sroot 6363709Sroot case CONT: 6373709Sroot #ifdef RKBDEBUG 6383709Sroot if (rkbdebug) 6393709Sroot printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 6403709Sroot #endif 6413709Sroot bp->b_flags &= ~B_BAD; 6423709Sroot rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short)); 64315213Skarels if (rk->rkwc == 0) 6447182Sroot return (0); 6453709Sroot break; 6463709Sroot } 6473709Sroot rk->rkcs1 = RK_CCLR; 6483709Sroot rk->rkcs2 = ui->ui_slave; 6493709Sroot rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 6503709Sroot rkwait(rk); 6512618Swnj rk->rkcyl = cn; 6522618Swnj rk->rkda = (tn << 8) | sn; 6533709Sroot ubaddr = (int)ptob(reg) + o; 6542618Swnj rk->rkba = ubaddr; 6553709Sroot cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO; 6563709Sroot cmd |= (ubaddr >> 8) & 0x300; 6573709Sroot cmd |= rktypes[ui->ui_type]; 6582618Swnj rk->rkcs1 = cmd; 6597031Swnj um->um_tab.b_active = 2; /* continuing */ 6603709Sroot um->um_tab.b_errcnt = 0; /* error has been corrected */ 6612618Swnj return (1); 6621899Swnj } 6631899Swnj 6642618Swnj rkreset(uban) 6652927Swnj int uban; 6661899Swnj { 6672981Swnj register struct uba_ctlr *um; 6682981Swnj register struct uba_device *ui; 6692618Swnj register rk11, unit; 6701899Swnj 6712648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 6722618Swnj if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || 6732618Swnj um->um_alive == 0) 6742618Swnj continue; 6752927Swnj printf(" hk%d", rk11); 6762618Swnj um->um_tab.b_active = 0; 6772618Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 6782618Swnj rk_softc[um->um_ctlr].sc_recal = 0; 6796347Swnj rk_softc[um->um_ctlr].sc_wticks = 0; 6802618Swnj if (um->um_ubinfo) { 6812618Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 6829354Ssam um->um_ubinfo = 0; 6832618Swnj } 6844039Swnj for (unit = 0; unit < NRK; unit++) { 6852618Swnj if ((ui = rkdinfo[unit]) == 0) 6862618Swnj continue; 6874039Swnj if (ui->ui_alive == 0 || ui->ui_mi != um) 6882618Swnj continue; 6892618Swnj rkutab[unit].b_active = 0; 6902618Swnj (void) rkustart(ui); 6912618Swnj } 6922618Swnj (void) rkstart(um); 6932618Swnj } 6941899Swnj } 6952380Swnj 6962618Swnj rkwatch() 6972380Swnj { 6982981Swnj register struct uba_ctlr *um; 6992618Swnj register rk11, unit; 7002618Swnj register struct rk_softc *sc; 7012380Swnj 7022758Swnj timeout(rkwatch, (caddr_t)0, hz); 7032648Swnj for (rk11 = 0; rk11 < NHK; rk11++) { 7042618Swnj um = rkminfo[rk11]; 7052618Swnj if (um == 0 || um->um_alive == 0) 7062618Swnj continue; 7072618Swnj sc = &rk_softc[rk11]; 7082618Swnj if (um->um_tab.b_active == 0) { 7092648Swnj for (unit = 0; unit < NRK; unit++) 7102622Swnj if (rkutab[unit].b_active && 7112622Swnj rkdinfo[unit]->ui_mi == um) 7122618Swnj goto active; 7132618Swnj sc->sc_wticks = 0; 7142618Swnj continue; 7152618Swnj } 7162618Swnj active: 7172618Swnj sc->sc_wticks++; 7182618Swnj if (sc->sc_wticks >= 20) { 7192618Swnj sc->sc_wticks = 0; 7202927Swnj printf("hk%d: lost interrupt\n", rk11); 7212648Swnj ubareset(um->um_ubanum); 7222618Swnj } 7232618Swnj } 7242380Swnj } 7252618Swnj 7262618Swnj #define DBSIZE 20 7272618Swnj 7282618Swnj rkdump(dev) 7292618Swnj dev_t dev; 7302618Swnj { 7312618Swnj struct rkdevice *rkaddr; 7322618Swnj char *start; 7332618Swnj int num, blk, unit; 7342618Swnj struct size *sizes; 7352618Swnj register struct uba_regs *uba; 7362981Swnj register struct uba_device *ui; 7372618Swnj register short *rp; 7382618Swnj struct rkst *st; 7392618Swnj 74024785Skarels unit = rkunit(dev); 7412885Swnj if (unit >= NRK) 7422885Swnj return (ENXIO); 7432618Swnj #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) 7442981Swnj ui = phys(struct uba_device *, rkdinfo[unit]); 7452885Swnj if (ui->ui_alive == 0) 7462885Swnj return (ENXIO); 7472618Swnj uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; 7483329Swnj ubainit(uba); 7492618Swnj rkaddr = (struct rkdevice *)ui->ui_physaddr; 7502618Swnj num = maxfree; 7512618Swnj start = 0; 7523709Sroot rkaddr->rkcs1 = RK_CCLR; 7532618Swnj rkaddr->rkcs2 = unit; 7543709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; 7552618Swnj rkwait(rkaddr); 7563293Swnj if ((rkaddr->rkds & RKDS_VV) == 0) { 7573709Sroot rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO; 7582618Swnj rkwait(rkaddr); 7592618Swnj } 7602618Swnj st = &rkst[ui->ui_type]; 7612618Swnj sizes = phys(struct size *, st->sizes); 76224210Sbloom if (dumplo < 0) 7632885Swnj return (EINVAL); 76424210Sbloom if (dumplo + num >= sizes[minor(dev)&07].nblocks) 76524210Sbloom num = sizes[minor(dev)&07].nblocks - dumplo; 7662618Swnj while (num > 0) { 7672618Swnj register struct pte *io; 7682618Swnj register int i; 7692618Swnj int cn, sn, tn; 7702618Swnj daddr_t bn; 7712618Swnj 7722618Swnj blk = num > DBSIZE ? DBSIZE : num; 7732618Swnj io = uba->uba_map; 7742618Swnj for (i = 0; i < blk; i++) 7752981Swnj *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; 7762618Swnj *(int *)io = 0; 7772618Swnj bn = dumplo + btop(start); 7782618Swnj cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; 7792618Swnj sn = bn%st->nspc; 7802618Swnj tn = sn/st->nsect; 7812618Swnj sn = sn%st->nsect; 7822618Swnj rkaddr->rkcyl = cn; 7832618Swnj rp = (short *) &rkaddr->rkda; 7842618Swnj *rp = (tn << 8) + sn; 7852618Swnj *--rp = 0; 7862618Swnj *--rp = -blk*NBPG / sizeof (short); 7873709Sroot *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE; 7882618Swnj rkwait(rkaddr); 7892885Swnj if (rkaddr->rkcs1 & RK_CERR) 7902885Swnj return (EIO); 7912618Swnj start += blk*NBPG; 7922618Swnj num -= blk; 7932618Swnj } 7942618Swnj return (0); 7952618Swnj } 79612503Ssam 79712503Ssam rksize(dev) 79812503Ssam dev_t dev; 79912503Ssam { 80024785Skarels int unit = rkunit(dev); 80112503Ssam struct uba_device *ui; 80212503Ssam struct rkst *st; 80312503Ssam 80412503Ssam if (unit >= NRK || (ui = rkdinfo[unit]) == 0 || ui->ui_alive == 0) 80512503Ssam return (-1); 80612503Ssam st = &rkst[ui->ui_type]; 80712503Ssam return (st->sizes[minor(dev) & 07].nblocks); 80812503Ssam } 8092618Swnj #endif 810