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