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