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