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