1738d1474Smckusick /*
252a732e2Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3738d1474Smckusick * All rights reserved. The Berkeley software License Agreement
4738d1474Smckusick * specifies the terms and conditions for redistribution.
5738d1474Smckusick *
6*d3ba9304Sbostic * @(#)rk.c 7.10 (Berkeley) 05/04/91
7738d1474Smckusick */
842d18ea7Swnj
942d18ea7Swnj /*
103323c3f1Swnj * RK611/RK07
1142d18ea7Swnj */
12805e418eSbostic #include "sys/param.h"
13805e418eSbostic #include "sys/disklabel.h"
1442d18ea7Swnj
15805e418eSbostic #include "../include/pte.h"
161330c7b2Ssam
17805e418eSbostic #include "../uba/ubareg.h"
18805e418eSbostic #include "../uba/rkreg.h"
191330c7b2Ssam
20805e418eSbostic #include "stand/saio.h"
213323c3f1Swnj #include "savax.h"
2242d18ea7Swnj
235780f38fSkarels #define SECTSIZ 512 /* sector size in bytes */
245780f38fSkarels
251d93295cSbostic #define MAXCTLR 1 /* all addresses must be specified */
2652a732e2Skarels #define MAXUNIT 8
271d93295cSbostic u_short rkstd[MAXCTLR] = { 0777440 };
2852a732e2Skarels struct disklabel rklabel[MAXNUBA][MAXCTLR][MAXUNIT];
295780f38fSkarels char lbuf[SECTSIZ];
3042d18ea7Swnj
rkopen(io)3142d18ea7Swnj rkopen(io)
3242d18ea7Swnj register struct iob *io;
3342d18ea7Swnj {
341d93295cSbostic register struct rkdevice *rkaddr;
351d93295cSbostic register struct disklabel *lp;
365780f38fSkarels struct iob tio;
3742d18ea7Swnj
3852a732e2Skarels if ((u_int)io->i_adapt >= nuba)
3952a732e2Skarels return (EADAPT);
401d93295cSbostic if ((u_int)io->i_ctlr >= MAXCTLR)
411d93295cSbostic return (ECTLR);
4252a732e2Skarels if ((u_int)io->i_unit >= MAXUNIT)
4352a732e2Skarels return (EUNIT);
441d93295cSbostic rkaddr = (struct rkdevice *)ubamem(io->i_adapt, rkstd[io->i_ctlr]);
45aaebc542Sbostic if (badaddr((char *)rkaddr, sizeof(short)))
465780f38fSkarels return (ENXIO);
47d79ba013Swnj rkaddr->rkcs2 = RKCS2_SCLR;
48d79ba013Swnj rkwait(rkaddr);
495780f38fSkarels /*
505780f38fSkarels * Read in the pack label.
515780f38fSkarels */
521d93295cSbostic lp = &rklabel[io->i_adapt][io->i_ctlr][io->i_unit];
535780f38fSkarels lp->d_nsectors = NRKSECT;
545780f38fSkarels lp->d_secpercyl = NRKTRK*NRKSECT;
555780f38fSkarels tio = *io;
565780f38fSkarels tio.i_bn = LABELSECTOR;
575780f38fSkarels tio.i_ma = lbuf;
585780f38fSkarels tio.i_cc = SECTSIZ;
595780f38fSkarels tio.i_flgs |= F_RDDATA;
60*d3ba9304Sbostic if (rkstrategy(&tio, F_READ) != SECTSIZ)
6193ba485dSbostic return (ERDLAB);
625780f38fSkarels *lp = *(struct disklabel *)(lbuf + LABELOFFSET);
6393ba485dSbostic if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC)
645780f38fSkarels #ifdef COMPAT_42
6593ba485dSbostic {
6693ba485dSbostic printf("rk%d: unlabeled\n", io->i_unit);
675780f38fSkarels rkmaptype(io, lp);
685780f38fSkarels }
6993ba485dSbostic #else
7093ba485dSbostic return (EUNLAB);
7193ba485dSbostic #endif
721d93295cSbostic if ((u_int)io->i_part >= lp->d_npartitions ||
731d93295cSbostic (io->i_boff = lp->d_partitions[io->i_part].p_offset) == -1)
741d93295cSbostic return (EPART);
755780f38fSkarels return (0);
765780f38fSkarels }
775780f38fSkarels
785780f38fSkarels #ifdef COMPAT_42
795780f38fSkarels u_long rk_off[] = { 0, 241, 0, -1, -1, -1, 393, -1 };
805780f38fSkarels
815780f38fSkarels rkmaptype(io, lp)
82eea9e99bSkarels struct iob *io;
835780f38fSkarels register struct disklabel *lp;
845780f38fSkarels {
855780f38fSkarels register struct partition *pp;
865780f38fSkarels register u_long *off = rk_off;
871d93295cSbostic register int i;
885780f38fSkarels
895780f38fSkarels lp->d_npartitions = 8;
905780f38fSkarels pp = lp->d_partitions;
915780f38fSkarels for (i = 0; i < 8; i++, pp++)
925780f38fSkarels pp->p_offset = *off++;
935780f38fSkarels }
945780f38fSkarels #endif
9542d18ea7Swnj
rkstrategy(io,func)9642d18ea7Swnj rkstrategy(io, func)
9742d18ea7Swnj register struct iob *io;
9842d18ea7Swnj {
991d93295cSbostic register struct rkdevice *rkaddr;
100eea9e99bSkarels register daddr_t bn;
1011d93295cSbostic int com, ubinfo, errcnt = 0;
102eea9e99bSkarels short cn, sn, tn;
10342d18ea7Swnj
1041d93295cSbostic rkaddr = (struct rkdevice *)ubamem(io->i_adapt, rkstd[io->i_ctlr]);
105d79ba013Swnj retry:
10642d18ea7Swnj ubinfo = ubasetup(io, 1);
10742d18ea7Swnj bn = io->i_bn;
1083323c3f1Swnj cn = bn / (NRKSECT*NRKTRK);
1093323c3f1Swnj sn = bn % NRKSECT;
1103323c3f1Swnj tn = (bn / NRKSECT) % NRKTRK;
1111d93295cSbostic rkaddr->rkcs2 = io->i_unit;
1123323c3f1Swnj rkaddr->rkcs1 = RK_CDT|RK_PACK|RK_GO;
1133323c3f1Swnj rkwait(rkaddr);
114d79ba013Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
115d79ba013Swnj rkwait(rkaddr);
1163323c3f1Swnj rkaddr->rkda = sn | (tn << 8);
1173323c3f1Swnj rkaddr->rkcyl = cn;
1183323c3f1Swnj rkaddr->rkba = ubinfo;
1193323c3f1Swnj rkaddr->rkwc = -(io->i_cc >> 1);
12035b83b9dSwnj com = RK_CDT|((ubinfo>>8)&0x300)|RK_GO;
121*d3ba9304Sbostic if (func == F_READ)
1223323c3f1Swnj com |= RK_READ;
1233323c3f1Swnj else
1243323c3f1Swnj com |= RK_WRITE;
1253323c3f1Swnj rkaddr->rkcs1 = com;
1263323c3f1Swnj rkwait(rkaddr);
127d79ba013Swnj while ((rkaddr->rkds & RKDS_SVAL) == 0)
12842d18ea7Swnj ;
1293323c3f1Swnj ubafree(io, ubinfo);
1303323c3f1Swnj if (rkaddr->rkcs1 & RK_CERR) {
131d79ba013Swnj printf("rk error: (cyl,trk,sec)=(%d,%d,%d) cs2=%b er=%b\n",
132d79ba013Swnj cn, tn, sn, rkaddr->rkcs2, RKCS2_BITS,
133d79ba013Swnj rkaddr->rker, RKER_BITS);
134d79ba013Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
1353323c3f1Swnj rkwait(rkaddr);
1361d93295cSbostic if (errcnt++ == 10) {
137d79ba013Swnj printf("rk: unrecovered error\n");
13842d18ea7Swnj return (-1);
13942d18ea7Swnj }
140d79ba013Swnj goto retry;
141d79ba013Swnj }
142d79ba013Swnj if (errcnt)
143d79ba013Swnj printf("rk: recovered by retry\n");
14442d18ea7Swnj return (io->i_cc);
14542d18ea7Swnj }
1463323c3f1Swnj
rkwait(rkaddr)1473323c3f1Swnj rkwait(rkaddr)
1483323c3f1Swnj register struct rkdevice *rkaddr;
1493323c3f1Swnj {
1501d93295cSbostic while ((rkaddr->rkcs1 & RK_CRDY) == 0);
151256ba4caSsam }
152