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