1 /* $FreeBSD: src/sys/dev/ncv/ncr53c500.c,v 1.1.2.4 2001/12/17 13:30:18 non Exp $ */
2 /* $DragonFly: src/sys/dev/disk/ncv/ncr53c500.c,v 1.13 2007/01/06 08:28:53 dillon Exp $ */
3 /* $NecBSD: ncr53c500.c,v 1.30.12.3 2001/06/26 07:31:41 honda Exp $ */
8 #define NCV_IO_CONTROL_FLAGS (0)
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.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
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.
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.
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
46 #include <sys/queue.h>
47 #include <sys/malloc.h>
48 #include <sys/errno.h>
50 #include <sys/thread2.h>
52 #include <machine/clock.h>
53 #include <machine/cpu.h>
57 #include <bus/cam/scsi/scsi_low.h>
59 #include "ncr53c500reg.h"
60 #include "ncr53c500hw.h"
61 #include "ncr53c500var.h"
63 #include "ncr53c500hwtab.h"
65 #define NCV_MAX_DATA_SIZE (64 * 1024)
66 #define NCV_DELAY_MAX (2 * 1000 * 1000)
67 #define NCV_DELAY_INTERVAL (1)
68 #define NCV_PADDING_SIZE (32)
70 /***************************************************
72 ***************************************************/
73 #define NCV_READ_INTERRUPTS_DRIVEN 0x0001
74 #define NCV_WRITE_INTERRUPTS_DRIVEN 0x0002
75 #define NCV_ENABLE_FAST_SCSI 0x0010
76 #define NCV_FAST_INTERRUPTS 0x0100
78 u_int ncv_io_control
= NCV_IO_CONTROL_FLAGS
;
79 int ncv_data_read_bytes
= 4096;
80 int ncv_data_write_bytes
= 4096;
82 /***************************************************
84 ***************************************************/
87 #endif /* NCV_DEBUG */
94 #endif /* NCV_STATICS */
96 /***************************************************
98 ***************************************************/
99 extern struct cfdriver ncv_cd
;
101 /**************************************************************
103 **************************************************************/
105 static void ncv_pio_read (struct ncv_softc
*, u_int8_t
*, u_int
);
106 static void ncv_pio_write (struct ncv_softc
*, u_int8_t
*, u_int
);
107 static int ncv_msg (struct ncv_softc
*, struct targ_info
*, u_int
);
108 static int ncv_reselected (struct ncv_softc
*);
109 static int ncv_disconnected (struct ncv_softc
*, struct targ_info
*);
111 static __inline
void ncvhw_set_count (bus_space_tag_t
, bus_space_handle_t
, int);
112 static __inline u_int
ncvhw_get_count (bus_space_tag_t
, bus_space_handle_t
);
113 static __inline
void ncvhw_select_register_0 (bus_space_tag_t
, bus_space_handle_t
, struct ncv_hw
*);
114 static __inline
void ncvhw_select_register_1 (bus_space_tag_t
, bus_space_handle_t
, struct ncv_hw
*);
115 static __inline
void ncvhw_fpush (bus_space_tag_t
, bus_space_handle_t
, u_int8_t
*, int);
117 static void ncv_pdma_end (struct ncv_softc
*sc
, struct targ_info
*);
118 static int ncv_world_start (struct ncv_softc
*, int);
119 static void ncvhw_bus_reset (struct ncv_softc
*);
120 static void ncvhw_reset (bus_space_tag_t
, bus_space_handle_t
, struct ncv_hw
*);
121 static int ncvhw_check (bus_space_tag_t
, bus_space_handle_t
, struct ncv_hw
*);
122 static void ncvhw_init (bus_space_tag_t
, bus_space_handle_t
, struct ncv_hw
*);
123 static int ncvhw_start_selection (struct ncv_softc
*sc
, struct slccb
*);
124 static void ncvhw_attention (struct ncv_softc
*);
125 static int ncv_ccb_nexus_establish (struct ncv_softc
*);
126 static int ncv_lun_nexus_establish (struct ncv_softc
*);
127 static int ncv_target_nexus_establish (struct ncv_softc
*);
128 static int ncv_targ_init (struct ncv_softc
*, struct targ_info
*, int);
129 static int ncv_catch_intr (struct ncv_softc
*);
130 #ifdef NCV_POWER_CONTROL
131 static int ncvhw_power (struct ncv_softc
*, u_int
);
132 #endif /* NCV_POWER_CONTROL */
133 static __inline
void ncv_setup_and_start_pio (struct ncv_softc
*, u_int
);
135 struct scsi_low_funcs ncv_funcs
= {
136 SC_LOW_INIT_T ncv_world_start
,
137 SC_LOW_BUSRST_T ncvhw_bus_reset
,
138 SC_LOW_TARG_INIT_T ncv_targ_init
,
139 SC_LOW_LUN_INIT_T NULL
,
141 SC_LOW_SELECT_T ncvhw_start_selection
,
142 SC_LOW_NEXUS_T ncv_lun_nexus_establish
,
143 SC_LOW_NEXUS_T ncv_ccb_nexus_establish
,
145 SC_LOW_ATTEN_T ncvhw_attention
,
146 SC_LOW_MSG_T ncv_msg
,
148 SC_LOW_TIMEOUT_T NULL
,
149 SC_LOW_POLL_T ncvintr
,
151 NULL
, /* SC_LOW_POWER_T ncvhw_power, */
154 /**************************************************************
156 **************************************************************/
158 ncvhw_select_register_0(bus_space_tag_t iot
, bus_space_handle_t ioh
,
162 bus_space_write_1(iot
, ioh
, cr0_cfg4
, hw
->hw_cfg4
);
166 ncvhw_select_register_1(bus_space_tag_t iot
, bus_space_handle_t ioh
,
170 bus_space_write_1(iot
, ioh
, cr1_cfg5
, hw
->hw_cfg5
);
174 ncvhw_fpush(bus_space_tag_t iot
, bus_space_handle_t ioh
, u_int8_t
*buf
,
179 for (ptr
= 0; ptr
< len
; ptr
++)
180 bus_space_write_1(iot
, ioh
, cr0_sfifo
, buf
[ptr
]);
184 ncvhw_set_count(bus_space_tag_t iot
, bus_space_handle_t ioh
, int count
)
187 bus_space_write_1(iot
, ioh
, cr0_tclsb
, (u_int8_t
) count
);
188 bus_space_write_1(iot
, ioh
, cr0_tcmsb
, (u_int8_t
) (count
>> NBBY
));
189 bus_space_write_1(iot
, ioh
, cr0_tchsb
, (u_int8_t
) (count
>> (NBBY
* 2)));
192 static __inline u_int
193 ncvhw_get_count(bus_space_tag_t iot
, bus_space_handle_t ioh
)
197 count
= (u_int
) bus_space_read_1(iot
, ioh
, cr0_tclsb
);
198 count
|= ((u_int
) bus_space_read_1(iot
, ioh
, cr0_tcmsb
)) << NBBY
;
199 count
|= ((u_int
) bus_space_read_1(iot
, ioh
, cr0_tchsb
)) << (NBBY
* 2);
204 ncvhw_check(bus_space_tag_t iot
, bus_space_handle_t ioh
, struct ncv_hw
*hw
)
208 ncvhw_select_register_0(iot
, ioh
, hw
);
209 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_NOP
| CMD_DMA
);
210 if (bus_space_read_1(iot
, ioh
, cr0_cmd
) != (CMD_NOP
| CMD_DMA
))
213 kprintf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n");
214 #endif /* NCV_DEBUG */
218 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_NOP
);
219 if (bus_space_read_1(iot
, ioh
, cr0_cmd
) != CMD_NOP
)
222 kprintf("ncv: cr0_cmd CMD_NOP failed\n");
223 #endif /* NCV_DEBUG */
228 ncvhw_reset(iot
, ioh
, hw
);
229 ncvhw_init(iot
, ioh
, hw
);
232 ncvhw_select_register_0(iot
, ioh
, hw
);
233 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_FLUSH
);
234 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_RSTSCSI
);
235 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_NOP
| CMD_DMA
);
236 SCSI_LOW_DELAY(100 * 1000);
239 bus_space_read_1(iot
, ioh
, cr0_stat
);
240 stat
= bus_space_read_1(iot
, ioh
, cr0_istat
);
241 SCSI_LOW_DELAY(1000);
243 if (((stat
& INTR_SBR
) == 0) ||
244 (bus_space_read_1(iot
, ioh
, cr0_istat
) & INTR_SBR
))
247 kprintf("ncv: cr0_istat SCSI BUS RESET failed\n");
248 #endif /* NCV_DEBUG */
256 ncvhw_reset(bus_space_tag_t iot
, bus_space_handle_t ioh
,
260 ncvhw_select_register_0(iot
, ioh
, hw
);
262 /* dummy cmd twice */
263 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_NOP
);
264 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_NOP
);
267 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_RSTCHIP
);
269 /* again dummy cmd twice */
270 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_NOP
);
271 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_NOP
);
275 ncvhw_init(bus_space_tag_t iot
, bus_space_handle_t ioh
,
279 ncvhw_select_register_0(iot
, ioh
, hw
);
280 bus_space_write_1(iot
, ioh
, cr0_clk
, hw
->hw_clk
);
281 bus_space_write_1(iot
, ioh
, cr0_srtout
, SEL_TOUT
);
282 bus_space_write_1(iot
, ioh
, cr0_period
, 0);
283 bus_space_write_1(iot
, ioh
, cr0_offs
, 0);
285 bus_space_write_1(iot
, ioh
, cr0_cfg1
, hw
->hw_cfg1
);
286 bus_space_write_1(iot
, ioh
, cr0_cfg2
, hw
->hw_cfg2
);
287 bus_space_write_1(iot
, ioh
, cr0_cfg3
, hw
->hw_cfg3
);
288 bus_space_write_1(iot
, ioh
, cr0_tchsb
, 0);
290 ncvhw_select_register_1(iot
, ioh
, hw
);
291 bus_space_write_1(iot
, ioh
, cr1_fstat
, 0x0);
292 bus_space_write_1(iot
, ioh
, cr1_pflag
, 0x0);
293 bus_space_write_1(iot
, ioh
, cr1_atacmd
, ATACMD_ENGAGE
);
295 ncvhw_select_register_0(iot
, ioh
, hw
);
298 #ifdef NCV_POWER_CONTROL
300 ncvhw_power(struct ncv_softc
*sc
, u_int flags
)
302 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
303 bus_space_tag_t iot
= sc
->sc_iot
;
304 bus_space_handle_t ioh
= sc
->sc_ioh
;
306 if (flags
== SCSI_LOW_POWDOWN
)
308 kprintf("%s power down\n", slp
->sl_xname
);
309 ncvhw_select_register_1(iot
, ioh
, &sc
->sc_hw
);
310 bus_space_write_1(iot
, ioh
, cr1_atacmd
, ATACMD_POWDOWN
);
314 switch (sc
->sc_rstep
)
317 kprintf("%s resume step O\n", slp
->sl_xname
);
318 ncvhw_select_register_1(iot
, ioh
, &sc
->sc_hw
);
319 bus_space_write_1(iot
, ioh
, cr1_atacmd
, ATACMD_ENGAGE
);
323 kprintf("%s resume step I\n", slp
->sl_xname
);
324 ncvhw_reset(iot
, ioh
, &sc
->sc_hw
);
325 ncvhw_init(iot
, ioh
, &sc
->sc_hw
);
332 #endif /* NCV_POWER_CONTROL */
334 /**************************************************************
336 **************************************************************/
338 ncvhw_attention(struct ncv_softc
*sc
)
341 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, cr0_cmd
, CMD_SETATN
);
346 ncvhw_bus_reset(struct ncv_softc
*sc
)
348 bus_space_tag_t iot
= sc
->sc_iot
;
349 bus_space_handle_t ioh
= sc
->sc_ioh
;
351 ncvhw_select_register_0(iot
, ioh
, &sc
->sc_hw
);
352 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_FLUSH
);
353 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_RSTSCSI
);
354 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_NOP
| CMD_DMA
);
358 ncvhw_start_selection(struct ncv_softc
*sc
, struct slccb
*cb
)
360 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
361 bus_space_tag_t iot
= sc
->sc_iot
;
362 bus_space_handle_t ioh
= sc
->sc_ioh
;
363 struct targ_info
*ti
= cb
->ti
;
368 sc
->sc_tmaxcnt
= cb
->ccb_tcmax
* 1000 * 1000;
370 if (scsi_low_is_msgout_continue(ti
, SCSI_LOW_MSG_IDENTIFY
) == 0)
374 flags
= SCSI_LOW_MSGOUT_UNIFY
| SCSI_LOW_MSGOUT_INIT
;
376 else if (scsi_low_is_msgout_continue(ti
,
377 SCSI_LOW_MSG_IDENTIFY
| SCSI_LOW_MSG_SIMPLE_QTAG
) == 0)
381 flags
= SCSI_LOW_MSGOUT_UNIFY
| SCSI_LOW_MSGOUT_INIT
;
387 flags
= SCSI_LOW_MSGOUT_INIT
;
390 ncvhw_select_register_0(iot
, ioh
, &sc
->sc_hw
);
391 if ((bus_space_read_1(iot
, ioh
, cr0_stat
) & STAT_INT
) != 0)
392 return SCSI_LOW_START_FAIL
;
394 ncv_target_nexus_establish(sc
);
396 len
= scsi_low_msgout(slp
, ti
, flags
);
397 if (sc
->sc_selstop
== 0)
398 scsi_low_cmd(slp
, ti
);
401 if ((bus_space_read_1(iot
, ioh
, cr0_stat
) & STAT_INT
) != 0)
404 return SCSI_LOW_START_FAIL
;
407 bus_space_write_1(iot
, ioh
, cr0_dstid
, ti
->ti_id
);
408 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_FLUSH
);
409 ncvhw_fpush(iot
, ioh
, ti
->ti_msgoutstr
, len
);
410 if (sc
->sc_selstop
== 0)
412 ncvhw_fpush(iot
, ioh
,
413 slp
->sl_scp
.scp_cmd
, slp
->sl_scp
.scp_cmdlen
);
415 bus_space_write_1(iot
, ioh
, cr0_cmd
, cmd
);
418 SCSI_LOW_SETUP_PHASE(ti
, PH_SELSTART
);
419 return SCSI_LOW_START_OK
;
423 ncv_world_start(struct ncv_softc
*sc
, int fdone
)
425 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
426 bus_space_tag_t iot
= sc
->sc_iot
;
427 bus_space_handle_t ioh
= sc
->sc_ioh
;
430 if ((slp
->sl_cfgflags
& CFG_NOPARITY
) == 0)
431 sc
->sc_hw
.hw_cfg1
|= C1_PARENB
;
433 sc
->sc_hw
.hw_cfg1
&= ~C1_PARENB
;
435 ncvhw_reset(iot
, ioh
, &sc
->sc_hw
);
436 ncvhw_init(iot
, ioh
, &sc
->sc_hw
);
438 scsi_low_bus_reset(slp
);
440 ncvhw_select_register_0(iot
, ioh
, &sc
->sc_hw
);
441 bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, cr0_stat
);
442 stat
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, cr0_istat
);
443 SCSI_LOW_DELAY(1000);
445 if (((stat
& INTR_SBR
) == 0) ||
446 (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, cr0_istat
) & INTR_SBR
))
449 SOFT_INTR_REQUIRED(slp
);
454 ncv_msg(struct ncv_softc
*sc
, struct targ_info
*ti
, u_int msg
)
456 bus_space_tag_t iot
= sc
->sc_iot
;
457 bus_space_handle_t ioh
= sc
->sc_ioh
;
458 struct ncv_targ_info
*nti
= (void *) ti
;
459 u_int hwcycle
, period
;
461 if ((msg
& SCSI_LOW_MSG_WIDE
) != 0)
463 if (ti
->ti_width
!= SCSI_LOW_BUS_WIDTH_8
)
465 ti
->ti_width
= SCSI_LOW_BUS_WIDTH_8
;
471 if ((msg
& SCSI_LOW_MSG_SYNCH
) == 0)
474 period
= ti
->ti_maxsynch
.period
;
475 hwcycle
= (sc
->sc_hw
.hw_clk
== 0) ? 40 : (5 * sc
->sc_hw
.hw_clk
);
476 hwcycle
= 1000 / hwcycle
;
478 if (period
< 200 / 4 && period
>= 100 / 4)
479 nti
->nti_reg_cfg3
|= sc
->sc_hw
.hw_cfg3_fscsi
;
481 nti
->nti_reg_cfg3
&= ~sc
->sc_hw
.hw_cfg3_fscsi
;
483 period
= ((period
* 40 / hwcycle
) + 5) / 10;
484 nti
->nti_reg_period
= period
& 0x1f;
485 nti
->nti_reg_offset
= ti
->ti_maxsynch
.offset
;
487 bus_space_write_1(iot
, ioh
, cr0_period
, nti
->nti_reg_period
);
488 bus_space_write_1(iot
, ioh
, cr0_offs
, nti
->nti_reg_offset
);
489 bus_space_write_1(iot
, ioh
, cr0_cfg3
, nti
->nti_reg_cfg3
);
494 ncv_targ_init(struct ncv_softc
*sc
, struct targ_info
*ti
, int action
)
496 struct ncv_targ_info
*nti
= (void *) ti
;
498 if (action
== SCSI_LOW_INFO_ALLOC
|| action
== SCSI_LOW_INFO_REVOKE
)
500 ti
->ti_width
= SCSI_LOW_BUS_WIDTH_8
;
501 ti
->ti_maxsynch
.period
= sc
->sc_hw
.hw_mperiod
;
502 ti
->ti_maxsynch
.offset
= sc
->sc_hw
.hw_moffset
;
504 nti
->nti_reg_cfg3
= sc
->sc_hw
.hw_cfg3
;
505 nti
->nti_reg_period
= 0;
506 nti
->nti_reg_offset
= 0;
511 /**************************************************************
512 * General probe attach
513 **************************************************************/
514 static int ncv_setup_img (struct ncv_hw
*, u_int
, int);
517 ncv_setup_img(struct ncv_hw
*hw
, u_int dvcfg
, int hostid
)
520 if (NCV_CLKFACTOR(dvcfg
) > CLK_35M_F
)
522 kprintf("ncv: invalid dvcfg flags\n");
526 if (NCV_C5IMG(dvcfg
) != 0)
528 hw
->hw_cfg5
= NCV_C5IMG(dvcfg
);
529 hw
->hw_clk
= NCV_CLKFACTOR(dvcfg
);
531 if ((ncv_io_control
& NCV_ENABLE_FAST_SCSI
) != 0 &&
532 (NCV_SPECIAL(dvcfg
) & NCVHWCFG_MAX10M
) != 0)
533 hw
->hw_mperiod
= 100 / 4;
535 if (NCV_SPECIAL(dvcfg
) & NCVHWCFG_FIFOBUG
)
536 hw
->hw_cfg3_fclk
= 0x04;
538 if (NCV_SPECIAL(dvcfg
) & NCVHWCFG_SCSI1
)
539 hw
->hw_cfg2
&= ~C2_SCSI2
;
541 if (NCV_SPECIAL(dvcfg
) & NCVHWCFG_SLOW
)
542 hw
->hw_cfg1
|= C1_SLOW
;
545 /* setup configuration image 3 */
546 if (hw
->hw_clk
!= CLK_40M_F
&& hw
->hw_clk
<= CLK_25M_F
)
547 hw
->hw_cfg3
&= ~hw
->hw_cfg3_fclk
;
549 hw
->hw_cfg3
|= hw
->hw_cfg3_fclk
;
551 /* setup configuration image 1 */
552 hw
->hw_cfg1
= (hw
->hw_cfg1
& 0xf0) | hostid
;
557 ncvprobesubr(bus_space_tag_t iot
, bus_space_handle_t ioh
, u_int dvcfg
,
562 hwtab
= ncv_template
;
563 if (ncv_setup_img(&hwtab
, dvcfg
, hsid
))
565 if (ncvhw_check(iot
, ioh
, &hwtab
) != 0)
572 ncvprint(void *aux
, const char *name
)
576 kprintf("%s: scsibus ", name
);
581 ncvattachsubr(struct ncv_softc
*sc
)
583 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
586 sc
->sc_hw
= ncv_template
;
587 ncv_setup_img(&sc
->sc_hw
, slp
->sl_cfgflags
, slp
->sl_hostid
);
588 slp
->sl_funcs
= &ncv_funcs
;
589 slp
->sl_flags
|= HW_READ_PADDING
;
590 sc
->sc_tmaxcnt
= SCSI_LOW_MIN_TOUT
* 1000 * 1000; /* default */
592 (void) scsi_low_attach(slp
, 0, NCV_NTARGETS
, NCV_NLUNS
,
593 sizeof(struct ncv_targ_info
), 0);
596 /**************************************************************
598 **************************************************************/
600 ncv_setup_and_start_pio(struct ncv_softc
*sc
, u_int reqlen
)
602 bus_space_tag_t iot
= sc
->sc_iot
;
603 bus_space_handle_t ioh
= sc
->sc_ioh
;
605 ncvhw_select_register_0(iot
, ioh
, &sc
->sc_hw
);
606 ncvhw_set_count(iot
, ioh
, reqlen
);
607 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_TRANS
| CMD_DMA
);
609 ncvhw_select_register_1(iot
, ioh
, &sc
->sc_hw
);
610 bus_space_write_1(iot
, ioh
, cr1_fstat
, FIFO_EN
);
614 ncv_pdma_end(struct ncv_softc
*sc
, struct targ_info
*ti
)
616 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
617 bus_space_tag_t iot
= sc
->sc_iot
;
618 bus_space_handle_t ioh
= sc
->sc_ioh
;
621 slp
->sl_flags
&= ~HW_PDMASTART
;
622 if (slp
->sl_Qnexus
== NULL
)
624 slp
->sl_error
|= PDMAERR
;
628 if (ti
->ti_phase
== PH_DATA
)
630 len
= ncvhw_get_count(sc
->sc_iot
, sc
->sc_ioh
);
631 if (slp
->sl_scp
.scp_direction
== SCSI_LOW_WRITE
)
632 len
+= (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
,
633 cr0_sffl
) & CR0_SFFLR_BMASK
);
635 if ((u_int
) len
<= (u_int
) sc
->sc_sdatalen
)
637 if ((slp
->sl_scp
.scp_direction
== SCSI_LOW_READ
) &&
638 sc
->sc_tdatalen
!= len
)
641 len
= sc
->sc_sdatalen
- len
;
642 if ((u_int
) len
> (u_int
) slp
->sl_scp
.scp_datalen
)
645 slp
->sl_scp
.scp_data
+= len
;
646 slp
->sl_scp
.scp_datalen
-= len
;
651 if ((slp
->sl_error
& PDMAERR
) == 0)
653 kprintf("%s: stragne cnt hw 0x%x soft 0x%x\n",
655 slp
->sl_scp
.scp_datalen
);
657 slp
->sl_error
|= PDMAERR
;
659 scsi_low_data_finish(slp
);
663 kprintf("%s: data phase miss\n", slp
->sl_xname
);
664 slp
->sl_error
|= PDMAERR
;
668 ncvhw_select_register_1(iot
, ioh
, &sc
->sc_hw
);
669 bus_space_write_1(iot
, ioh
, cr1_fstat
, 0);
670 ncvhw_select_register_0(iot
, ioh
, &sc
->sc_hw
);
674 ncv_pio_read(struct ncv_softc
*sc
, u_int8_t
*buf
, u_int reqlen
)
676 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
677 bus_space_tag_t iot
= sc
->sc_iot
;
678 bus_space_handle_t ioh
= sc
->sc_ioh
;
682 ncv_setup_and_start_pio(sc
, reqlen
);
683 slp
->sl_flags
|= HW_PDMASTART
;
684 sc
->sc_sdatalen
= reqlen
;
685 tout
= sc
->sc_tmaxcnt
;
687 while (reqlen
>= FIFO_F_SZ
&& tout
-- > 0)
689 fstat
= bus_space_read_1(iot
, ioh
, cr1_fstat
);
690 if (fstat
== (u_int8_t
) -1)
694 #define NCV_FAST32_ACCESS
695 #ifdef NCV_FAST32_ACCESS
696 bus_space_read_multi_4(iot
, ioh
, cr1_fdata
,
697 (u_int32_t
*) buf
, FIFO_F_SZ
/ 4);
698 #else /* !NCV_FAST32_ACCESS */
699 bus_space_read_multi_2(iot
, ioh
, cr1_fdata
,
700 (u_int16_t
*) buf
, FIFO_F_SZ
/ 2);
701 #endif /* !NCV_FAST32_ACCESS */
707 if (fstat
& FIFO_BRK
)
714 while (reqlen
> 0 && tout
-- > 0)
716 fstat
= bus_space_read_1(iot
, ioh
, cr1_fstat
);
717 if ((fstat
& FIFO_E
) == 0)
719 *buf
++ = bus_space_read_1(iot
, ioh
, cr1_fdata
);
724 if (fstat
& FIFO_BRK
)
732 ncvhw_select_register_0(iot
, ioh
, &sc
->sc_hw
);
733 sc
->sc_tdatalen
= reqlen
;
737 ncv_pio_write(struct ncv_softc
*sc
, u_int8_t
*buf
, u_int reqlen
)
739 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
740 bus_space_tag_t iot
= sc
->sc_iot
;
741 bus_space_handle_t ioh
= sc
->sc_ioh
;
745 ncv_setup_and_start_pio(sc
, reqlen
);
746 sc
->sc_sdatalen
= reqlen
;
747 tout
= sc
->sc_tmaxcnt
;
748 slp
->sl_flags
|= HW_PDMASTART
;
750 while (reqlen
>= FIFO_F_SZ
&& tout
-- > 0)
752 fstat
= bus_space_read_1(iot
, ioh
, cr1_fstat
);
753 if (fstat
& FIFO_BRK
)
756 if ((fstat
& FIFO_E
) != 0)
758 #ifdef NCV_FAST32_ACCESS
759 bus_space_write_multi_4(iot
, ioh
, cr1_fdata
,
760 (u_int32_t
*) buf
, FIFO_F_SZ
/ 4);
761 #else /* !NCV_FAST32_ACCESS */
762 bus_space_write_multi_2(iot
, ioh
, cr1_fdata
,
763 (u_int16_t
*) buf
, FIFO_F_SZ
/ 2);
764 #endif /* !NCV_FAST32_ACCESS */
774 while (reqlen
> 0 && tout
-- > 0)
776 fstat
= bus_space_read_1(iot
, ioh
, cr1_fstat
);
777 if (fstat
& FIFO_BRK
)
780 if ((fstat
& FIFO_F
) == 0) /* fifo not full */
782 bus_space_write_1(iot
, ioh
, cr1_fdata
, *buf
++);
792 ncvhw_select_register_0(iot
, ioh
, &sc
->sc_hw
);
795 /**************************************************************
796 * disconnect & reselect (HW low)
797 **************************************************************/
799 ncv_reselected(struct ncv_softc
*sc
)
801 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
802 bus_space_tag_t iot
= sc
->sc_iot
;
803 bus_space_handle_t ioh
= sc
->sc_ioh
;
804 struct targ_info
*ti
;
807 if ((bus_space_read_1(iot
, ioh
, cr0_sffl
) & CR0_SFFLR_BMASK
) != 2)
809 kprintf("%s illegal fifo bytes\n", slp
->sl_xname
);
810 scsi_low_restart(slp
, SCSI_LOW_RESTART_HARD
, "chip confused");
814 sid
= (u_int
) bus_space_read_1(iot
, ioh
, cr0_sfifo
);
815 sid
&= ~(1 << slp
->sl_hostid
);
817 ti
= scsi_low_reselected((struct scsi_low_softc
*) sc
, sid
);
822 ncv_statics
.reselect
++;
823 #endif /* NCV_STATICS */
824 bus_space_write_1(iot
, ioh
, cr0_dstid
, sid
);
829 ncv_disconnected(struct ncv_softc
*sc
, struct targ_info
*ti
)
831 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
832 bus_space_tag_t iot
= sc
->sc_iot
;
833 bus_space_handle_t ioh
= sc
->sc_ioh
;
835 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_FLUSH
);
836 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_ENSEL
);
839 ncv_statics
.disconnect
++;
840 #endif /* NCV_STATICS */
842 scsi_low_disconnected(slp
, ti
);
846 /**************************************************************
848 **************************************************************/
850 ncv_target_nexus_establish(struct ncv_softc
*sc
)
852 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
853 struct targ_info
*ti
= slp
->sl_Tnexus
;
854 struct ncv_targ_info
*nti
= (void *) ti
;
855 bus_space_tag_t iot
= sc
->sc_iot
;
856 bus_space_handle_t ioh
= sc
->sc_ioh
;
858 bus_space_write_1(iot
, ioh
, cr0_period
, nti
->nti_reg_period
);
859 bus_space_write_1(iot
, ioh
, cr0_offs
, nti
->nti_reg_offset
);
860 bus_space_write_1(iot
, ioh
, cr0_cfg3
, nti
->nti_reg_cfg3
);
865 ncv_lun_nexus_establish(struct ncv_softc
*sc
)
872 ncv_ccb_nexus_establish(struct ncv_softc
*sc
)
874 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
875 struct slccb
*cb
= slp
->sl_Qnexus
;
877 sc
->sc_tmaxcnt
= cb
->ccb_tcmax
* 1000 * 1000;
882 ncv_catch_intr(struct ncv_softc
*sc
)
884 bus_space_tag_t iot
= sc
->sc_iot
;
885 bus_space_handle_t ioh
= sc
->sc_ioh
;
889 for (wc
= 0; wc
< NCV_DELAY_MAX
/ NCV_DELAY_INTERVAL
; wc
++)
891 status
= bus_space_read_1(iot
, ioh
, cr0_stat
);
892 if ((status
& STAT_INT
) != 0)
895 SCSI_LOW_DELAY(NCV_DELAY_INTERVAL
);
903 struct ncv_softc
*sc
= arg
;
904 struct scsi_low_softc
*slp
= &sc
->sc_sclow
;
905 bus_space_tag_t iot
= sc
->sc_iot
;
906 bus_space_handle_t ioh
= sc
->sc_ioh
;
907 struct targ_info
*ti
;
911 u_int8_t regv
, status
, ireason
;
914 if (slp
->sl_flags
& HW_INACTIVE
)
917 /********************************************
919 ********************************************/
920 ncvhw_select_register_0(iot
, ioh
, &sc
->sc_hw
);
921 status
= bus_space_read_1(iot
, ioh
, cr0_stat
);
922 if ((status
& STAT_INT
) == 0 || status
== (u_int8_t
) -1)
925 ireason
= bus_space_read_1(iot
, ioh
, cr0_istat
);
926 if ((ireason
& INTR_SBR
) != 0)
930 /* avoid power off hangup */
931 val
= bus_space_read_1(iot
, ioh
, cr0_cfg1
);
932 bus_space_write_1(iot
, ioh
, cr0_cfg1
, val
| C1_SRR
);
935 scsi_low_restart(slp
, SCSI_LOW_RESTART_SOFT
,
936 "bus reset (power off?)");
940 /********************************************
942 ********************************************/
946 scsi_low_print(slp
, NULL
);
947 kprintf("%s st %x ist %x\n\n", slp
->sl_xname
,
951 SCSI_LOW_DEBUGGER("ncv");
954 #endif /* NCV_DEBUG */
956 /********************************************
957 * Reselect or Disconnect or Nexus check
958 ********************************************/
960 if (ireason
== INTR_RESELECT
)
962 if (ncv_reselected(sc
) == EJUSTRETURN
)
967 if ((ti
= slp
->sl_Tnexus
) == NULL
)
971 if ((status
& (STAT_PE
| STAT_GE
)) != 0)
973 slp
->sl_error
|= PARITYERR
;
974 if ((status
& PHASE_MASK
) == MESSAGE_IN_PHASE
)
975 scsi_low_assert_msg(slp
, ti
, SCSI_LOW_MSG_PARITY
, 0);
977 scsi_low_assert_msg(slp
, ti
, SCSI_LOW_MSG_ERROR
, 1);
978 derror
= SCSI_LOW_DATA_PE
;
981 if ((ireason
& (INTR_DIS
| INTR_ILL
)) != 0)
983 if ((ireason
& INTR_ILL
) == 0)
984 return ncv_disconnected(sc
, ti
);
986 slp
->sl_error
|= FATALIO
;
987 scsi_low_restart(slp
, SCSI_LOW_RESTART_HARD
, "illegal cmd");
991 /********************************************
992 * Internal scsi phase
993 ********************************************/
994 switch (ti
->ti_phase
)
997 scsi_low_arbit_win(slp
);
998 SCSI_LOW_SETUP_PHASE(ti
, PH_SELECTED
);
1000 if (sc
->sc_selstop
== 0)
1003 * Here scsi phases expected are
1005 * MSGIN : target wants to disconnect the host.
1006 * STATUSIN : immediate command completed.
1007 * CMD PHASE : command out failed
1008 * MSGOUT : identify command failed.
1010 if ((status
& PHASE_MASK
) != MESSAGE_OUT_PHASE
)
1015 if ((status
& PHASE_MASK
) != MESSAGE_OUT_PHASE
)
1017 if ((ireason
& INTR_FC
) != 0)
1019 SCSI_LOW_ASSERT_ATN(slp
);
1022 SCSI_LOW_SETUP_PHASE(ti
, PH_MSGOUT
);
1026 ncv_target_nexus_establish(sc
);
1027 if ((status
& PHASE_MASK
) != MESSAGE_IN_PHASE
)
1029 kprintf("%s: unexpected phase after reselect\n",
1031 slp
->sl_error
|= FATALIO
;
1032 scsi_low_assert_msg(slp
, ti
, SCSI_LOW_MSG_ABORT
, 1);
1038 if ((slp
->sl_flags
& HW_PDMASTART
) != 0)
1040 ncv_pdma_end(sc
, ti
);
1045 /********************************************
1046 * Scsi phase sequencer
1047 ********************************************/
1048 switch (status
& PHASE_MASK
)
1050 case DATA_OUT_PHASE
: /* data out */
1051 SCSI_LOW_SETUP_PHASE(ti
, PH_DATA
);
1052 if (scsi_low_data(slp
, ti
, &bp
, SCSI_LOW_WRITE
) != 0)
1054 scsi_low_attention(slp
);
1057 if (slp
->sl_scp
.scp_datalen
<= 0)
1059 if ((ireason
& INTR_BS
) == 0)
1062 if ((slp
->sl_error
& PDMAERR
) == 0)
1063 kprintf("%s: data underrun\n", slp
->sl_xname
);
1064 slp
->sl_error
|= PDMAERR
;
1066 if ((slp
->sl_flags
& HW_WRITE_PADDING
) != 0)
1068 u_int8_t padding
[NCV_PADDING_SIZE
];
1070 SCSI_LOW_BZERO(padding
, sizeof(padding
));
1071 ncv_pio_write(sc
, padding
, sizeof(padding
));
1075 kprintf("%s: write padding required\n",
1081 len
= slp
->sl_scp
.scp_datalen
;
1082 if ((ncv_io_control
& NCV_WRITE_INTERRUPTS_DRIVEN
) != 0)
1084 if (len
> ncv_data_write_bytes
)
1085 len
= ncv_data_write_bytes
;
1087 ncv_pio_write(sc
, slp
->sl_scp
.scp_data
, len
);
1091 case DATA_IN_PHASE
: /* data in */
1092 SCSI_LOW_SETUP_PHASE(ti
, PH_DATA
);
1093 if (scsi_low_data(slp
, ti
, &bp
, SCSI_LOW_READ
) != 0)
1095 scsi_low_attention(slp
);
1098 if (slp
->sl_scp
.scp_datalen
<= 0)
1100 if ((ireason
& INTR_BS
) == 0)
1103 if ((slp
->sl_error
& PDMAERR
) == 0)
1104 kprintf("%s: data overrun\n", slp
->sl_xname
);
1105 slp
->sl_error
|= PDMAERR
;
1107 if ((slp
->sl_flags
& HW_READ_PADDING
) != 0)
1109 u_int8_t padding
[NCV_PADDING_SIZE
];
1111 ncv_pio_read(sc
, padding
, sizeof(padding
));
1115 kprintf("%s: read padding required\n",
1122 len
= slp
->sl_scp
.scp_datalen
;
1123 if ((ncv_io_control
& NCV_READ_INTERRUPTS_DRIVEN
) != 0)
1125 if (len
> ncv_data_read_bytes
)
1126 len
= ncv_data_read_bytes
;
1128 ncv_pio_read(sc
, slp
->sl_scp
.scp_data
, len
);
1132 case COMMAND_PHASE
: /* cmd out */
1133 SCSI_LOW_SETUP_PHASE(ti
, PH_CMD
);
1134 if (scsi_low_cmd(slp
, ti
) != 0)
1136 scsi_low_attention(slp
);
1139 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_FLUSH
);
1140 ncvhw_fpush(iot
, ioh
,
1141 slp
->sl_scp
.scp_cmd
, slp
->sl_scp
.scp_cmdlen
);
1142 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_TRANS
);
1145 case STATUS_PHASE
: /* status in */
1146 SCSI_LOW_SETUP_PHASE(ti
, PH_STAT
);
1147 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_FLUSH
);
1148 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_ICCS
);
1155 case MESSAGE_OUT_PHASE
: /* msg out */
1156 SCSI_LOW_SETUP_PHASE(ti
, PH_MSGOUT
);
1157 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_FLUSH
);
1159 flags
= SCSI_LOW_MSGOUT_UNIFY
;
1160 if (ti
->ti_ophase
!= ti
->ti_phase
)
1161 flags
|= SCSI_LOW_MSGOUT_INIT
;
1162 len
= scsi_low_msgout(slp
, ti
, flags
);
1164 if (len
> 1 && slp
->sl_atten
== 0)
1166 scsi_low_attention(slp
);
1169 ncvhw_fpush(iot
, ioh
, ti
->ti_msgoutstr
, len
);
1170 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_TRANS
);
1171 SCSI_LOW_DEASSERT_ATN(slp
);
1174 case MESSAGE_IN_PHASE
: /* msg in */
1175 SCSI_LOW_SETUP_PHASE(ti
, PH_MSGIN
);
1177 len
= bus_space_read_1(iot
, ioh
, cr0_sffl
) & CR0_SFFLR_BMASK
;
1178 if (sc
->sc_compseq
!= 0)
1181 if ((ireason
& INTR_FC
) && len
== 2)
1183 regv
= bus_space_read_1(iot
, ioh
, cr0_sfifo
);
1184 scsi_low_statusin(slp
, ti
, regv
| derror
);
1189 slp
->sl_error
|= FATALIO
;
1190 scsi_low_assert_msg(slp
, ti
,
1191 SCSI_LOW_MSG_ABORT
, 1);
1192 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
,
1193 cr0_cmd
, CMD_MSGOK
);
1197 else if (ireason
& INTR_BS
)
1199 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_FLUSH
);
1200 bus_space_write_1(iot
, ioh
, cr0_cmd
, CMD_TRANS
);
1201 if ((ncv_io_control
& NCV_FAST_INTERRUPTS
) != 0)
1203 if (ncv_catch_intr(sc
) == 0)
1209 if ((ireason
& INTR_FC
) && len
== 1)
1211 regv
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
,
1213 if (scsi_low_msgin(slp
, ti
, regv
| derror
) == 0)
1215 if (scsi_low_is_msgout_continue(ti
, 0) != 0)
1217 scsi_low_attention(slp
);
1220 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, cr0_cmd
,
1222 if ((ncv_io_control
& NCV_FAST_INTERRUPTS
) != 0)
1225 * clear a pending interrupt and sync with
1233 slp
->sl_error
|= FATALIO
;
1234 scsi_low_assert_msg(slp
, ti
, SCSI_LOW_MSG_ABORT
, 1);
1235 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, cr0_cmd
,