1 /*
2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)uda.c 7.12 (Berkeley) 05/04/91
7 */
8
9 /*
10 * UDA50/RAxx disk device driver
11 */
12
13 #include "sys/param.h"
14 #include "sys/buf.h"
15 #include "sys/disklabel.h"
16
17 #include "../include/pte.h"
18
19 #include "stand/saio.h"
20 #include "savax.h"
21
22 /*
23 * Unused, but needed in udareg.h
24 */
25 #define NRSP 1
26 #define NCMD 1
27
28 #include "../uba/udareg.h"
29 #include "../uba/ubareg.h"
30 #include "../uba/ubavar.h"
31 #include "../vax/mscp.h"
32
33 #define NRA 8 /* max. unit number on controller */
34 #define SECTSIZ 512 /* sector size in bytes */
35
36 #define MAXCTLR 1 /* all addresses must be specified */
37 u_short udastd[MAXCTLR] = { 0772150 };
38
39 struct udadevice *udaddr[MAXNUBA][MAXCTLR];
40
41 struct uda1 {
42 struct uda1ca uda1_ca; /* communications area */
43 struct mscp uda1_rsp; /* response packet */
44 struct mscp uda1_cmd; /* command packet */
45 } uda1;
46
47 /* Unibus address of uda structure */
48 struct uda1 *ud_ubaddr[MAXNUBA][MAXCTLR];
49 struct disklabel ralabel[MAXNUBA][MAXCTLR][NRA];
50 static u_long ramedia[MAXNUBA][MAXCTLR][NRA];
51 char lbuf[SECTSIZ];
52
raopen(io)53 raopen(io)
54 register struct iob *io;
55 {
56 register struct disklabel *lp;
57 register struct udadevice *addr;
58 register struct uda1 *ubaaddr;
59 register int uba, unit;
60 static int udainit[MAXNUBA][MAXCTLR];
61 struct iob tio;
62
63 if ((u_int)(uba = io->i_adapt) >= nuba)
64 return (EADAPT);
65 if ((u_int)io->i_ctlr >= MAXCTLR)
66 return (ECTLR);
67 if ((u_int)(unit = io->i_unit) >= NRA)
68 return (EUNIT);
69 addr = udaddr[uba][io->i_ctlr] =
70 (struct udadevice *)ubamem(uba, udastd[io->i_ctlr]);
71 if (badaddr((char *)addr, sizeof(short)))
72 return (ENXIO);
73 if ((ubaaddr = ud_ubaddr[uba][io->i_ctlr]) == 0) {
74 tio = *io;
75 tio.i_ma = (caddr_t)&uda1;
76 tio.i_cc = sizeof(uda1);
77 ud_ubaddr[uba][io->i_ctlr] = ubaaddr =
78 (struct uda1 *)ubasetup(&tio, 2);
79 }
80 if (udainit[uba][io->i_ctlr] == 0) {
81 addr->udaip = 0;
82 while ((addr->udasa & UDA_STEP1) == 0);
83 addr->udasa = UDA_ERR;
84 while ((addr->udasa & UDA_STEP2) == 0);
85 addr->udasa = (int)&ubaaddr->uda1_ca.ca_rspdsc;
86 while ((addr->udasa & UDA_STEP3) == 0);
87 addr->udasa = (int)&ubaaddr->uda1_ca.ca_rspdsc >> 16;
88 while ((addr->udasa & UDA_STEP4) == 0);
89 addr->udasa = UDA_GO;
90 uda1.uda1_ca.ca_rspdsc = (long)&ubaaddr->uda1_rsp.mscp_cmdref;
91 uda1.uda1_ca.ca_cmddsc = (long)&ubaaddr->uda1_cmd.mscp_cmdref;
92 /* uda1.uda1_cmd.mscp_cntflgs = 0; */
93 if (udcmd(M_OP_SETCTLRC, io)) {
94 printf("ra: open error, SETCTLRC\n");
95 return (ENXIO);
96 }
97 udainit[uba][io->i_ctlr] = 1;
98 }
99 lp = &ralabel[uba][io->i_ctlr][unit];
100 if (ramedia[uba][io->i_ctlr][unit] == 0) {
101 uda1.uda1_cmd.mscp_unit = unit;
102 if (udcmd(M_OP_ONLINE, io)) {
103 printf("ra: open error, ONLINE\n");
104 return (ENXIO);
105 }
106 ramedia[uba][io->i_ctlr][unit] =
107 uda1.uda1_rsp.mscp_onle.onle_mediaid;
108 tio = *io;
109 tio.i_bn = LABELSECTOR;
110 tio.i_ma = lbuf;
111 tio.i_cc = SECTSIZ;
112 tio.i_flgs |= F_RDDATA;
113 if (rastrategy(&tio, F_READ) != SECTSIZ)
114 return (ERDLAB);
115 *lp = *(struct disklabel *)(lbuf + LABELOFFSET);
116 if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC) {
117 #ifdef COMPAT_42
118 printf("ra%d: unlabeled\n", unit);
119 ramaptype(io, lp);
120 #else
121 return (EUNLAB);
122 #endif
123 }
124 }
125 if ((u_int)io->i_part >= lp->d_npartitions ||
126 (io->i_boff = lp->d_partitions[io->i_part].p_offset) == -1)
127 return (EPART);
128 return (0);
129 }
130
131 int
udcmd(op,io)132 udcmd(op, io)
133 int op;
134 register struct iob *io;
135 {
136 register struct uda1 *u = &uda1;
137 register struct mscp *mp;
138 register int i;
139
140 u->uda1_cmd.mscp_opcode = op;
141 u->uda1_cmd.mscp_msglen = MSCP_MSGLEN;
142 u->uda1_rsp.mscp_msglen = MSCP_MSGLEN;
143 u->uda1_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT;
144 u->uda1_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT;
145 i = udaddr[io->i_adapt][io->i_ctlr]->udaip; /* start uda polling */
146 #ifdef lint
147 i = i;
148 #endif
149 mp = &u->uda1_rsp;
150 for (;;) {
151 if (u->uda1_ca.ca_cmdint)
152 u->uda1_ca.ca_cmdint = 0;
153 if (u->uda1_ca.ca_rspint == 0)
154 continue;
155 u->uda1_ca.ca_rspint = 0;
156 if (mp->mscp_opcode == (op | M_OP_END))
157 break;
158 printf("unexpected rsp type %x op %x ignored\n",
159 MSCP_MSGTYPE(mp->mscp_msgtc), mp->mscp_opcode);
160 u->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT;
161 }
162 if ((mp->mscp_status&M_ST_MASK) != M_ST_SUCCESS)
163 return (-1);
164 return (0);
165 }
166
rastrategy(io,func)167 rastrategy(io, func)
168 register struct iob *io;
169 int func;
170 {
171 register struct mscp *mp;
172 register int ubinfo;
173
174 ubinfo = ubasetup(io, 1);
175 mp = &uda1.uda1_cmd;
176 mp->mscp_unit = io->i_unit;
177 mp->mscp_seq.seq_lbn = io->i_bn;
178 mp->mscp_seq.seq_bytecount = io->i_cc;
179 mp->mscp_seq.seq_buffer = UBAI_ADDR(ubinfo) | (UBAI_BDP(ubinfo) << 24);
180 if (udcmd(func == F_READ ? M_OP_READ : M_OP_WRITE, io)) {
181 printf("ra: I/O error\n");
182 ubafree(io, ubinfo);
183 return (-1);
184 }
185 ubafree(io, ubinfo);
186 return (io->i_cc);
187 }
188
189 #ifdef COMPAT_42
190 u_long rc25_off[] = { 0, 15884, 0, -1, -1, -1, 25916, -1 };
191 u_long rx50_off[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
192 u_long rd52_off[] = { 0, 15884, 0, 0, 0, 0, 25650, 0 };
193 u_long rd53_off[] = { 0, 15884, 0, 0, 0, 33440, 49324, 15884 };
194 u_long ra60_off[] = { 0, 15884, 0, 49324, 131404, 49324, 242606, 49324 };
195 #define ra70_off ra60_off
196 u_long ra80_off[] = { 0, 15884, 0, -1, 49324, 49324, 49910, 131404 };
197 #ifndef UCBRA
198 #ifdef RA_COMPAT
199 u_long ra81_off[] = { 0, 16422, 0, 49324, 131404, 412490, 375564, 83538 };
200 #else
201 u_long ra81_off[] = { 0, 16422, 0, 375564, 391986, 699720, 375564, 83538 };
202 #endif
203 #else
204 u_long ra81_off[] = { 0, 15884, 0, 242606, 258490, 565690, 242606, 49324 };
205 #endif
206 u_long ra82_off[] = { 0, 15884, 0, 375345, 391590, 699390, 375345, 83790 };
207
208 struct mediamap {
209 u_long id; /* media ID */
210 u_long *off; /* offsets */
211 } ra_map[] = {
212 { MSCP_MKDRIVE2('R', 'A', 60), ra60_off },
213 { MSCP_MKDRIVE2('R', 'A', 70), ra70_off },
214 { MSCP_MKDRIVE2('R', 'A', 80), ra80_off },
215 { MSCP_MKDRIVE2('R', 'A', 81), ra81_off },
216 { MSCP_MKDRIVE2('R', 'A', 82), ra82_off },
217 { MSCP_MKDRIVE2('R', 'C', 25), rc25_off },
218 { MSCP_MKDRIVE3('R', 'C', 'F', 25), rc25_off },
219 { MSCP_MKDRIVE2('R', 'D', 52), rd52_off },
220 { MSCP_MKDRIVE2('R', 'D', 53), rd53_off },
221 { MSCP_MKDRIVE2('R', 'X', 50), rx50_off },
222 0
223 };
224
ramaptype(io,lp)225 ramaptype(io, lp)
226 register struct iob *io;
227 register struct disklabel *lp;
228 {
229 register struct partition *pp;
230 register u_long i;
231 register struct mediamap *map;
232
233 i = MSCP_MEDIA_DRIVE(ramedia[io->i_adapt][io->i_ctlr][io->i_unit]);
234 for (map = ra_map; map->id != 0; map++) {
235 if (map->id == i) {
236 lp->d_npartitions = 8;
237 for (pp = lp->d_partitions, i = 0; i < 8; pp++, i++)
238 pp->p_offset = map->off[i];
239 return;
240 }
241 }
242 printf("ra%d: media type 0x%x unsupported\n", io->i_unit, i);
243 lp->d_npartitions = 0;
244 }
245 #endif
246