xref: /NextBSD/sys/dev/ncv/ncr53c500.c (revision 65145fa4c81da358fcbc3b650156dab705dfa34e)
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$");
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 
78 u_int ncv_io_control = NCV_IO_CONTROL_FLAGS;
79 int ncv_data_read_bytes = 4096;
80 int ncv_data_write_bytes = 4096;
81 
82 /***************************************************
83  * DEBUG
84  ***************************************************/
85 #ifdef	NCV_DEBUG
86 static int ncv_debug;
87 #endif	/* NCV_DEBUG */
88 
89 #ifdef	NCV_STATICS
90 static struct ncv_statics {
91 	int disconnect;
92 	int reselect;
93 } ncv_statics;
94 #endif	/* NCV_STATICS */
95 
96 /***************************************************
97  * DEVICE STRUCTURE
98  ***************************************************/
99 extern struct cfdriver ncv_cd;
100 
101 /**************************************************************
102  * DECLARE
103  **************************************************************/
104 /* static */
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 *);
110 
111 static __inline void ncvhw_set_count(struct resource *, int);
112 static __inline u_int ncvhw_get_count(struct resource *);
113 static __inline void ncvhw_select_register_0(struct resource *, struct ncv_hw *);
114 static __inline void ncvhw_select_register_1(struct resource *, struct ncv_hw *);
115 static __inline void ncvhw_fpush(struct resource *, u_int8_t *, int);
116 
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(struct resource *, struct ncv_hw *);
121 static int ncvhw_check(struct resource *, struct ncv_hw *);
122 static void ncvhw_init(struct resource *, 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);
134 
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,
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  **************************************************************/
157 static __inline void
ncvhw_select_register_0(struct resource * res,struct ncv_hw * hw)158 ncvhw_select_register_0(struct resource *res, struct ncv_hw *hw)
159 {
160 
161 	bus_write_1(res, cr0_cfg4, hw->hw_cfg4);
162 }
163 
164 static __inline void
ncvhw_select_register_1(struct resource * res,struct ncv_hw * hw)165 ncvhw_select_register_1(struct resource *res, struct ncv_hw *hw)
166 {
167 
168 	bus_write_1(res, cr1_cfg5, hw->hw_cfg5);
169 }
170 
171 static __inline void
ncvhw_fpush(struct resource * res,u_int8_t * buf,int len)172 ncvhw_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 
180 static __inline void
ncvhw_set_count(struct resource * res,int count)181 ncvhw_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 
189 static __inline u_int
ncvhw_get_count(struct resource * res)190 ncvhw_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 
200 static int
ncvhw_check(struct resource * res,struct ncv_hw * hw)201 ncvhw_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 
252 static void
ncvhw_reset(struct resource * res,struct ncv_hw * hw)253 ncvhw_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 
270 static void
ncvhw_init(struct resource * res,struct ncv_hw * hw)271 ncvhw_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
294 static int
ncvhw_power(sc,flags)295 ncvhw_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  **************************************************************/
333 static void
ncvhw_attention(sc)334 ncvhw_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 
342 static void
ncvhw_bus_reset(sc)343 ncvhw_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 
353 static int
ncvhw_start_selection(sc,cb)354 ncvhw_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 
414 static int
ncv_world_start(sc,fdone)415 ncv_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 
445 static int
ncv_msg(sc,ti,msg)446 ncv_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 
487 static int
ncv_targ_init(sc,ti,action)488 ncv_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  **************************************************************/
511 static int ncv_setup_img(struct ncv_hw *, u_int, int);
512 
513 static int
ncv_setup_img(hw,dvcfg,hostid)514 ncv_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 
556 int
ncvprobesubr(struct resource * res,u_int dvcfg,int hsid)557 ncvprobesubr(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 
570 void
ncvattachsubr(sc)571 ncvattachsubr(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  **************************************************************/
590 static __inline void
ncv_setup_and_start_pio(sc,reqlen)591 ncv_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 
605 static void
ncv_pdma_end(sc,ti)606 ncv_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 		{
643 bad:
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 
660 out:
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 
666 static void
ncv_pio_read(sc,buf,reqlen)667 ncv_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 
726 out:
727 	ncvhw_select_register_0(res, &sc->sc_hw);
728 	sc->sc_tdatalen = reqlen;
729 }
730 
731 static void
ncv_pio_write(sc,buf,reqlen)732 ncv_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 
788 done:
789 	ncvhw_select_register_0(res, &sc->sc_hw);
790 }
791 
792 /**************************************************************
793  * disconnect & reselect (HW low)
794  **************************************************************/
795 static int
ncv_reselected(sc)796 ncv_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 
825 static int
ncv_disconnected(sc,ti)826 ncv_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  **************************************************************/
847 static int
ncv_target_nexus_establish(sc)848 ncv_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 
862 static int
ncv_lun_nexus_establish(sc)863 ncv_lun_nexus_establish(sc)
864 	struct ncv_softc *sc;
865 {
866 
867 	return 0;
868 }
869 
870 static int
ncv_ccb_nexus_establish(sc)871 ncv_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 
881 static int
ncv_catch_intr(sc)882 ncv_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 
900 int
ncvintr(arg)901 ncvintr(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 
913 again:
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