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