123237Smckusick /*
235052Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
323237Smckusick * All rights reserved. The Berkeley software License Agreement
423237Smckusick * specifies the terms and conditions for redistribution.
523237Smckusick *
6*49100Sbostic * @(#)rk.c 7.10 (Berkeley) 05/04/91
723237Smckusick */
81915Swnj
91915Swnj /*
103263Swnj * RK611/RK07
111915Swnj */
1245803Sbostic #include "sys/param.h"
1345803Sbostic #include "sys/disklabel.h"
141915Swnj
1545803Sbostic #include "../include/pte.h"
169186Ssam
1745803Sbostic #include "../uba/ubareg.h"
1845803Sbostic #include "../uba/rkreg.h"
199186Ssam
2045803Sbostic #include "stand/saio.h"
213263Swnj #include "savax.h"
221915Swnj
2333541Sbostic #define SECTSIZ 512 /* sector size in bytes */
2430547Skarels
2533541Sbostic #define MAXCTLR 1 /* all addresses must be specified */
2635052Skarels #define MAXUNIT 8
2733541Sbostic u_short rkstd[MAXCTLR] = { 0777440 };
2835052Skarels struct disklabel rklabel[MAXNUBA][MAXCTLR][MAXUNIT];
2930547Skarels char lbuf[SECTSIZ];
301915Swnj
rkopen(io)311915Swnj rkopen(io)
323263Swnj register struct iob *io;
331915Swnj {
3433541Sbostic register struct rkdevice *rkaddr;
3533541Sbostic register struct disklabel *lp;
3630547Skarels struct iob tio;
371915Swnj
3835052Skarels if ((u_int)io->i_adapt >= nuba)
3935052Skarels return (EADAPT);
4033541Sbostic if ((u_int)io->i_ctlr >= MAXCTLR)
4133541Sbostic return (ECTLR);
4235052Skarels if ((u_int)io->i_unit >= MAXUNIT)
4335052Skarels return (EUNIT);
4433541Sbostic rkaddr = (struct rkdevice *)ubamem(io->i_adapt, rkstd[io->i_ctlr]);
4533548Sbostic if (badaddr((char *)rkaddr, sizeof(short)))
4630547Skarels return (ENXIO);
473349Swnj rkaddr->rkcs2 = RKCS2_SCLR;
483349Swnj rkwait(rkaddr);
4930547Skarels /*
5030547Skarels * Read in the pack label.
5130547Skarels */
5233541Sbostic lp = &rklabel[io->i_adapt][io->i_ctlr][io->i_unit];
5330547Skarels lp->d_nsectors = NRKSECT;
5430547Skarels lp->d_secpercyl = NRKTRK*NRKSECT;
5530547Skarels tio = *io;
5630547Skarels tio.i_bn = LABELSECTOR;
5730547Skarels tio.i_ma = lbuf;
5830547Skarels tio.i_cc = SECTSIZ;
5930547Skarels tio.i_flgs |= F_RDDATA;
60*49100Sbostic if (rkstrategy(&tio, F_READ) != SECTSIZ)
6133636Sbostic return (ERDLAB);
6230547Skarels *lp = *(struct disklabel *)(lbuf + LABELOFFSET);
6333636Sbostic if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC)
6433636Sbostic #ifdef COMPAT_42
6533636Sbostic {
6633541Sbostic printf("rk%d: unlabeled\n", io->i_unit);
6730547Skarels rkmaptype(io, lp);
6833636Sbostic }
6930547Skarels #else
7033636Sbostic return (EUNLAB);
7130547Skarels #endif
7233541Sbostic if ((u_int)io->i_part >= lp->d_npartitions ||
7333541Sbostic (io->i_boff = lp->d_partitions[io->i_part].p_offset) == -1)
7433541Sbostic return (EPART);
7530547Skarels return (0);
761915Swnj }
771915Swnj
7830547Skarels #ifdef COMPAT_42
7930547Skarels u_long rk_off[] = { 0, 241, 0, -1, -1, -1, 393, -1 };
8030547Skarels
8130547Skarels rkmaptype(io, lp)
8233408Skarels struct iob *io;
8330547Skarels register struct disklabel *lp;
8430547Skarels {
8530547Skarels register struct partition *pp;
8630547Skarels register u_long *off = rk_off;
8733541Sbostic register int i;
8830547Skarels
8930547Skarels lp->d_npartitions = 8;
9030547Skarels pp = lp->d_partitions;
9130547Skarels for (i = 0; i < 8; i++, pp++)
9230547Skarels pp->p_offset = *off++;
9330547Skarels }
9430547Skarels #endif
9530547Skarels
rkstrategy(io,func)961915Swnj rkstrategy(io, func)
973263Swnj register struct iob *io;
981915Swnj {
9933541Sbostic register struct rkdevice *rkaddr;
10033408Skarels register daddr_t bn;
10133541Sbostic int com, ubinfo, errcnt = 0;
10233408Skarels short cn, sn, tn;
1031915Swnj
10433541Sbostic rkaddr = (struct rkdevice *)ubamem(io->i_adapt, rkstd[io->i_ctlr]);
1053349Swnj retry:
1061915Swnj ubinfo = ubasetup(io, 1);
1071915Swnj bn = io->i_bn;
10833408Skarels cn = bn / (NRKSECT*NRKTRK);
10933408Skarels sn = bn % NRKSECT;
1103263Swnj tn = (bn / NRKSECT) % NRKTRK;
11133541Sbostic rkaddr->rkcs2 = io->i_unit;
1123263Swnj rkaddr->rkcs1 = RK_CDT|RK_PACK|RK_GO;
1133263Swnj rkwait(rkaddr);
1143349Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
1153349Swnj rkwait(rkaddr);
1163263Swnj rkaddr->rkda = sn | (tn << 8);
1173263Swnj rkaddr->rkcyl = cn;
1183263Swnj rkaddr->rkba = ubinfo;
1193263Swnj rkaddr->rkwc = -(io->i_cc >> 1);
1204038Swnj com = RK_CDT|((ubinfo>>8)&0x300)|RK_GO;
121*49100Sbostic if (func == F_READ)
1223263Swnj com |= RK_READ;
1233263Swnj else
1243263Swnj com |= RK_WRITE;
1253263Swnj rkaddr->rkcs1 = com;
1263263Swnj rkwait(rkaddr);
1273349Swnj while ((rkaddr->rkds & RKDS_SVAL) == 0)
1281915Swnj ;
1293263Swnj ubafree(io, ubinfo);
1303263Swnj if (rkaddr->rkcs1 & RK_CERR) {
1313349Swnj printf("rk error: (cyl,trk,sec)=(%d,%d,%d) cs2=%b er=%b\n",
1323349Swnj cn, tn, sn, rkaddr->rkcs2, RKCS2_BITS,
1333349Swnj rkaddr->rker, RKER_BITS);
1343349Swnj rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO;
1353263Swnj rkwait(rkaddr);
13633541Sbostic if (errcnt++ == 10) {
1373349Swnj printf("rk: unrecovered error\n");
1383349Swnj return (-1);
1393349Swnj }
1403349Swnj goto retry;
1411915Swnj }
1423349Swnj if (errcnt)
1433349Swnj printf("rk: recovered by retry\n");
1441915Swnj return (io->i_cc);
1451915Swnj }
1463263Swnj
rkwait(rkaddr)1473263Swnj rkwait(rkaddr)
1483263Swnj register struct rkdevice *rkaddr;
1493263Swnj {
15033541Sbostic while ((rkaddr->rkcs1 & RK_CRDY) == 0);
1513263Swnj }
152