1: /*
2: * RL disk driver
3: *
4: * RL driver modified for the standalone shell.
5: * Armando P. Stettner Digital Equipment Corp. July, 1980
6: */
7:
8: #include <sys/param.h>
9: #include <sys/inode.h>
10: #include "../saio.h"
11:
12: #define BLKRL1 10240 /* Number of UNIX blocks for an RL01 drive */
13: #define BLKRL2 20480 /* Number of UNIX blocks for an RL02 drive */
14: #define RLCYLSZ 10240 /* bytes per cylinder */
15: #define RLSECSZ 256 /* bytes per sector */
16:
17: #define RESET 013
18: #define RL02TYP 0200 /* drive type bit */
19: #define STAT 03
20: #define GETSTAT 04
21: #define WCOM 012
22: #define RCOM 014
23: #define SEEK 06
24: #define SEEKHI 5
25: #define SEEKLO 1
26: #define RDHDR 010
27: #define IENABLE 0100
28: #define CRDY 0200
29: #define OPI 02000
30: #define CRCERR 04000
31: #define TIMOUT 010000
32: #define NXM 020000
33: #define DE 040000
34:
35: struct device
36: {
37: int rlcs ,
38: rlba ,
39: rlda ,
40: rlmp ;
41: } ;
42:
43: #define RLADDR ((struct device *)0174400)
44: #define RL_CNT 1
45:
46: struct
47: {
48: int cn[4] ; /* location of heads for each drive */
49: int type[4] ; /* parameter dependent upon drive type (RL01/02) */
50: int com ; /* read or write command word */
51: int chn ; /* cylinder and head number */
52: unsigned int bleft ; /* bytes left to be transferred */
53: unsigned int bpart ; /* number of bytes transferred */
54: int sn ; /* sector number */
55: union {
56: int w[2] ;
57: long l ;
58: } addr ; /* address of memory for transfer */
59:
60: } rl = {-1,-1,-1,-1, -1,-1,-1,-1} ; /* initialize cn[] and type[] */
61:
62: rlstrategy(io, func)
63: register struct iob *io ;
64: int func ;
65: {
66: int nblocks ; /* number of UNIX blocks for the drive in question */
67: int drive ;
68: int dif ;
69: int head ;
70: int ctr ;
71:
72:
73: /*
74: * We must determine what type of drive we are talking to in order
75: * to determine how many blocks are on the device. The rl.type[]
76: * array has been initialized with -1's so that we may test first
77: * contact with a particular drive and do this determination only once.
78: * Sorry tjk for this hack.
79: *
80: * RL02 GET STATUS BAND-AID - Fred Canter 10/14/80
81: *
82: * For some unknown reason the RL02 (seems to be
83: * only drive 1) does not return a valid drive status
84: * the first time that a GET STATUS request is issued
85: * for the drive, in fact it can take up to three or more
86: * GET STATUS requests to obtain the correct status.
87: * In order to overcome this "HACK" the driver has been
88: * modified to issue a GET STATUS request, validate the
89: * drive status returned, and then use it to determine the
90: * drive type. If a valid status is not returned after eight
91: * attempts, then an error message is printed.
92: */
93: drive = io->i_unit ;
94: if (rl.type[drive] < 0)
95: {
96: ctr = 0;
97: do {
98: RLADDR->rlda = RESET ; /* load this register; what a dumb controller */
99: RLADDR->rlcs = (drive << 8) | GETSTAT ; /* set up csr */
100: while ((RLADDR->rlcs & CRDY) == 0) /* wait for it */
101: ;
102: } while (((RLADDR->rlmp & 0177477) != 035) && (++ctr < 8)) ;
103: if (ctr >= 8)
104: printf("\nCan't get status of RL unit %d\n",drive) ;
105: if (RLADDR->rlmp & RL02TYP)
106: rl.type[drive] = BLKRL2 ; /* drive is RL02 */
107: else
108: rl.type[drive] = BLKRL1 ; /* drive RL01 */
109: /*
110: * When the device is first touched, find out where the heads are.
111: */
112: /* find where the heads are */
113: RLADDR->rlcs = (drive << 8) | RDHDR;
114: while ((RLADDR->rlcs&CRDY) == 0)
115: ;
116: /*rl.cn[drive] = (RLADDR->rlmp&0177700) >> 6;*/
117: rl.cn[drive] = ((RLADDR->rlmp) >> 6) & 01777; /* fix sign bug */
118: }
119: nblocks = rl.type[drive] ; /* how many blocks on this drive */
120: if(io->i_bn >= nblocks)
121: return -1 ;
122: rl.chn = io->i_bn/20;
123: rl.sn = (io->i_bn%20) << 1;
124: rl.bleft = io->i_cc;
125: rl.addr.w[0] = segflag & 3;
126: rl.addr.w[1] = (int)io->i_ma ;
127: rl.com = (drive << 8) ;
128: if (func == READ)
129: rl.com |= RCOM;
130: else
131: rl.com |= WCOM;
132: reading:
133: /*
134: * One has to seek an RL head, relativily.
135: */
136: dif =(rl.cn[drive] >> 1) - (rl.chn >>1);
137: head = (rl.chn & 1) << 4;
138: if (dif < 0)
139: RLADDR->rlda = (-dif <<7) | SEEKHI | head;
140: else
141: RLADDR->rlda = (dif << 7) | SEEKLO | head;
142: RLADDR->rlcs = (drive << 8) | SEEK;
143: rl.cn[drive] = rl.chn; /* keep current, our notion of where the heads are */
144: if (rl.bleft < (rl.bpart = RLCYLSZ - (rl.sn * RLSECSZ)))
145: rl.bpart = rl.bleft;
146: while ((RLADDR->rlcs&CRDY) == 0) ;
147: RLADDR->rlda = (rl.chn << 6) | rl.sn;
148: RLADDR->rlba = rl.addr.w[1];
149: RLADDR->rlmp = -(rl.bpart >> 1);
150: RLADDR->rlcs = rl.com | rl.addr.w[0] << 4;
151: while ((RLADDR->rlcs & CRDY) == 0) /* wait for completion */
152: ;
153: if (RLADDR->rlcs < 0) /* check error bit */
154: {
155: if (RLADDR->rlcs & 040000) /* Drive error */
156: {
157: /*
158: * get status from drive
159: */
160: RLADDR->rlda = STAT;
161: RLADDR->rlcs = (drive << 8) | GETSTAT;
162: while ((RLADDR->rlcs & CRDY) == 0) /* wait for controller */
163: ;
164: }
165: printf("Rl disk error: cyl=%d, head=%d, sector=%d, rlcs=%o, rlmp=%o\n",
166: rl.chn>>01, rl.chn&01, rl.sn, RLADDR->rlcs, RLADDR->rlmp) ;
167: return -1 ;
168: }
169: /*
170: * Determine if there is more to read to satisfy this request.
171: * This is to compensate for the lacl of spiraling reads.
172: */
173: if ((rl.bleft -= rl.bpart) > 0)
174: {
175: rl.addr.l += rl.bpart ;
176: rl.sn = 0 ;
177: rl.chn++ ;
178: goto reading ; /* read some more */
179: }
180: return io->i_cc ;
181: }
Defined functions
Defined struct's
Defined macros
CRDY
defined in line
28; used 5 times
DE
defined in line
33;
never used
NXM
defined in line
32;
never used
OPI
defined in line
29;
never used
RCOM
defined in line
22; used 1 times
RDHDR
defined in line
26; used 1 times
RESET
defined in line
17; used 1 times
RLADDR
defined in line
43; used 24 times
SEEK
defined in line
23; used 1 times
STAT
defined in line
19; used 1 times
WCOM
defined in line
21; used 1 times