iris_scsi.c revision 1.1 1 1.1 tsutsui /* $NetBSD: iris_scsi.c,v 1.1 2019/01/12 16:44:47 tsutsui Exp $ */
2 1.1 tsutsui
3 1.1 tsutsui /*
4 1.1 tsutsui * Copyright (c) 2018 Naruaki Etomi
5 1.1 tsutsui * All rights reserved.
6 1.1 tsutsui *
7 1.1 tsutsui * Redistribution and use in source and binary forms, with or without
8 1.1 tsutsui * modification, are permitted provided that the following conditions
9 1.1 tsutsui * are met:
10 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright
11 1.1 tsutsui * notice, this list of conditions and the following disclaimer.
12 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the
14 1.1 tsutsui * documentation and/or other materials provided with the distribution.
15 1.1 tsutsui *
16 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.1 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.1 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.1 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.1 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.1 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.1 tsutsui */
27 1.1 tsutsui
28 1.1 tsutsui /*
29 1.1 tsutsui * Silicon Graphics "IRIS" series MIPS processors machine bootloader.
30 1.1 tsutsui * WD33C93 SCSI bus driver for standalone programs.
31 1.1 tsutsui */
32 1.1 tsutsui
33 1.1 tsutsui #include <sys/cdefs.h>
34 1.1 tsutsui #include <lib/libsa/stand.h>
35 1.1 tsutsui
36 1.1 tsutsui #ifndef INDIGO_R3K_MODE
37 1.1 tsutsui #include <dev/arcbios/arcbios.h>
38 1.1 tsutsui #endif
39 1.1 tsutsui
40 1.1 tsutsui #include "iris_machdep.h"
41 1.1 tsutsui #include "iris_scsivar.h"
42 1.1 tsutsui #include "iris_scsireg.h"
43 1.1 tsutsui #include "iris_scsicmd.h"
44 1.1 tsutsui #include <dev/scsipi/scsi_message.h>
45 1.1 tsutsui
46 1.1 tsutsui #define SBIC_WAIT(regs, until, timeo) wd33c93_wait(regs, until, timeo)
47 1.1 tsutsui
48 1.1 tsutsui /*
49 1.1 tsutsui * Timeouts
50 1.1 tsutsui */
51 1.1 tsutsui int wd33c93_cmd_wait = SBIC_CMD_WAIT;
52 1.1 tsutsui int wd33c93_data_wait = SBIC_DATA_WAIT;
53 1.1 tsutsui int wd33c93_init_wait = SBIC_INIT_WAIT;
54 1.1 tsutsui
55 1.1 tsutsui #define STATUS_UNKNOWN 0xff
56 1.1 tsutsui
57 1.1 tsutsui void wd33c93_reset(struct wd33c93_softc *);
58 1.1 tsutsui int wd33c93_wait(struct wd33c93_softc *, uint8_t, int);
59 1.1 tsutsui uint8_t wd33c93_selectbus(struct wd33c93_softc *, uint8_t *, size_t, uint8_t *,
60 1.1 tsutsui size_t *);
61 1.1 tsutsui void wd33c93_setsync(struct wd33c93_softc *);
62 1.1 tsutsui int wd33c93_nextstate(struct wd33c93_softc *, uint8_t *, size_t, uint8_t *,
63 1.1 tsutsui size_t *, uint8_t, uint8_t);
64 1.1 tsutsui size_t wd33c93_xfout(struct wd33c93_softc *, void *, size_t *);
65 1.1 tsutsui int wd33c93_intr(struct wd33c93_softc *, uint8_t *, size_t, uint8_t *,
66 1.1 tsutsui size_t *);
67 1.1 tsutsui size_t wd33c93_xfin(struct wd33c93_softc *, void *, size_t *);
68 1.1 tsutsui void wd33c93_xferdone(struct wd33c93_softc *);
69 1.1 tsutsui int wd33c93_abort(struct wd33c93_softc *, uint8_t *, size_t, uint8_t *,
70 1.1 tsutsui size_t *);
71 1.1 tsutsui int wd33c93_poll(struct wd33c93_softc *, uint8_t *, size_t, uint8_t *,
72 1.1 tsutsui size_t *);
73 1.1 tsutsui void wd33c93_timeout(struct wd33c93_softc *, uint8_t *, size_t, uint8_t *,
74 1.1 tsutsui size_t *);
75 1.1 tsutsui int wd33c93_msgin_phase(struct wd33c93_softc *);
76 1.1 tsutsui void wd33c93_scsistart(struct wd33c93_softc *);
77 1.1 tsutsui void wd33c93_scsidone(struct wd33c93_softc *);
78 1.1 tsutsui void wd33c93_error(struct wd33c93_softc *);
79 1.1 tsutsui
80 1.1 tsutsui /*
81 1.1 tsutsui * Initialize SPC & Data Structure
82 1.1 tsutsui */
83 1.1 tsutsui void
84 1.1 tsutsui wd33c93_init(void *aaddr, void *daddr)
85 1.1 tsutsui {
86 1.1 tsutsui struct wd33c93_softc *sc;
87 1.1 tsutsui
88 1.1 tsutsui sc = &wd33c93_softc[scsi_ctlr];
89 1.1 tsutsui
90 1.1 tsutsui sc->sc_asr_regh = aaddr;
91 1.1 tsutsui sc->sc_data_regh = daddr;
92 1.1 tsutsui sc->sc_target = scsi_id;
93 1.1 tsutsui
94 1.1 tsutsui sc->sc_flags = 0;
95 1.1 tsutsui sc->sc_state = SBIC_IDLE;
96 1.1 tsutsui
97 1.1 tsutsui wd33c93_reset(sc);
98 1.1 tsutsui }
99 1.1 tsutsui
100 1.1 tsutsui void
101 1.1 tsutsui wd33c93_reset(struct wd33c93_softc *sc)
102 1.1 tsutsui {
103 1.1 tsutsui u_int my_id;
104 1.1 tsutsui uint8_t csr;
105 1.1 tsutsui
106 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_ABORT);
107 1.1 tsutsui WAIT_CIP(sc);
108 1.1 tsutsui
109 1.1 tsutsui my_id = sc->sc_target & SBIC_ID_MASK;
110 1.1 tsutsui
111 1.1 tsutsui /* Set Clock == 20.0 MHz */
112 1.1 tsutsui my_id |= SBIC_ID_FS_8_10;
113 1.1 tsutsui sc->sc_syncperiods = 2 * 2 * 1250 / SCSI_CLKFREQ;
114 1.1 tsutsui
115 1.1 tsutsui SET_SBIC_myid(sc, my_id);
116 1.1 tsutsui
117 1.1 tsutsui /* Reset the chip */
118 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_RESET);
119 1.1 tsutsui DELAY(25);
120 1.1 tsutsui SBIC_WAIT(sc, SBIC_ASR_INT, 0);
121 1.1 tsutsui
122 1.1 tsutsui /* PIO mode */
123 1.1 tsutsui SBIC_TC_PUT(sc, 0);
124 1.1 tsutsui SET_SBIC_control(sc, SBIC_CTL_EDI | SBIC_CTL_IDI);
125 1.1 tsutsui
126 1.1 tsutsui /* clears interrupt also */
127 1.1 tsutsui GET_SBIC_csr(sc, csr);
128 1.1 tsutsui __USE(csr);
129 1.1 tsutsui
130 1.1 tsutsui SET_SBIC_rselid(sc, SBIC_RID_ER);
131 1.1 tsutsui SET_SBIC_syn(sc, 0);
132 1.1 tsutsui
133 1.1 tsutsui sc->sc_flags = 0;
134 1.1 tsutsui sc->sc_state = SBIC_IDLE;
135 1.1 tsutsui }
136 1.1 tsutsui
137 1.1 tsutsui int
138 1.1 tsutsui wd33c93_wait(struct wd33c93_softc *sc, uint8_t until, int timeo)
139 1.1 tsutsui {
140 1.1 tsutsui uint8_t val;
141 1.1 tsutsui
142 1.1 tsutsui if (timeo == 0)
143 1.1 tsutsui /* some large value.. */
144 1.1 tsutsui timeo = 1000000;
145 1.1 tsutsui
146 1.1 tsutsui GET_SBIC_asr(sc, val);
147 1.1 tsutsui
148 1.1 tsutsui while ((val & until) == 0) {
149 1.1 tsutsui if (timeo-- == 0) {
150 1.1 tsutsui return val;
151 1.1 tsutsui break;
152 1.1 tsutsui }
153 1.1 tsutsui DELAY(1);
154 1.1 tsutsui GET_SBIC_asr(sc, val);
155 1.1 tsutsui }
156 1.1 tsutsui return val;
157 1.1 tsutsui }
158 1.1 tsutsui
159 1.1 tsutsui /* SCSI command entry point */
160 1.1 tsutsui int
161 1.1 tsutsui wd33c93_go(struct wd33c93_softc *sc, uint8_t *cbuf, size_t clen, uint8_t *buf,
162 1.1 tsutsui size_t *lenp)
163 1.1 tsutsui {
164 1.1 tsutsui int i;
165 1.1 tsutsui uint8_t csr, asr;
166 1.1 tsutsui
167 1.1 tsutsui wd33c93_scsistart(sc);
168 1.1 tsutsui
169 1.1 tsutsui sc->sc_status = STATUS_UNKNOWN;
170 1.1 tsutsui sc->sc_flags = 0;
171 1.1 tsutsui /* select the SCSI bus (it's an error if bus isn't free) */
172 1.1 tsutsui if ((csr = wd33c93_selectbus(sc, cbuf, clen, buf, lenp)) == 0)
173 1.1 tsutsui /* Not done: needs to be rescheduled */
174 1.1 tsutsui return 1;
175 1.1 tsutsui
176 1.1 tsutsui /*
177 1.1 tsutsui * Lets cycle a while then let the interrupt handler take over.
178 1.1 tsutsui */
179 1.1 tsutsui GET_SBIC_asr(sc, asr);
180 1.1 tsutsui do {
181 1.1 tsutsui /* Handle the new phase */
182 1.1 tsutsui i = wd33c93_nextstate(sc, cbuf, clen, buf, lenp, csr, asr);
183 1.1 tsutsui WAIT_CIP(sc); /* XXX */
184 1.1 tsutsui if (sc->sc_state == SBIC_CONNECTED) {
185 1.1 tsutsui GET_SBIC_asr(sc, asr);
186 1.1 tsutsui
187 1.1 tsutsui if ((asr & SBIC_ASR_LCI) != 0)
188 1.1 tsutsui DELAY(5000);
189 1.1 tsutsui
190 1.1 tsutsui if ((asr & SBIC_ASR_INT) != 0)
191 1.1 tsutsui GET_SBIC_csr(sc, csr);
192 1.1 tsutsui }
193 1.1 tsutsui
194 1.1 tsutsui } while (sc->sc_state == SBIC_CONNECTED &&
195 1.1 tsutsui (asr & (SBIC_ASR_INT|SBIC_ASR_LCI)) != 0);
196 1.1 tsutsui
197 1.1 tsutsui if (i == SBIC_STATE_DONE) {
198 1.1 tsutsui if (sc->sc_status == STATUS_UNKNOWN) {
199 1.1 tsutsui printf("wd33c93_go: stat == UNKNOWN\n");
200 1.1 tsutsui return 1;
201 1.1 tsutsui }
202 1.1 tsutsui }
203 1.1 tsutsui
204 1.1 tsutsui if (wd33c93_poll(sc, cbuf, clen, buf, lenp)) {
205 1.1 tsutsui wd33c93_timeout(sc, cbuf, clen, buf, lenp);
206 1.1 tsutsui if (wd33c93_poll(sc, cbuf, clen, buf, lenp)) {
207 1.1 tsutsui wd33c93_timeout(sc, cbuf, clen, buf, lenp);
208 1.1 tsutsui }
209 1.1 tsutsui }
210 1.1 tsutsui return 0;
211 1.1 tsutsui }
212 1.1 tsutsui
213 1.1 tsutsui /*
214 1.1 tsutsui * select the bus, return when selected or error.
215 1.1 tsutsui *
216 1.1 tsutsui * Returns the current CSR following selection and optionally MSG out phase.
217 1.1 tsutsui * i.e. the returned CSR *should* indicate CMD phase...
218 1.1 tsutsui * If the return value is 0, some error happened.
219 1.1 tsutsui */
220 1.1 tsutsui uint8_t
221 1.1 tsutsui wd33c93_selectbus(struct wd33c93_softc *sc, uint8_t *cbuf, size_t clen,
222 1.1 tsutsui uint8_t *buf, size_t *lenp)
223 1.1 tsutsui {
224 1.1 tsutsui uint8_t asr, csr, id, lun, target;
225 1.1 tsutsui static int i = 0;
226 1.1 tsutsui
227 1.1 tsutsui sc->sc_state = SBIC_SELECTING;
228 1.1 tsutsui
229 1.1 tsutsui target = sc->sc_target;
230 1.1 tsutsui lun = SCSI_LUN;
231 1.1 tsutsui
232 1.1 tsutsui /*
233 1.1 tsutsui * issue select
234 1.1 tsutsui */
235 1.1 tsutsui SBIC_TC_PUT(sc, 0);
236 1.1 tsutsui SET_SBIC_selid(sc, target);
237 1.1 tsutsui SET_SBIC_timeo(sc, SBIC_TIMEOUT(250, SCSI_CLKFREQ));
238 1.1 tsutsui
239 1.1 tsutsui GET_SBIC_asr(sc, asr);
240 1.1 tsutsui
241 1.1 tsutsui if ((asr & (SBIC_ASR_INT|SBIC_ASR_BSY)) != 0) {
242 1.1 tsutsui return 0;
243 1.1 tsutsui }
244 1.1 tsutsui
245 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_SEL_ATN);
246 1.1 tsutsui WAIT_CIP(sc);
247 1.1 tsutsui
248 1.1 tsutsui /*
249 1.1 tsutsui * wait for select (merged from separate function may need
250 1.1 tsutsui * cleanup)
251 1.1 tsutsui */
252 1.1 tsutsui do {
253 1.1 tsutsui asr = SBIC_WAIT(sc, SBIC_ASR_INT | SBIC_ASR_LCI, 0);
254 1.1 tsutsui
255 1.1 tsutsui if ((asr & SBIC_ASR_LCI) != 0) {
256 1.1 tsutsui return 0;
257 1.1 tsutsui }
258 1.1 tsutsui
259 1.1 tsutsui /* Clear interrupt */
260 1.1 tsutsui GET_SBIC_csr(sc, csr);
261 1.1 tsutsui
262 1.1 tsutsui /* Reselected from under our feet? */
263 1.1 tsutsui if (csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY) {
264 1.1 tsutsui /*
265 1.1 tsutsui * We need to handle this now so we don't lock up later
266 1.1 tsutsui */
267 1.1 tsutsui wd33c93_nextstate(sc, cbuf, clen, buf, lenp, csr, asr);
268 1.1 tsutsui return 0;
269 1.1 tsutsui }
270 1.1 tsutsui /* Whoops! */
271 1.1 tsutsui if (csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN) {
272 1.1 tsutsui return 0;
273 1.1 tsutsui }
274 1.1 tsutsui } while (csr != (SBIC_CSR_MIS_2 | MESG_OUT_PHASE) &&
275 1.1 tsutsui csr != (SBIC_CSR_MIS_2 | CMD_PHASE) &&
276 1.1 tsutsui csr != SBIC_CSR_SEL_TIMEO);
277 1.1 tsutsui
278 1.1 tsutsui /* Anyone at home? */
279 1.1 tsutsui if (csr == SBIC_CSR_SEL_TIMEO) {
280 1.1 tsutsui return 0;
281 1.1 tsutsui }
282 1.1 tsutsui
283 1.1 tsutsui /* Assume we're now selected */
284 1.1 tsutsui GET_SBIC_selid(sc, id);
285 1.1 tsutsui
286 1.1 tsutsui if (id != target) {
287 1.1 tsutsui /* Something went wrong - wrong target was select */
288 1.1 tsutsui printf("wd33c93_selectbus: wrong target selected WANTED %d GOT %d \n",
289 1.1 tsutsui target, id);
290 1.1 tsutsui printf("Boot failed! Halting...\n");
291 1.1 tsutsui reboot();
292 1.1 tsutsui }
293 1.1 tsutsui
294 1.1 tsutsui sc->sc_flags |= SBICF_SELECTED;
295 1.1 tsutsui sc->sc_state = SBIC_CONNECTED;
296 1.1 tsutsui
297 1.1 tsutsui /* setup correct sync mode for this target */
298 1.1 tsutsui wd33c93_setsync(sc);
299 1.1 tsutsui SET_SBIC_rselid(sc, SBIC_RID_ER);
300 1.1 tsutsui
301 1.1 tsutsui /*
302 1.1 tsutsui * We only really need to do anything when the target goes to MSG out
303 1.1 tsutsui * If the device ignored ATN, it's probably old and brain-dead,
304 1.1 tsutsui * but we'll try to support it anyhow.
305 1.1 tsutsui * If it doesn't support message out, it definately doesn't
306 1.1 tsutsui * support synchronous transfers, so no point in even asking...
307 1.1 tsutsui */
308 1.1 tsutsui
309 1.1 tsutsui if (csr == (SBIC_CSR_MIS_2 | MESG_OUT_PHASE)) {
310 1.1 tsutsui if (i < 6) {
311 1.1 tsutsui SEND_BYTE(sc, MSG_IDENTIFY(lun, 0));
312 1.1 tsutsui DELAY(200000);
313 1.1 tsutsui i++;
314 1.1 tsutsui } else {
315 1.1 tsutsui /*
316 1.1 tsutsui * setup scsi message sync message request
317 1.1 tsutsui */
318 1.1 tsutsui sc->sc_omsg[0] = MSG_IDENTIFY(lun, 0);
319 1.1 tsutsui sc->sc_omsg[1] = MSG_EXTENDED;
320 1.1 tsutsui sc->sc_omsg[2] = MSG_EXT_SDTR_LEN;
321 1.1 tsutsui sc->sc_omsg[3] = MSG_EXT_SDTR;
322 1.1 tsutsui sc->sc_omsg[4] = sc->sc_syncperiods;
323 1.1 tsutsui sc->sc_omsg[5] = SBIC_SYN_93AB_MAX_OFFSET;
324 1.1 tsutsui
325 1.1 tsutsui size_t foo = 6;
326 1.1 tsutsui size_t *bar;
327 1.1 tsutsui bar = &foo;
328 1.1 tsutsui
329 1.1 tsutsui wd33c93_xfout(sc, sc->sc_omsg, bar);
330 1.1 tsutsui sc->sc_flags |= SBICF_SYNCNEGO;
331 1.1 tsutsui }
332 1.1 tsutsui
333 1.1 tsutsui SBIC_WAIT(sc, SBIC_ASR_INT , 0);
334 1.1 tsutsui GET_SBIC_csr(sc, csr);
335 1.1 tsutsui }
336 1.1 tsutsui return csr;
337 1.1 tsutsui }
338 1.1 tsutsui
339 1.1 tsutsui /*
340 1.1 tsutsui * Setup sync mode for given target
341 1.1 tsutsui */
342 1.1 tsutsui void
343 1.1 tsutsui wd33c93_setsync(struct wd33c93_softc *sc)
344 1.1 tsutsui {
345 1.1 tsutsui uint8_t syncreg;
346 1.1 tsutsui
347 1.1 tsutsui syncreg = SBIC_SYN(0, 0, 0);
348 1.1 tsutsui
349 1.1 tsutsui SET_SBIC_syn(sc, syncreg);
350 1.1 tsutsui }
351 1.1 tsutsui
352 1.1 tsutsui /*
353 1.1 tsutsui * wd33c93_nextstate()
354 1.1 tsutsui * return:
355 1.1 tsutsui * SBIC_STATE_DONE == done
356 1.1 tsutsui * SBIC_STATE_RUNNING == working
357 1.1 tsutsui * SBIC_STATE_DISCONNECT == disconnected
358 1.1 tsutsui * SBIC_STATE_ERROR == error
359 1.1 tsutsui */
360 1.1 tsutsui int
361 1.1 tsutsui wd33c93_nextstate(struct wd33c93_softc *sc, uint8_t *cbuf, size_t clen,
362 1.1 tsutsui uint8_t *buf, size_t *lenp, uint8_t csr, uint8_t asr)
363 1.1 tsutsui {
364 1.1 tsutsui size_t *clenp;
365 1.1 tsutsui size_t resid;
366 1.1 tsutsui
367 1.1 tsutsui switch (csr) {
368 1.1 tsutsui case SBIC_CSR_XFERRED | CMD_PHASE:
369 1.1 tsutsui case SBIC_CSR_MIS | CMD_PHASE:
370 1.1 tsutsui case SBIC_CSR_MIS_1 | CMD_PHASE:
371 1.1 tsutsui case SBIC_CSR_MIS_2 | CMD_PHASE:
372 1.1 tsutsui clenp = &clen;
373 1.1 tsutsui
374 1.1 tsutsui if (wd33c93_xfout(sc, cbuf, clenp))
375 1.1 tsutsui goto abort;
376 1.1 tsutsui break;
377 1.1 tsutsui
378 1.1 tsutsui case SBIC_CSR_XFERRED | STATUS_PHASE:
379 1.1 tsutsui case SBIC_CSR_MIS | STATUS_PHASE:
380 1.1 tsutsui case SBIC_CSR_MIS_1 | STATUS_PHASE:
381 1.1 tsutsui case SBIC_CSR_MIS_2 | STATUS_PHASE:
382 1.1 tsutsui SET_SBIC_control(sc, SBIC_CTL_EDI | SBIC_CTL_IDI);
383 1.1 tsutsui
384 1.1 tsutsui /*
385 1.1 tsutsui * this should be the normal i/o completion case.
386 1.1 tsutsui * get the status & cmd complete msg then let the
387 1.1 tsutsui * device driver look at what happened.
388 1.1 tsutsui */
389 1.1 tsutsui wd33c93_xferdone(sc);
390 1.1 tsutsui wd33c93_scsidone(sc);
391 1.1 tsutsui
392 1.1 tsutsui return SBIC_STATE_DONE;
393 1.1 tsutsui
394 1.1 tsutsui case SBIC_CSR_XFERRED | DATA_IN_PHASE:
395 1.1 tsutsui case SBIC_CSR_MIS | DATA_IN_PHASE:
396 1.1 tsutsui case SBIC_CSR_MIS_1 | DATA_IN_PHASE:
397 1.1 tsutsui case SBIC_CSR_MIS_2 | DATA_IN_PHASE:
398 1.1 tsutsui case SBIC_CSR_XFERRED | DATA_OUT_PHASE:
399 1.1 tsutsui case SBIC_CSR_MIS | DATA_OUT_PHASE:
400 1.1 tsutsui case SBIC_CSR_MIS_1 | DATA_OUT_PHASE:
401 1.1 tsutsui case SBIC_CSR_MIS_2 | DATA_OUT_PHASE:
402 1.1 tsutsui /*
403 1.1 tsutsui * Should we transfer using PIO or DMA ?
404 1.1 tsutsui */
405 1.1 tsutsui /* Perfrom transfer using PIO */
406 1.1 tsutsui if (SBIC_PHASE(csr) == DATA_IN_PHASE){
407 1.1 tsutsui /* data in */
408 1.1 tsutsui resid = wd33c93_xfin(sc, buf, lenp);
409 1.1 tsutsui *lenp = resid;
410 1.1 tsutsui wd33c93_intr(sc, cbuf, clen, buf, lenp);
411 1.1 tsutsui } else { /* data out */
412 1.1 tsutsui resid = wd33c93_xfout(sc, buf, lenp);
413 1.1 tsutsui *lenp = resid;
414 1.1 tsutsui }
415 1.1 tsutsui break;
416 1.1 tsutsui
417 1.1 tsutsui case SBIC_CSR_XFERRED | MESG_IN_PHASE:
418 1.1 tsutsui case SBIC_CSR_MIS | MESG_IN_PHASE:
419 1.1 tsutsui case SBIC_CSR_MIS_1 | MESG_IN_PHASE:
420 1.1 tsutsui case SBIC_CSR_MIS_2 | MESG_IN_PHASE:
421 1.1 tsutsui /* Handle a single message in... */
422 1.1 tsutsui return wd33c93_msgin_phase(sc);
423 1.1 tsutsui
424 1.1 tsutsui case SBIC_CSR_MSGIN_W_ACK:
425 1.1 tsutsui /*
426 1.1 tsutsui * We should never see this since it's handled in
427 1.1 tsutsui * 'wd33c93_msgin_phase()' but just for the sake of paranoia...
428 1.1 tsutsui */
429 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_CLR_ACK);
430 1.1 tsutsui break;
431 1.1 tsutsui
432 1.1 tsutsui case SBIC_CSR_XFERRED | MESG_OUT_PHASE:
433 1.1 tsutsui case SBIC_CSR_MIS | MESG_OUT_PHASE:
434 1.1 tsutsui case SBIC_CSR_MIS_1 | MESG_OUT_PHASE:
435 1.1 tsutsui case SBIC_CSR_MIS_2 | MESG_OUT_PHASE:
436 1.1 tsutsui /*
437 1.1 tsutsui * Message out phase. ATN signal has been asserted
438 1.1 tsutsui */
439 1.1 tsutsui return SBIC_STATE_RUNNING;
440 1.1 tsutsui
441 1.1 tsutsui case SBIC_CSR_DISC:
442 1.1 tsutsui case SBIC_CSR_DISC_1:
443 1.1 tsutsui sc->sc_state = SBIC_IDLE;
444 1.1 tsutsui sc->sc_flags = 0;
445 1.1 tsutsui
446 1.1 tsutsui return SBIC_STATE_DISCONNECT;
447 1.1 tsutsui
448 1.1 tsutsui case SBIC_CSR_RSLT_NI:
449 1.1 tsutsui case SBIC_CSR_RSLT_IFY:
450 1.1 tsutsui {
451 1.1 tsutsui sc->sc_state = SBIC_RESELECTED;
452 1.1 tsutsui
453 1.1 tsutsui if (csr == SBIC_CSR_RSLT_IFY)
454 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_CLR_ACK);
455 1.1 tsutsui break;
456 1.1 tsutsui }
457 1.1 tsutsui
458 1.1 tsutsui default:
459 1.1 tsutsui abort:
460 1.1 tsutsui /* Something unexpected happend -- deal with it. */
461 1.1 tsutsui printf("wd33c93_nextstate:abort\n");
462 1.1 tsutsui printf("Boot failed! Halting...\n");
463 1.1 tsutsui reboot();
464 1.1 tsutsui }
465 1.1 tsutsui return SBIC_STATE_RUNNING;
466 1.1 tsutsui }
467 1.1 tsutsui
468 1.1 tsutsui /*
469 1.1 tsutsui * Information Transfer *to* a SCSI Target.
470 1.1 tsutsui *
471 1.1 tsutsui * Note: Don't expect there to be an interrupt immediately after all
472 1.1 tsutsui * the data is transferred out. The WD spec sheet says that the Transfer-
473 1.1 tsutsui * Info command for non-MSG_IN phases only completes when the target
474 1.1 tsutsui * next asserts 'REQ'. That is, when the SCSI bus changes to a new state.
475 1.1 tsutsui *
476 1.1 tsutsui * This can have a nasty effect on commands which take a relatively long
477 1.1 tsutsui * time to complete, for example a START/STOP unit command may remain in
478 1.1 tsutsui * CMD phase until the disk has spun up. Only then will the target change
479 1.1 tsutsui * to STATUS phase. This is really only a problem for immediate commands
480 1.1 tsutsui * since we don't allow disconnection for them (yet).
481 1.1 tsutsui */
482 1.1 tsutsui size_t
483 1.1 tsutsui wd33c93_xfout(struct wd33c93_softc *sc, void *bp, size_t *lenp)
484 1.1 tsutsui {
485 1.1 tsutsui
486 1.1 tsutsui int wait = wd33c93_data_wait;
487 1.1 tsutsui uint8_t asr, *buf = bp;
488 1.1 tsutsui size_t len = *lenp;
489 1.1 tsutsui
490 1.1 tsutsui /*
491 1.1 tsutsui * sigh.. WD-PROTO strikes again.. sending the command in one go
492 1.1 tsutsui * causes the chip to lock up if talking to certain (misbehaving?)
493 1.1 tsutsui * targets. Anyway, this procedure should work for all targets, but
494 1.1 tsutsui * it's slightly slower due to the overhead
495 1.1 tsutsui */
496 1.1 tsutsui
497 1.1 tsutsui SET_SBIC_control(sc, SBIC_CTL_EDI | SBIC_CTL_IDI);
498 1.1 tsutsui SBIC_TC_PUT(sc, (unsigned int)len);
499 1.1 tsutsui
500 1.1 tsutsui WAIT_CIP(sc);
501 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_XFER_INFO);
502 1.1 tsutsui
503 1.1 tsutsui /*
504 1.1 tsutsui * Loop for each byte transferred
505 1.1 tsutsui */
506 1.1 tsutsui do {
507 1.1 tsutsui GET_SBIC_asr(sc, asr);
508 1.1 tsutsui
509 1.1 tsutsui if ((asr & SBIC_ASR_DBR) != 0) {
510 1.1 tsutsui if (len != 0) {
511 1.1 tsutsui SET_SBIC_data(sc, *buf);
512 1.1 tsutsui buf++;
513 1.1 tsutsui len--;
514 1.1 tsutsui } else {
515 1.1 tsutsui SET_SBIC_data(sc, 0);
516 1.1 tsutsui }
517 1.1 tsutsui wait = wd33c93_data_wait;
518 1.1 tsutsui }
519 1.1 tsutsui } while (len != 0 && (asr & SBIC_ASR_INT) == 0 && wait-- > 0);
520 1.1 tsutsui
521 1.1 tsutsui /*
522 1.1 tsutsui * Normally, an interrupt will be pending when this routing returns.
523 1.1 tsutsui */
524 1.1 tsutsui return len;
525 1.1 tsutsui }
526 1.1 tsutsui
527 1.1 tsutsui int
528 1.1 tsutsui wd33c93_intr(struct wd33c93_softc *sc, uint8_t *cbuf, size_t clen,
529 1.1 tsutsui uint8_t *buf, size_t *lenp)
530 1.1 tsutsui {
531 1.1 tsutsui uint8_t asr, csr;
532 1.1 tsutsui
533 1.1 tsutsui /*
534 1.1 tsutsui * pending interrupt?
535 1.1 tsutsui */
536 1.1 tsutsui GET_SBIC_asr(sc, asr);
537 1.1 tsutsui if ((asr & SBIC_ASR_INT) == 0)
538 1.1 tsutsui return 0;
539 1.1 tsutsui
540 1.1 tsutsui GET_SBIC_csr(sc, csr);
541 1.1 tsutsui
542 1.1 tsutsui do {
543 1.1 tsutsui
544 1.1 tsutsui (void)wd33c93_nextstate(sc, cbuf, clen, buf, lenp, csr, asr);
545 1.1 tsutsui WAIT_CIP(sc);
546 1.1 tsutsui if (sc->sc_state == SBIC_CONNECTED) {
547 1.1 tsutsui GET_SBIC_asr(sc, asr);
548 1.1 tsutsui
549 1.1 tsutsui if ((asr & SBIC_ASR_INT) != 0)
550 1.1 tsutsui GET_SBIC_csr(sc, csr);
551 1.1 tsutsui }
552 1.1 tsutsui } while (sc->sc_state == SBIC_CONNECTED &&
553 1.1 tsutsui (asr & (SBIC_ASR_INT|SBIC_ASR_LCI)) != 0);
554 1.1 tsutsui
555 1.1 tsutsui return 1;
556 1.1 tsutsui }
557 1.1 tsutsui
558 1.1 tsutsui /*
559 1.1 tsutsui * Information Transfer *from* a Scsi Target
560 1.1 tsutsui * returns # bytes left to read
561 1.1 tsutsui */
562 1.1 tsutsui size_t
563 1.1 tsutsui wd33c93_xfin(struct wd33c93_softc *sc, void *bp, size_t *lenp)
564 1.1 tsutsui {
565 1.1 tsutsui size_t len = *lenp;
566 1.1 tsutsui
567 1.1 tsutsui int wait = wd33c93_data_wait;
568 1.1 tsutsui uint8_t *buf = bp;
569 1.1 tsutsui uint8_t asr;
570 1.1 tsutsui
571 1.1 tsutsui SET_SBIC_control(sc, SBIC_CTL_EDI | SBIC_CTL_IDI);
572 1.1 tsutsui SBIC_TC_PUT(sc, (unsigned int)len);
573 1.1 tsutsui
574 1.1 tsutsui WAIT_CIP(sc);
575 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_XFER_INFO);
576 1.1 tsutsui
577 1.1 tsutsui /*
578 1.1 tsutsui * Loop for each byte transferred
579 1.1 tsutsui */
580 1.1 tsutsui do {
581 1.1 tsutsui GET_SBIC_asr(sc, asr);
582 1.1 tsutsui
583 1.1 tsutsui if ((asr & SBIC_ASR_DBR) != 0) {
584 1.1 tsutsui if (len != 0) {
585 1.1 tsutsui GET_SBIC_data(sc, *buf);
586 1.1 tsutsui buf++;
587 1.1 tsutsui len--;
588 1.1 tsutsui } else {
589 1.1 tsutsui uint8_t foo;
590 1.1 tsutsui GET_SBIC_data(sc, foo);
591 1.1 tsutsui __USE(foo);
592 1.1 tsutsui }
593 1.1 tsutsui wait = wd33c93_data_wait;
594 1.1 tsutsui }
595 1.1 tsutsui
596 1.1 tsutsui } while ((asr & SBIC_ASR_INT) == 0 && wait-- > 0);
597 1.1 tsutsui
598 1.1 tsutsui SBIC_TC_PUT(sc, 0);
599 1.1 tsutsui
600 1.1 tsutsui /*
601 1.1 tsutsui * this leaves with one csr to be read
602 1.1 tsutsui */
603 1.1 tsutsui return len;
604 1.1 tsutsui }
605 1.1 tsutsui
606 1.1 tsutsui /*
607 1.1 tsutsui * Finish SCSI xfer command: After the completion interrupt from
608 1.1 tsutsui * a read/write operation, sequence through the final phases in
609 1.1 tsutsui * programmed i/o.
610 1.1 tsutsui */
611 1.1 tsutsui void
612 1.1 tsutsui wd33c93_xferdone(struct wd33c93_softc *sc)
613 1.1 tsutsui {
614 1.1 tsutsui uint8_t phase, csr;
615 1.1 tsutsui
616 1.1 tsutsui /*
617 1.1 tsutsui * have the wd33c93 complete on its own
618 1.1 tsutsui */
619 1.1 tsutsui SBIC_TC_PUT(sc, 0);
620 1.1 tsutsui SET_SBIC_cmd_phase(sc, 0x46);
621 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_SEL_ATN_XFER);
622 1.1 tsutsui
623 1.1 tsutsui do {
624 1.1 tsutsui SBIC_WAIT(sc, SBIC_ASR_INT, 0);
625 1.1 tsutsui GET_SBIC_csr(sc, csr);
626 1.1 tsutsui } while ((csr != SBIC_CSR_DISC) &&
627 1.1 tsutsui (csr != SBIC_CSR_DISC_1) &&
628 1.1 tsutsui (csr != SBIC_CSR_S_XFERRED));
629 1.1 tsutsui
630 1.1 tsutsui sc->sc_flags &= ~SBICF_SELECTED;
631 1.1 tsutsui sc->sc_state = SBIC_DISCONNECT;
632 1.1 tsutsui
633 1.1 tsutsui GET_SBIC_cmd_phase(sc, phase);
634 1.1 tsutsui
635 1.1 tsutsui if (phase == 0x60)
636 1.1 tsutsui GET_SBIC_tlun(sc, sc->sc_status);
637 1.1 tsutsui else
638 1.1 tsutsui wd33c93_error(sc);
639 1.1 tsutsui }
640 1.1 tsutsui
641 1.1 tsutsui int
642 1.1 tsutsui wd33c93_abort(struct wd33c93_softc *sc, uint8_t *cbuf, size_t clen,
643 1.1 tsutsui uint8_t *buf, size_t *lenp)
644 1.1 tsutsui {
645 1.1 tsutsui uint8_t csr, asr;
646 1.1 tsutsui
647 1.1 tsutsui GET_SBIC_asr(sc, asr);
648 1.1 tsutsui GET_SBIC_csr(sc, csr);
649 1.1 tsutsui
650 1.1 tsutsui /*
651 1.1 tsutsui * Clean up chip itself
652 1.1 tsutsui */
653 1.1 tsutsui wd33c93_timeout(sc, cbuf, clen, buf, lenp);
654 1.1 tsutsui
655 1.1 tsutsui while ((asr & SBIC_ASR_DBR) != 0) {
656 1.1 tsutsui /*
657 1.1 tsutsui * wd33c93 is jammed w/data. need to clear it
658 1.1 tsutsui * But we don't know what direction it needs to go
659 1.1 tsutsui */
660 1.1 tsutsui GET_SBIC_data(sc, asr);
661 1.1 tsutsui GET_SBIC_asr(sc, asr);
662 1.1 tsutsui if ((asr & SBIC_ASR_DBR) != 0)
663 1.1 tsutsui /* Not the read direction */
664 1.1 tsutsui SET_SBIC_data(sc, asr);
665 1.1 tsutsui GET_SBIC_asr(sc, asr);
666 1.1 tsutsui }
667 1.1 tsutsui
668 1.1 tsutsui WAIT_CIP(sc);
669 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_ABORT);
670 1.1 tsutsui WAIT_CIP(sc);
671 1.1 tsutsui
672 1.1 tsutsui GET_SBIC_asr(sc, asr);
673 1.1 tsutsui
674 1.1 tsutsui if ((asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) != 0) {
675 1.1 tsutsui /*
676 1.1 tsutsui * ok, get more drastic..
677 1.1 tsutsui */
678 1.1 tsutsui wd33c93_reset(sc);
679 1.1 tsutsui } else {
680 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_DISC);
681 1.1 tsutsui WAIT_CIP(sc);
682 1.1 tsutsui
683 1.1 tsutsui do {
684 1.1 tsutsui SBIC_WAIT(sc, SBIC_ASR_INT, 0);
685 1.1 tsutsui GET_SBIC_asr(sc, asr);
686 1.1 tsutsui GET_SBIC_csr(sc, csr);
687 1.1 tsutsui } while ((csr != SBIC_CSR_DISC) &&
688 1.1 tsutsui (csr != SBIC_CSR_DISC_1) &&
689 1.1 tsutsui (csr != SBIC_CSR_CMD_INVALID));
690 1.1 tsutsui
691 1.1 tsutsui sc->sc_state = SBIC_ERROR;
692 1.1 tsutsui sc->sc_flags = 0;
693 1.1 tsutsui }
694 1.1 tsutsui return SBIC_STATE_ERROR;
695 1.1 tsutsui }
696 1.1 tsutsui
697 1.1 tsutsui void
698 1.1 tsutsui wd33c93_timeout(struct wd33c93_softc *sc, uint8_t *cbuf, size_t clen,
699 1.1 tsutsui uint8_t *buf, size_t *lenp)
700 1.1 tsutsui {
701 1.1 tsutsui uint8_t asr;
702 1.1 tsutsui
703 1.1 tsutsui GET_SBIC_asr(sc, asr);
704 1.1 tsutsui
705 1.1 tsutsui if ((asr & SBIC_ASR_INT) != 0) {
706 1.1 tsutsui /* We need to service a missed IRQ */
707 1.1 tsutsui wd33c93_intr(sc, cbuf, clen, buf, lenp);
708 1.1 tsutsui } else {
709 1.1 tsutsui wd33c93_abort(sc, cbuf, clen, buf, lenp);
710 1.1 tsutsui }
711 1.1 tsutsui }
712 1.1 tsutsui
713 1.1 tsutsui /*
714 1.1 tsutsui * Complete current command using polled I/O.Used when interrupt driven
715 1.1 tsutsui * I/O is not allowed (ie. during boot and shutdown)
716 1.1 tsutsui *
717 1.1 tsutsui * Polled I/O is very processor intensive
718 1.1 tsutsui */
719 1.1 tsutsui int
720 1.1 tsutsui wd33c93_poll(struct wd33c93_softc *sc, uint8_t *cbuf, size_t clen,
721 1.1 tsutsui uint8_t *buf, size_t *lenp)
722 1.1 tsutsui {
723 1.1 tsutsui uint8_t asr, csr = 0;
724 1.1 tsutsui int count;
725 1.1 tsutsui
726 1.1 tsutsui SBIC_WAIT(sc, SBIC_ASR_INT, wd33c93_cmd_wait);
727 1.1 tsutsui for (count = SBIC_ABORT_TIMEOUT; count;) {
728 1.1 tsutsui GET_SBIC_asr(sc, asr);
729 1.1 tsutsui if ((asr & SBIC_ASR_LCI) != 0)
730 1.1 tsutsui DELAY(5000);
731 1.1 tsutsui
732 1.1 tsutsui if ((asr & SBIC_ASR_INT) != 0) {
733 1.1 tsutsui GET_SBIC_csr(sc, csr);
734 1.1 tsutsui (void)wd33c93_nextstate(sc, cbuf, clen, buf, lenp, csr,
735 1.1 tsutsui asr);
736 1.1 tsutsui WAIT_CIP(sc);
737 1.1 tsutsui } else {
738 1.1 tsutsui DELAY(5000);
739 1.1 tsutsui count--;
740 1.1 tsutsui }
741 1.1 tsutsui
742 1.1 tsutsui if ((sc->xs_status & XS_STS_DONE) != 0)
743 1.1 tsutsui return 0;
744 1.1 tsutsui }
745 1.1 tsutsui return 1;
746 1.1 tsutsui }
747 1.1 tsutsui
748 1.1 tsutsui static inline int
749 1.1 tsutsui __verify_msg_format(uint8_t *p, int len)
750 1.1 tsutsui {
751 1.1 tsutsui
752 1.1 tsutsui if (len == 1 && MSG_IS1BYTE(p[0]))
753 1.1 tsutsui return 1;
754 1.1 tsutsui if (len == 2 && MSG_IS2BYTE(p[0]))
755 1.1 tsutsui return 1;
756 1.1 tsutsui if (len >= 3 && MSG_ISEXTENDED(p[0]) &&
757 1.1 tsutsui len == p[1] + 2)
758 1.1 tsutsui return 1;
759 1.1 tsutsui return 0;
760 1.1 tsutsui }
761 1.1 tsutsui
762 1.1 tsutsui /*
763 1.1 tsutsui * Handle message_in phase
764 1.1 tsutsui */
765 1.1 tsutsui int
766 1.1 tsutsui wd33c93_msgin_phase(struct wd33c93_softc *sc)
767 1.1 tsutsui {
768 1.1 tsutsui int len;
769 1.1 tsutsui uint8_t asr, csr, *msg;
770 1.1 tsutsui
771 1.1 tsutsui GET_SBIC_asr(sc, asr);
772 1.1 tsutsui __USE(asr);
773 1.1 tsutsui
774 1.1 tsutsui GET_SBIC_selid(sc, csr);
775 1.1 tsutsui SET_SBIC_selid(sc, csr | SBIC_SID_FROM_SCSI);
776 1.1 tsutsui
777 1.1 tsutsui SBIC_TC_PUT(sc, 0);
778 1.1 tsutsui
779 1.1 tsutsui SET_SBIC_control(sc, SBIC_CTL_EDI | SBIC_CTL_IDI);
780 1.1 tsutsui
781 1.1 tsutsui msg = sc->sc_imsg;
782 1.1 tsutsui len = 0;
783 1.1 tsutsui
784 1.1 tsutsui do {
785 1.1 tsutsui /* Fetch the next byte of the message */
786 1.1 tsutsui RECV_BYTE(sc, *msg++);
787 1.1 tsutsui len++;
788 1.1 tsutsui
789 1.1 tsutsui /*
790 1.1 tsutsui * get the command completion interrupt, or we
791 1.1 tsutsui * can't send a new command (LCI)
792 1.1 tsutsui */
793 1.1 tsutsui SBIC_WAIT(sc, SBIC_ASR_INT, 0);
794 1.1 tsutsui GET_SBIC_csr(sc, csr);
795 1.1 tsutsui
796 1.1 tsutsui if (__verify_msg_format(sc->sc_imsg, len))
797 1.1 tsutsui /* Complete message received */
798 1.1 tsutsui break;
799 1.1 tsutsui
800 1.1 tsutsui /*
801 1.1 tsutsui * Clear ACK, and wait for the interrupt
802 1.1 tsutsui * for the next byte or phase change
803 1.1 tsutsui */
804 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_CLR_ACK);
805 1.1 tsutsui SBIC_WAIT(sc, SBIC_ASR_INT, 0);
806 1.1 tsutsui
807 1.1 tsutsui GET_SBIC_csr(sc, csr);
808 1.1 tsutsui } while (len < SBIC_MAX_MSGLEN);
809 1.1 tsutsui
810 1.1 tsutsui /*
811 1.1 tsutsui * Clear ACK, and wait for the interrupt
812 1.1 tsutsui * for the phase change
813 1.1 tsutsui */
814 1.1 tsutsui SET_SBIC_cmd(sc, SBIC_CMD_CLR_ACK);
815 1.1 tsutsui SBIC_WAIT(sc, SBIC_ASR_INT, 0);
816 1.1 tsutsui
817 1.1 tsutsui /* Should still have one CSR to read */
818 1.1 tsutsui return SBIC_STATE_RUNNING;
819 1.1 tsutsui }
820 1.1 tsutsui
821 1.1 tsutsui void
822 1.1 tsutsui wd33c93_scsistart(struct wd33c93_softc *sc)
823 1.1 tsutsui {
824 1.1 tsutsui
825 1.1 tsutsui sc->xs_status = 0;
826 1.1 tsutsui }
827 1.1 tsutsui
828 1.1 tsutsui void
829 1.1 tsutsui wd33c93_scsidone(struct wd33c93_softc *sc)
830 1.1 tsutsui {
831 1.1 tsutsui
832 1.1 tsutsui sc->xs_status = XS_STS_DONE;
833 1.1 tsutsui }
834 1.1 tsutsui
835 1.1 tsutsui void
836 1.1 tsutsui wd33c93_error(struct wd33c93_softc *sc)
837 1.1 tsutsui {
838 1.1 tsutsui }
839