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