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