1 /* $NecBSD: ncr53c500.c,v 1.30.12.3 2001/06/26 07:31:41 honda Exp $ */
2 /* $NetBSD$ */
3
4 #define NCV_DEBUG
5 #define NCV_STATICS
6 #define NCV_IO_CONTROL_FLAGS (0)
7
8 /*-
9 * [NetBSD for NEC PC-98 series]
10 * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
11 * NetBSD/pc98 porting staff. All rights reserved.
12 * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
13 * Naofumi HONDA. All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. The name of the author may not be used to endorse or promote products
24 * derived from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD: releng/8.4/sys/dev/ncv/ncr53c500.c 158651 2006-05-16 14:37:58Z phk $");
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #if defined(__FreeBSD__) && __FreeBSD_version >= 500001
46 #include <sys/bio.h>
47 #endif /* __FreeBSD__ */
48 #include <sys/buf.h>
49 #include <sys/queue.h>
50 #include <sys/malloc.h>
51 #include <sys/errno.h>
52
53 #ifdef __NetBSD__
54 #include <sys/device.h>
55 #include <machine/bus.h>
56 #include <machine/intr.h>
57
58 #include <dev/scsipi/scsi_all.h>
59 #include <dev/scsipi/scsipi_all.h>
60 #include <dev/scsipi/scsiconf.h>
61 #include <dev/scsipi/scsi_disk.h>
62
63 #include <machine/dvcfg.h>
64 #include <machine/physio_proc.h>
65
66 #include <i386/Cbus/dev/scsi_low.h>
67
68 #include <i386/Cbus/dev/ncr53c500reg.h>
69 #include <i386/Cbus/dev/ncr53c500hw.h>
70 #include <i386/Cbus/dev/ncr53c500var.h>
71
72 #include <i386/Cbus/dev/ncr53c500hwtab.h>
73 #endif /* __NetBSD__ */
74
75 #ifdef __FreeBSD__
76 #include <machine/cpu.h>
77 #include <machine/bus.h>
78
79 #include <compat/netbsd/dvcfg.h>
80 #include <compat/netbsd/physio_proc.h>
81
82 #include <cam/scsi/scsi_low.h>
83
84 #include <dev/ncv/ncr53c500reg.h>
85 #include <dev/ncv/ncr53c500hw.h>
86 #include <dev/ncv/ncr53c500var.h>
87
88 #include <dev/ncv/ncr53c500hwtab.h>
89 #endif /* __FreeBSD__ */
90
91 #define NCV_MAX_DATA_SIZE (64 * 1024)
92 #define NCV_DELAY_MAX (2 * 1000 * 1000)
93 #define NCV_DELAY_INTERVAL (1)
94 #define NCV_PADDING_SIZE (32)
95
96 /***************************************************
97 * IO control
98 ***************************************************/
99 #define NCV_READ_INTERRUPTS_DRIVEN 0x0001
100 #define NCV_WRITE_INTERRUPTS_DRIVEN 0x0002
101 #define NCV_ENABLE_FAST_SCSI 0x0010
102 #define NCV_FAST_INTERRUPTS 0x0100
103
104 u_int ncv_io_control = NCV_IO_CONTROL_FLAGS;
105 int ncv_data_read_bytes = 4096;
106 int ncv_data_write_bytes = 4096;
107
108 /***************************************************
109 * DEBUG
110 ***************************************************/
111 #ifdef NCV_DEBUG
112 static int ncv_debug;
113 #endif /* NCV_DEBUG */
114
115 #ifdef NCV_STATICS
116 static struct ncv_statics {
117 int disconnect;
118 int reselect;
119 } ncv_statics;
120 #endif /* NCV_STATICS */
121
122 /***************************************************
123 * DEVICE STRUCTURE
124 ***************************************************/
125 extern struct cfdriver ncv_cd;
126
127 /**************************************************************
128 * DECLARE
129 **************************************************************/
130 /* static */
131 static void ncv_pio_read(struct ncv_softc *, u_int8_t *, u_int);
132 static void ncv_pio_write(struct ncv_softc *, u_int8_t *, u_int);
133 static int ncv_msg(struct ncv_softc *, struct targ_info *, u_int);
134 static int ncv_reselected(struct ncv_softc *);
135 static int ncv_disconnected(struct ncv_softc *, struct targ_info *);
136
137 static __inline void ncvhw_set_count(bus_space_tag_t, bus_space_handle_t, int);
138 static __inline u_int ncvhw_get_count(bus_space_tag_t, bus_space_handle_t);
139 static __inline void ncvhw_select_register_0(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
140 static __inline void ncvhw_select_register_1(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
141 static __inline void ncvhw_fpush(bus_space_tag_t, bus_space_handle_t, u_int8_t *, int);
142
143 static void ncv_pdma_end(struct ncv_softc *sc, struct targ_info *);
144 static int ncv_world_start(struct ncv_softc *, int);
145 static void ncvhw_bus_reset(struct ncv_softc *);
146 static void ncvhw_reset(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
147 static int ncvhw_check(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
148 static void ncvhw_init(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
149 static int ncvhw_start_selection(struct ncv_softc *sc, struct slccb *);
150 static void ncvhw_attention(struct ncv_softc *);
151 static int ncv_ccb_nexus_establish(struct ncv_softc *);
152 static int ncv_lun_nexus_establish(struct ncv_softc *);
153 static int ncv_target_nexus_establish(struct ncv_softc *);
154 static int ncv_targ_init(struct ncv_softc *, struct targ_info *, int);
155 static int ncv_catch_intr(struct ncv_softc *);
156 #ifdef NCV_POWER_CONTROL
157 static int ncvhw_power(struct ncv_softc *, u_int);
158 #endif /* NCV_POWER_CONTROL */
159 static __inline void ncv_setup_and_start_pio(struct ncv_softc *, u_int);
160
161 struct scsi_low_funcs ncv_funcs = {
162 SC_LOW_INIT_T ncv_world_start,
163 SC_LOW_BUSRST_T ncvhw_bus_reset,
164 SC_LOW_TARG_INIT_T ncv_targ_init,
165 SC_LOW_LUN_INIT_T NULL,
166
167 SC_LOW_SELECT_T ncvhw_start_selection,
168 SC_LOW_NEXUS_T ncv_lun_nexus_establish,
169 SC_LOW_NEXUS_T ncv_ccb_nexus_establish,
170
171 SC_LOW_ATTEN_T ncvhw_attention,
172 SC_LOW_MSG_T ncv_msg,
173
174 SC_LOW_TIMEOUT_T NULL,
175 SC_LOW_POLL_T ncvintr,
176
177 NULL, /* SC_LOW_POWER_T ncvhw_power, */
178 };
179
180 /**************************************************************
181 * hwfuncs
182 **************************************************************/
183 static __inline void
184 ncvhw_select_register_0(iot, ioh, hw)
185 bus_space_tag_t iot;
186 bus_space_handle_t ioh;
187 struct ncv_hw *hw;
188 {
189
190 bus_space_write_1(iot, ioh, cr0_cfg4, hw->hw_cfg4);
191 }
192
193 static __inline void
194 ncvhw_select_register_1(iot, ioh, hw)
195 bus_space_tag_t iot;
196 bus_space_handle_t ioh;
197 struct ncv_hw *hw;
198 {
199
200 bus_space_write_1(iot, ioh, cr1_cfg5, hw->hw_cfg5);
201 }
202
203 static __inline void
204 ncvhw_fpush(iot, ioh, buf, len)
205 bus_space_tag_t iot;
206 bus_space_handle_t ioh;
207 u_int8_t *buf;
208 int len;
209 {
210 int ptr;
211
212 for (ptr = 0; ptr < len; ptr ++)
213 bus_space_write_1(iot, ioh, cr0_sfifo, buf[ptr]);
214 }
215
216 static __inline void
217 ncvhw_set_count(iot, ioh, count)
218 bus_space_tag_t iot;
219 bus_space_handle_t ioh;
220 int count;
221 {
222
223 bus_space_write_1(iot, ioh, cr0_tclsb, (u_int8_t) count);
224 bus_space_write_1(iot, ioh, cr0_tcmsb, (u_int8_t) (count >> NBBY));
225 bus_space_write_1(iot, ioh, cr0_tchsb, (u_int8_t) (count >> (NBBY * 2)));
226 }
227
228 static __inline u_int
229 ncvhw_get_count(iot, ioh)
230 bus_space_tag_t iot;
231 bus_space_handle_t ioh;
232 {
233 u_int count;
234
235 count = (u_int) bus_space_read_1(iot, ioh, cr0_tclsb);
236 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tcmsb)) << NBBY;
237 count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tchsb)) << (NBBY * 2);
238 return count;
239 }
240
241 static int
242 ncvhw_check(iot, ioh, hw)
243 bus_space_tag_t iot;
244 bus_space_handle_t ioh;
245 struct ncv_hw *hw;
246 {
247 u_int8_t stat;
248
249 ncvhw_select_register_0(iot, ioh, hw);
250 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
251 if (bus_space_read_1(iot, ioh, cr0_cmd) != (CMD_NOP | CMD_DMA))
252 {
253 #ifdef NCV_DEBUG
254 printf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n");
255 #endif /* NCV_DEBUG */
256 return ENODEV;
257 }
258
259 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
260 if (bus_space_read_1(iot, ioh, cr0_cmd) != CMD_NOP)
261 {
262 #ifdef NCV_DEBUG
263 printf("ncv: cr0_cmd CMD_NOP failed\n");
264 #endif /* NCV_DEBUG */
265 return ENODEV;
266 }
267
268 /* hardware reset */
269 ncvhw_reset(iot, ioh, hw);
270 ncvhw_init(iot, ioh, hw);
271
272 /* bus reset */
273 ncvhw_select_register_0(iot, ioh, hw);
274 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
275 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
276 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
277 SCSI_LOW_DELAY(100 * 1000);
278
279 /* check response */
280 bus_space_read_1(iot, ioh, cr0_stat);
281 stat = bus_space_read_1(iot, ioh, cr0_istat);
282 SCSI_LOW_DELAY(1000);
283
284 if (((stat & INTR_SBR) == 0) ||
285 (bus_space_read_1(iot, ioh, cr0_istat) & INTR_SBR))
286 {
287 #ifdef NCV_DEBUG
288 printf("ncv: cr0_istat SCSI BUS RESET failed\n");
289 #endif /* NCV_DEBUG */
290 return ENODEV;
291 }
292
293 return 0;
294 }
295
296 static void
297 ncvhw_reset(iot, ioh, hw)
298 bus_space_tag_t iot;
299 bus_space_handle_t ioh;
300 struct ncv_hw *hw;
301 {
302
303 ncvhw_select_register_0(iot, ioh, hw);
304
305 /* dummy cmd twice */
306 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
307 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
308
309 /* chip reset */
310 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTCHIP);
311
312 /* again dummy cmd twice */
313 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
314 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
315 }
316
317 static void
318 ncvhw_init(iot, ioh, hw)
319 bus_space_tag_t iot;
320 bus_space_handle_t ioh;
321 struct ncv_hw *hw;
322 {
323
324 ncvhw_select_register_0(iot, ioh, hw);
325 bus_space_write_1(iot, ioh, cr0_clk, hw->hw_clk);
326 bus_space_write_1(iot, ioh, cr0_srtout, SEL_TOUT);
327 bus_space_write_1(iot, ioh, cr0_period, 0);
328 bus_space_write_1(iot, ioh, cr0_offs, 0);
329
330 bus_space_write_1(iot, ioh, cr0_cfg1, hw->hw_cfg1);
331 bus_space_write_1(iot, ioh, cr0_cfg2, hw->hw_cfg2);
332 bus_space_write_1(iot, ioh, cr0_cfg3, hw->hw_cfg3);
333 bus_space_write_1(iot, ioh, cr0_tchsb, 0);
334
335 ncvhw_select_register_1(iot, ioh, hw);
336 bus_space_write_1(iot, ioh, cr1_fstat, 0x0);
337 bus_space_write_1(iot, ioh, cr1_pflag, 0x0);
338 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
339
340 ncvhw_select_register_0(iot, ioh, hw);
341 }
342
343 #ifdef NCV_POWER_CONTROL
344 static int
345 ncvhw_power(sc, flags)
346 struct ncv_softc *sc;
347 u_int flags;
348 {
349 struct scsi_low_softc *slp = &sc->sc_sclow;
350 bus_space_tag_t iot = sc->sc_iot;
351 bus_space_handle_t ioh = sc->sc_ioh;
352
353 if (flags == SCSI_LOW_POWDOWN)
354 {
355 printf("%s power down\n", slp->sl_xname);
356 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
357 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_POWDOWN);
358 }
359 else
360 {
361 switch (sc->sc_rstep)
362 {
363 case 0:
364 printf("%s resume step O\n", slp->sl_xname);
365 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
366 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
367 break;
368
369 case 1:
370 printf("%s resume step I\n", slp->sl_xname);
371 ncvhw_reset(iot, ioh, &sc->sc_hw);
372 ncvhw_init(iot, ioh, &sc->sc_hw);
373 break;
374 }
375 }
376
377 return 0;
378 }
379 #endif /* NCV_POWER_CONTROL */
380
381 /**************************************************************
382 * scsi low interface
383 **************************************************************/
384 static void
385 ncvhw_attention(sc)
386 struct ncv_softc *sc;
387 {
388
389 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd, CMD_SETATN);
390 SCSI_LOW_DELAY(10);
391 }
392
393 static void
394 ncvhw_bus_reset(sc)
395 struct ncv_softc *sc;
396 {
397 bus_space_tag_t iot = sc->sc_iot;
398 bus_space_handle_t ioh = sc->sc_ioh;
399
400 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
401 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
402 bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
403 bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
404 }
405
406 static int
407 ncvhw_start_selection(sc, cb)
408 struct ncv_softc *sc;
409 struct slccb *cb;
410 {
411 struct scsi_low_softc *slp = &sc->sc_sclow;
412 bus_space_tag_t iot = sc->sc_iot;
413 bus_space_handle_t ioh = sc->sc_ioh;
414 struct targ_info *ti = cb->ti;
415 int s, len;
416 u_int flags;
417 u_int8_t cmd;
418
419 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
420 sc->sc_compseq = 0;
421 if (scsi_low_is_msgout_continue(ti, SCSI_LOW_MSG_IDENTIFY) == 0)
422 {
423 cmd = CMD_SELATN;
424 sc->sc_selstop = 0;
425 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
426 }
427 else if (scsi_low_is_msgout_continue(ti,
428 SCSI_LOW_MSG_IDENTIFY | SCSI_LOW_MSG_SIMPLE_QTAG) == 0)
429 {
430 cmd = CMD_SELATN3;
431 sc->sc_selstop = 0;
432 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
433 }
434 else
435 {
436 cmd = CMD_SELATNS;
437 sc->sc_selstop = 1;
438 flags = SCSI_LOW_MSGOUT_INIT;
439 }
440
441 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
442 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
443 return SCSI_LOW_START_FAIL;
444
445 ncv_target_nexus_establish(sc);
446
447 len = scsi_low_msgout(slp, ti, flags);
448 if (sc->sc_selstop == 0)
449 scsi_low_cmd(slp, ti);
450
451 s = splhigh();
452 if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
453 {
454 splx(s);
455 return SCSI_LOW_START_FAIL;
456 }
457
458 bus_space_write_1(iot, ioh, cr0_dstid, ti->ti_id);
459 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
460 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
461 if (sc->sc_selstop == 0)
462 {
463 ncvhw_fpush(iot, ioh,
464 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
465 }
466 bus_space_write_1(iot, ioh, cr0_cmd, cmd);
467 splx(s);
468
469 SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
470 return SCSI_LOW_START_OK;
471 }
472
473 static int
474 ncv_world_start(sc, fdone)
475 struct ncv_softc *sc;
476 int fdone;
477 {
478 struct scsi_low_softc *slp = &sc->sc_sclow;
479 bus_space_tag_t iot = sc->sc_iot;
480 bus_space_handle_t ioh = sc->sc_ioh;
481 u_int8_t stat;
482
483 if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
484 sc->sc_hw.hw_cfg1 |= C1_PARENB;
485 else
486 sc->sc_hw.hw_cfg1 &= ~C1_PARENB;
487
488 ncvhw_reset(iot, ioh, &sc->sc_hw);
489 ncvhw_init(iot, ioh, &sc->sc_hw);
490
491 scsi_low_bus_reset(slp);
492
493 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
494 bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_stat);
495 stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat);
496 SCSI_LOW_DELAY(1000);
497
498 if (((stat & INTR_SBR) == 0) ||
499 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat) & INTR_SBR))
500 return ENODEV;
501
502 SOFT_INTR_REQUIRED(slp);
503 return 0;
504 }
505
506 static int
507 ncv_msg(sc, ti, msg)
508 struct ncv_softc *sc;
509 struct targ_info *ti;
510 u_int msg;
511 {
512 bus_space_tag_t iot = sc->sc_iot;
513 bus_space_handle_t ioh = sc->sc_ioh;
514 struct ncv_targ_info *nti = (void *) ti;
515 u_int hwcycle, period;
516
517 if ((msg & SCSI_LOW_MSG_WIDE) != 0)
518 {
519 if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
520 {
521 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
522 return EINVAL;
523 }
524 return 0;
525 }
526
527 if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
528 return 0;
529
530 period = ti->ti_maxsynch.period;
531 hwcycle = (sc->sc_hw.hw_clk == 0) ? 40 : (5 * sc->sc_hw.hw_clk);
532 hwcycle = 1000 / hwcycle;
533
534 if (period < 200 / 4 && period >= 100 / 4)
535 nti->nti_reg_cfg3 |= sc->sc_hw.hw_cfg3_fscsi;
536 else
537 nti->nti_reg_cfg3 &= ~sc->sc_hw.hw_cfg3_fscsi;
538
539 period = ((period * 40 / hwcycle) + 5) / 10;
540 nti->nti_reg_period = period & 0x1f;
541 nti->nti_reg_offset = ti->ti_maxsynch.offset;
542
543 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
544 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
545 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
546 return 0;
547 }
548
549 static int
550 ncv_targ_init(sc, ti, action)
551 struct ncv_softc *sc;
552 struct targ_info *ti;
553 int action;
554 {
555 struct ncv_targ_info *nti = (void *) ti;
556
557 if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
558 {
559 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
560 ti->ti_maxsynch.period = sc->sc_hw.hw_mperiod;
561 ti->ti_maxsynch.offset = sc->sc_hw.hw_moffset;
562
563 nti->nti_reg_cfg3 = sc->sc_hw.hw_cfg3;
564 nti->nti_reg_period = 0;
565 nti->nti_reg_offset = 0;
566 }
567 return 0;
568 }
569
570 /**************************************************************
571 * General probe attach
572 **************************************************************/
573 static int ncv_setup_img(struct ncv_hw *, u_int, int);
574
575 static int
576 ncv_setup_img(hw, dvcfg, hostid)
577 struct ncv_hw *hw;
578 u_int dvcfg;
579 int hostid;
580 {
581
582 if (NCV_CLKFACTOR(dvcfg) > CLK_35M_F)
583 {
584 printf("ncv: invalid dvcfg flags\n");
585 return EINVAL;
586 }
587
588 if (NCV_C5IMG(dvcfg) != 0)
589 {
590 hw->hw_cfg5 = NCV_C5IMG(dvcfg);
591 hw->hw_clk = NCV_CLKFACTOR(dvcfg);
592
593 if ((ncv_io_control & NCV_ENABLE_FAST_SCSI) != 0 &&
594 (NCV_SPECIAL(dvcfg) & NCVHWCFG_MAX10M) != 0)
595 hw->hw_mperiod = 100 / 4;
596
597 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_FIFOBUG)
598 hw->hw_cfg3_fclk = 0x04;
599
600 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SCSI1)
601 hw->hw_cfg2 &= ~C2_SCSI2;
602
603 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SLOW)
604 hw->hw_cfg1 |= C1_SLOW;
605 }
606
607 /* setup configuration image 3 */
608 if (hw->hw_clk != CLK_40M_F && hw->hw_clk <= CLK_25M_F)
609 hw->hw_cfg3 &= ~hw->hw_cfg3_fclk;
610 else
611 hw->hw_cfg3 |= hw->hw_cfg3_fclk;
612
613 /* setup configuration image 1 */
614 hw->hw_cfg1 = (hw->hw_cfg1 & 0xf0) | hostid;
615 return 0;
616 }
617
618 int
619 ncvprobesubr(iot, ioh, dvcfg, hsid)
620 bus_space_tag_t iot;
621 bus_space_handle_t ioh;
622 u_int dvcfg;
623 int hsid;
624 {
625 struct ncv_hw hwtab;
626
627 hwtab = ncv_template;
628 if (ncv_setup_img(&hwtab, dvcfg, hsid))
629 return 0;
630 if (ncvhw_check(iot, ioh, &hwtab) != 0)
631 return 0;
632
633 return 1;
634 }
635
636 int
637 ncvprint(aux, name)
638 void *aux;
639 const char *name;
640 {
641
642 if (name != NULL)
643 printf("%s: scsibus ", name);
644 return UNCONF;
645 }
646
647 void
648 ncvattachsubr(sc)
649 struct ncv_softc *sc;
650 {
651 struct scsi_low_softc *slp = &sc->sc_sclow;
652
653 printf("\n");
654 sc->sc_hw = ncv_template;
655 ncv_setup_img(&sc->sc_hw, slp->sl_cfgflags, slp->sl_hostid);
656 slp->sl_funcs = &ncv_funcs;
657 slp->sl_flags |= HW_READ_PADDING;
658 sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
659
660 (void) scsi_low_attach(slp, 0, NCV_NTARGETS, NCV_NLUNS,
661 sizeof(struct ncv_targ_info), 0);
662 }
663
664 /**************************************************************
665 * PDMA
666 **************************************************************/
667 static __inline void
668 ncv_setup_and_start_pio(sc, reqlen)
669 struct ncv_softc *sc;
670 u_int reqlen;
671 {
672 bus_space_tag_t iot = sc->sc_iot;
673 bus_space_handle_t ioh = sc->sc_ioh;
674
675 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
676 ncvhw_set_count(iot, ioh, reqlen);
677 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS | CMD_DMA);
678
679 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
680 bus_space_write_1(iot, ioh, cr1_fstat, FIFO_EN);
681 }
682
683 static void
684 ncv_pdma_end(sc, ti)
685 struct ncv_softc *sc;
686 struct targ_info *ti;
687 {
688 struct scsi_low_softc *slp = &sc->sc_sclow;
689 bus_space_tag_t iot = sc->sc_iot;
690 bus_space_handle_t ioh = sc->sc_ioh;
691 int len;
692
693 slp->sl_flags &= ~HW_PDMASTART;
694 if (slp->sl_Qnexus == NULL)
695 {
696 slp->sl_error |= PDMAERR;
697 goto out;
698 }
699
700 if (ti->ti_phase == PH_DATA)
701 {
702 len = ncvhw_get_count(sc->sc_iot, sc->sc_ioh);
703 if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE)
704 len += (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
705 cr0_sffl) & CR0_SFFLR_BMASK);
706
707 if ((u_int) len <= (u_int) sc->sc_sdatalen)
708 {
709 if ((slp->sl_scp.scp_direction == SCSI_LOW_READ) &&
710 sc->sc_tdatalen != len)
711 goto bad;
712
713 len = sc->sc_sdatalen - len;
714 if ((u_int) len > (u_int) slp->sl_scp.scp_datalen)
715 goto bad;
716
717 slp->sl_scp.scp_data += len;
718 slp->sl_scp.scp_datalen -= len;
719 }
720 else
721 {
722 bad:
723 if ((slp->sl_error & PDMAERR) == 0)
724 {
725 printf("%s: stragne cnt hw 0x%x soft 0x%x\n",
726 slp->sl_xname, len,
727 slp->sl_scp.scp_datalen);
728 }
729 slp->sl_error |= PDMAERR;
730 }
731 scsi_low_data_finish(slp);
732 }
733 else
734 {
735 printf("%s: data phase miss\n", slp->sl_xname);
736 slp->sl_error |= PDMAERR;
737 }
738
739 out:
740 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
741 bus_space_write_1(iot, ioh, cr1_fstat, 0);
742 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
743 }
744
745 static void
746 ncv_pio_read(sc, buf, reqlen)
747 struct ncv_softc *sc;
748 u_int8_t *buf;
749 u_int reqlen;
750 {
751 struct scsi_low_softc *slp = &sc->sc_sclow;
752 bus_space_tag_t iot = sc->sc_iot;
753 bus_space_handle_t ioh = sc->sc_ioh;
754 int tout;
755 register u_int8_t fstat;
756
757 ncv_setup_and_start_pio(sc, reqlen);
758 slp->sl_flags |= HW_PDMASTART;
759 sc->sc_sdatalen = reqlen;
760 tout = sc->sc_tmaxcnt;
761
762 while (reqlen >= FIFO_F_SZ && tout -- > 0)
763 {
764 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
765 if (fstat == (u_int8_t) -1)
766 goto out;
767 if (fstat & FIFO_F)
768 {
769 #define NCV_FAST32_ACCESS
770 #ifdef NCV_FAST32_ACCESS
771 bus_space_read_multi_4(iot, ioh, cr1_fdata,
772 (u_int32_t *) buf, FIFO_F_SZ / 4);
773 #else /* !NCV_FAST32_ACCESS */
774 bus_space_read_multi_2(iot, ioh, cr1_fdata,
775 (u_int16_t *) buf, FIFO_F_SZ / 2);
776 #endif /* !NCV_FAST32_ACCESS */
777 buf += FIFO_F_SZ;
778 reqlen -= FIFO_F_SZ;
779 }
780 else
781 {
782 if (fstat & FIFO_BRK)
783 break;
784
785 SCSI_LOW_DELAY(1);
786 }
787 }
788
789 while (reqlen > 0 && tout -- > 0)
790 {
791 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
792 if ((fstat & FIFO_E) == 0)
793 {
794 *buf++ = bus_space_read_1(iot, ioh, cr1_fdata);
795 reqlen --;
796 }
797 else
798 {
799 if (fstat & FIFO_BRK)
800 break;
801
802 SCSI_LOW_DELAY(1);
803 }
804 }
805
806 out:
807 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
808 sc->sc_tdatalen = reqlen;
809 }
810
811 static void
812 ncv_pio_write(sc, buf, reqlen)
813 struct ncv_softc *sc;
814 u_int8_t *buf;
815 u_int reqlen;
816 {
817 struct scsi_low_softc *slp = &sc->sc_sclow;
818 bus_space_tag_t iot = sc->sc_iot;
819 bus_space_handle_t ioh = sc->sc_ioh;
820 int tout;
821 register u_int8_t fstat;
822
823 ncv_setup_and_start_pio(sc, reqlen);
824 sc->sc_sdatalen = reqlen;
825 tout = sc->sc_tmaxcnt;
826 slp->sl_flags |= HW_PDMASTART;
827
828 while (reqlen >= FIFO_F_SZ && tout -- > 0)
829 {
830 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
831 if (fstat & FIFO_BRK)
832 goto done;
833
834 if ((fstat & FIFO_E) != 0)
835 {
836 #ifdef NCV_FAST32_ACCESS
837 bus_space_write_multi_4(iot, ioh, cr1_fdata,
838 (u_int32_t *) buf, FIFO_F_SZ / 4);
839 #else /* !NCV_FAST32_ACCESS */
840 bus_space_write_multi_2(iot, ioh, cr1_fdata,
841 (u_int16_t *) buf, FIFO_F_SZ / 2);
842 #endif /* !NCV_FAST32_ACCESS */
843 buf += FIFO_F_SZ;
844 reqlen -= FIFO_F_SZ;
845 }
846 else
847 {
848 SCSI_LOW_DELAY(1);
849 }
850 }
851
852 while (reqlen > 0 && tout -- > 0)
853 {
854 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
855 if (fstat & FIFO_BRK)
856 break;
857
858 if ((fstat & FIFO_F) == 0) /* fifo not full */
859 {
860 bus_space_write_1(iot, ioh, cr1_fdata, *buf++);
861 reqlen --;
862 }
863 else
864 {
865 SCSI_LOW_DELAY(1);
866 }
867 }
868
869 done:
870 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
871 }
872
873 /**************************************************************
874 * disconnect & reselect (HW low)
875 **************************************************************/
876 static int
877 ncv_reselected(sc)
878 struct ncv_softc *sc;
879 {
880 struct scsi_low_softc *slp = &sc->sc_sclow;
881 bus_space_tag_t iot = sc->sc_iot;
882 bus_space_handle_t ioh = sc->sc_ioh;
883 struct targ_info *ti;
884 u_int sid;
885
886 if ((bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK) != 2)
887 {
888 printf("%s illegal fifo bytes\n", slp->sl_xname);
889 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "chip confused");
890 return EJUSTRETURN;
891 }
892
893 sid = (u_int) bus_space_read_1(iot, ioh, cr0_sfifo);
894 sid &= ~(1 << slp->sl_hostid);
895 sid = ffs(sid) - 1;
896 ti = scsi_low_reselected((struct scsi_low_softc *) sc, sid);
897 if (ti == NULL)
898 return EJUSTRETURN;
899
900 #ifdef NCV_STATICS
901 ncv_statics.reselect ++;
902 #endif /* NCV_STATICS */
903 bus_space_write_1(iot, ioh, cr0_dstid, sid);
904 return 0;
905 }
906
907 static int
908 ncv_disconnected(sc, ti)
909 struct ncv_softc *sc;
910 struct targ_info *ti;
911 {
912 struct scsi_low_softc *slp = &sc->sc_sclow;
913 bus_space_tag_t iot = sc->sc_iot;
914 bus_space_handle_t ioh = sc->sc_ioh;
915
916 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
917 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ENSEL);
918
919 #ifdef NCV_STATICS
920 ncv_statics.disconnect ++;
921 #endif /* NCV_STATICS */
922
923 scsi_low_disconnected(slp, ti);
924 return 1;
925 }
926
927 /**************************************************************
928 * SEQUENCER
929 **************************************************************/
930 static int
931 ncv_target_nexus_establish(sc)
932 struct ncv_softc *sc;
933 {
934 struct scsi_low_softc *slp = &sc->sc_sclow;
935 struct targ_info *ti = slp->sl_Tnexus;
936 struct ncv_targ_info *nti = (void *) ti;
937 bus_space_tag_t iot = sc->sc_iot;
938 bus_space_handle_t ioh = sc->sc_ioh;
939
940 bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
941 bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
942 bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
943 return 0;
944 }
945
946 static int
947 ncv_lun_nexus_establish(sc)
948 struct ncv_softc *sc;
949 {
950
951 return 0;
952 }
953
954 static int
955 ncv_ccb_nexus_establish(sc)
956 struct ncv_softc *sc;
957 {
958 struct scsi_low_softc *slp = &sc->sc_sclow;
959 struct slccb *cb = slp->sl_Qnexus;
960
961 sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
962 return 0;
963 }
964
965 static int
966 ncv_catch_intr(sc)
967 struct ncv_softc *sc;
968 {
969 bus_space_tag_t iot = sc->sc_iot;
970 bus_space_handle_t ioh = sc->sc_ioh;
971 int wc;
972 register u_int8_t status;
973
974 for (wc = 0; wc < NCV_DELAY_MAX / NCV_DELAY_INTERVAL; wc ++)
975 {
976 status = bus_space_read_1(iot, ioh, cr0_stat);
977 if ((status & STAT_INT) != 0)
978 return 0;
979
980 SCSI_LOW_DELAY(NCV_DELAY_INTERVAL);
981 }
982 return EJUSTRETURN;
983 }
984
985 int
986 ncvintr(arg)
987 void *arg;
988 {
989 struct ncv_softc *sc = arg;
990 struct scsi_low_softc *slp = &sc->sc_sclow;
991 bus_space_tag_t iot = sc->sc_iot;
992 bus_space_handle_t ioh = sc->sc_ioh;
993 struct targ_info *ti;
994 struct physio_proc *pp;
995 struct buf *bp;
996 u_int derror, flags;
997 int len;
998 u_int8_t regv, status, ireason;
999
1000 again:
1001 if (slp->sl_flags & HW_INACTIVE)
1002 return 0;
1003
1004 /********************************************
1005 * Status
1006 ********************************************/
1007 ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
1008 status = bus_space_read_1(iot, ioh, cr0_stat);
1009 if ((status & STAT_INT) == 0 || status == (u_int8_t) -1)
1010 return 0;
1011
1012 ireason = bus_space_read_1(iot, ioh, cr0_istat);
1013 if ((ireason & INTR_SBR) != 0)
1014 {
1015 u_int8_t val;
1016
1017 /* avoid power off hangup */
1018 val = bus_space_read_1(iot, ioh, cr0_cfg1);
1019 bus_space_write_1(iot, ioh, cr0_cfg1, val | C1_SRR);
1020
1021 /* status init */
1022 scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT,
1023 "bus reset (power off?)");
1024 return 1;
1025 }
1026
1027 /********************************************
1028 * Debug section
1029 ********************************************/
1030 #ifdef NCV_DEBUG
1031 if (ncv_debug)
1032 {
1033 scsi_low_print(slp, NULL);
1034 printf("%s st %x ist %x\n\n", slp->sl_xname,
1035 status, ireason);
1036 #ifdef KDB
1037 if (ncv_debug > 1)
1038 SCSI_LOW_DEBUGGER("ncv");
1039 #endif /* KDB */
1040 }
1041 #endif /* NCV_DEBUG */
1042
1043 /********************************************
1044 * Reselect or Disconnect or Nexus check
1045 ********************************************/
1046 /* (I) reselect */
1047 if (ireason == INTR_RESELECT)
1048 {
1049 if (ncv_reselected(sc) == EJUSTRETURN)
1050 return 1;
1051 }
1052
1053 /* (II) nexus */
1054 if ((ti = slp->sl_Tnexus) == NULL)
1055 return 0;
1056
1057 derror = 0;
1058 if ((status & (STAT_PE | STAT_GE)) != 0)
1059 {
1060 slp->sl_error |= PARITYERR;
1061 if ((status & PHASE_MASK) == MESSAGE_IN_PHASE)
1062 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
1063 else
1064 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
1065 derror = SCSI_LOW_DATA_PE;
1066 }
1067
1068 if ((ireason & (INTR_DIS | INTR_ILL)) != 0)
1069 {
1070 if ((ireason & INTR_ILL) == 0)
1071 return ncv_disconnected(sc, ti);
1072
1073 slp->sl_error |= FATALIO;
1074 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "illegal cmd");
1075 return 1;
1076 }
1077
1078 /********************************************
1079 * Internal scsi phase
1080 ********************************************/
1081 switch (ti->ti_phase)
1082 {
1083 case PH_SELSTART:
1084 scsi_low_arbit_win(slp);
1085 SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
1086
1087 if (sc->sc_selstop == 0)
1088 {
1089 /* XXX:
1090 * Here scsi phases expected are
1091 * DATA PHASE:
1092 * MSGIN : target wants to disconnect the host.
1093 * STATUSIN : immediate command completed.
1094 * CMD PHASE : command out failed
1095 * MSGOUT : identify command failed.
1096 */
1097 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1098 break;
1099 }
1100 else
1101 {
1102 if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
1103 break;
1104 if ((ireason & INTR_FC) != 0)
1105 {
1106 SCSI_LOW_ASSERT_ATN(slp);
1107 }
1108 }
1109 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1110 break;
1111
1112 case PH_RESEL:
1113 ncv_target_nexus_establish(sc);
1114 if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
1115 {
1116 printf("%s: unexpected phase after reselect\n",
1117 slp->sl_xname);
1118 slp->sl_error |= FATALIO;
1119 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1120 return 1;
1121 }
1122 break;
1123
1124 default:
1125 if ((slp->sl_flags & HW_PDMASTART) != 0)
1126 {
1127 ncv_pdma_end(sc, ti);
1128 }
1129 break;
1130 }
1131
1132 /********************************************
1133 * Scsi phase sequencer
1134 ********************************************/
1135 switch (status & PHASE_MASK)
1136 {
1137 case DATA_OUT_PHASE: /* data out */
1138 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1139 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
1140 {
1141 scsi_low_attention(slp);
1142 }
1143
1144 pp = physio_proc_enter(bp);
1145 if (slp->sl_scp.scp_datalen <= 0)
1146 {
1147 if ((ireason & INTR_BS) == 0)
1148 break;
1149
1150 if ((slp->sl_error & PDMAERR) == 0)
1151 printf("%s: data underrun\n", slp->sl_xname);
1152 slp->sl_error |= PDMAERR;
1153
1154 if ((slp->sl_flags & HW_WRITE_PADDING) != 0)
1155 {
1156 u_int8_t padding[NCV_PADDING_SIZE];
1157
1158 SCSI_LOW_BZERO(padding, sizeof(padding));
1159 ncv_pio_write(sc, padding, sizeof(padding));
1160 }
1161 else
1162 {
1163 printf("%s: write padding required\n",
1164 slp->sl_xname);
1165 }
1166 }
1167 else
1168 {
1169 len = slp->sl_scp.scp_datalen;
1170 if ((ncv_io_control & NCV_WRITE_INTERRUPTS_DRIVEN) != 0)
1171 {
1172 if (len > ncv_data_write_bytes)
1173 len = ncv_data_write_bytes;
1174 }
1175 ncv_pio_write(sc, slp->sl_scp.scp_data, len);
1176 }
1177 physio_proc_leave(pp);
1178 break;
1179
1180 case DATA_IN_PHASE: /* data in */
1181 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
1182 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
1183 {
1184 scsi_low_attention(slp);
1185 }
1186
1187 pp = physio_proc_enter(bp);
1188 if (slp->sl_scp.scp_datalen <= 0)
1189 {
1190 if ((ireason & INTR_BS) == 0)
1191 break;
1192
1193 if ((slp->sl_error & PDMAERR) == 0)
1194 printf("%s: data overrun\n", slp->sl_xname);
1195 slp->sl_error |= PDMAERR;
1196
1197 if ((slp->sl_flags & HW_READ_PADDING) != 0)
1198 {
1199 u_int8_t padding[NCV_PADDING_SIZE];
1200
1201 ncv_pio_read(sc, padding, sizeof(padding));
1202 }
1203 else
1204 {
1205 printf("%s: read padding required\n",
1206 slp->sl_xname);
1207 break;
1208 }
1209 }
1210 else
1211 {
1212 len = slp->sl_scp.scp_datalen;
1213 if ((ncv_io_control & NCV_READ_INTERRUPTS_DRIVEN) != 0)
1214 {
1215 if (len > ncv_data_read_bytes)
1216 len = ncv_data_read_bytes;
1217 }
1218 ncv_pio_read(sc, slp->sl_scp.scp_data, len);
1219 }
1220 physio_proc_leave(pp);
1221 break;
1222
1223 case COMMAND_PHASE: /* cmd out */
1224 SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
1225 if (scsi_low_cmd(slp, ti) != 0)
1226 {
1227 scsi_low_attention(slp);
1228 }
1229
1230 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1231 ncvhw_fpush(iot, ioh,
1232 slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
1233 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1234 break;
1235
1236 case STATUS_PHASE: /* status in */
1237 SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
1238 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1239 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ICCS);
1240 sc->sc_compseq = 1;
1241 break;
1242
1243 default:
1244 break;
1245
1246 case MESSAGE_OUT_PHASE: /* msg out */
1247 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
1248 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1249
1250 flags = SCSI_LOW_MSGOUT_UNIFY;
1251 if (ti->ti_ophase != ti->ti_phase)
1252 flags |= SCSI_LOW_MSGOUT_INIT;
1253 len = scsi_low_msgout(slp, ti, flags);
1254
1255 if (len > 1 && slp->sl_atten == 0)
1256 {
1257 scsi_low_attention(slp);
1258 }
1259
1260 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
1261 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1262 SCSI_LOW_DEASSERT_ATN(slp);
1263 break;
1264
1265 case MESSAGE_IN_PHASE: /* msg in */
1266 SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
1267
1268 len = bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK;
1269 if (sc->sc_compseq != 0)
1270 {
1271 sc->sc_compseq = 0;
1272 if ((ireason & INTR_FC) && len == 2)
1273 {
1274 regv = bus_space_read_1(iot, ioh, cr0_sfifo);
1275 scsi_low_statusin(slp, ti, regv | derror);
1276 len --;
1277 }
1278 else
1279 {
1280 slp->sl_error |= FATALIO;
1281 scsi_low_assert_msg(slp, ti,
1282 SCSI_LOW_MSG_ABORT, 1);
1283 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1284 cr0_cmd, CMD_MSGOK);
1285 break;
1286 }
1287 }
1288 else if (ireason & INTR_BS)
1289 {
1290 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
1291 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
1292 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1293 {
1294 if (ncv_catch_intr(sc) == 0)
1295 goto again;
1296 }
1297 break;
1298 }
1299
1300 if ((ireason & INTR_FC) && len == 1)
1301 {
1302 regv = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
1303 cr0_sfifo);
1304 if (scsi_low_msgin(slp, ti, regv | derror) == 0)
1305 {
1306 if (scsi_low_is_msgout_continue(ti, 0) != 0)
1307 {
1308 scsi_low_attention(slp);
1309 }
1310 }
1311 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,
1312 CMD_MSGOK);
1313 if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
1314 {
1315 /* XXX:
1316 * clear a pending interrupt and sync with
1317 * a next interrupt!
1318 */
1319 ncv_catch_intr(sc);
1320 }
1321 }
1322 else
1323 {
1324 slp->sl_error |= FATALIO;
1325 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
1326 bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,
1327 CMD_MSGOK);
1328 }
1329 break;
1330 }
1331
1332 return 1;
1333 }
Cache object: 7df86dab3bca7316636c124bfc0f3766
|