1 /* $NetBSD: siop_common.c,v 1.5 2000/06/28 17:13:04 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Manuel Bouyer. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Manuel Bouyer 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 */ 32 33 /* SYM53c7/8xx PCI-SCSI I/O Processors driver */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/device.h> 38 #include <sys/malloc.h> 39 #include <sys/buf.h> 40 #include <sys/kernel.h> 41 #include <sys/scsiio.h> 42 43 #include <machine/endian.h> 44 #include <machine/bus.h> 45 46 #include <dev/scsipi/scsi_all.h> 47 #include <dev/scsipi/scsi_message.h> 48 #include <dev/scsipi/scsipi_all.h> 49 50 #include <dev/scsipi/scsiconf.h> 51 52 #include <dev/ic/siopreg.h> 53 #include <dev/ic/siopvar.h> 54 #include <dev/ic/siopvar_common.h> 55 56 #undef DEBUG 57 #undef DEBUG_DR 58 59 void 60 siop_common_reset(sc) 61 struct siop_softc *sc; 62 { 63 u_int32_t stest3; 64 65 /* reset the chip */ 66 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_SRST); 67 delay(1000); 68 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, 0); 69 70 /* init registers */ 71 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL0, 72 SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP); 73 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, 0); 74 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3, sc->clock_div); 75 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCXFER, 0); 76 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DIEN, 0xff); 77 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SIEN0, 78 0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL)); 79 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SIEN1, 80 0xff & ~(SIEN1_HTH | SIEN1_GEN)); 81 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2, 0); 82 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3, STEST3_TE); 83 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STIME0, 84 (0xb << STIME0_SEL_SHIFT)); 85 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCID, 86 sc->sc_link.scsipi_scsi.adapter_target | SCID_RRE); 87 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_RESPID0, 88 1 << sc->sc_link.scsipi_scsi.adapter_target); 89 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, 90 (sc->features & SF_CHIP_PF) ? DCNTL_COM | DCNTL_PFEN : DCNTL_COM); 91 92 /* enable clock doubler or quadruler if appropriate */ 93 if (sc->features & (SF_CHIP_DBLR | SF_CHIP_QUAD)) { 94 stest3 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3); 95 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1, 96 STEST1_DBLEN); 97 if (sc->features & SF_CHIP_QUAD) { 98 /* wait for PPL to lock */ 99 while ((bus_space_read_1(sc->sc_rt, sc->sc_rh, 100 SIOP_STEST4) & STEST4_LOCK) == 0) 101 delay(10); 102 } else { 103 /* data sheet says 20us - more won't hurt */ 104 delay(100); 105 } 106 /* halt scsi clock, select doubler/quad, restart clock */ 107 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3, 108 stest3 | STEST3_HSC); 109 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1, 110 STEST1_DBLEN | STEST1_DBLSEL); 111 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3, stest3); 112 } else { 113 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1, 0); 114 } 115 if (sc->features & SF_CHIP_FIFO) 116 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST5, 117 bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST5) | 118 CTEST5_DFS); 119 120 sc->sc_reset(sc); 121 } 122 123 int 124 siop_wdtr_neg(siop_cmd) 125 struct siop_cmd *siop_cmd; 126 { 127 struct siop_softc *sc = siop_cmd->siop_target->siop_sc; 128 struct siop_target *siop_target = siop_cmd->siop_target; 129 int target = siop_cmd->xs->sc_link->scsipi_scsi.target; 130 131 if (siop_target->status == TARST_WIDE_NEG) { 132 /* we initiated wide negotiation */ 133 switch (siop_cmd->siop_table->msg_in[3]) { 134 case MSG_EXT_WDTR_BUS_8_BIT: 135 printf("%s: target %d using 8bit transfers\n", 136 sc->sc_dev.dv_xname, target); 137 siop_target->flags &= ~SF_BUS_WIDE; 138 sc->targets[target]->id &= ~(SCNTL3_EWS << 24); 139 break; 140 case MSG_EXT_WDTR_BUS_16_BIT: 141 if (sc->features & SF_BUS_WIDE) { 142 printf("%s: target %d using 16bit transfers\n", 143 sc->sc_dev.dv_xname, target); 144 siop_target->flags |= TARF_WIDE; 145 sc->targets[target]->id |= (SCNTL3_EWS << 24); 146 break; 147 } 148 /* FALLTHROUH */ 149 default: 150 /* 151 * hum, we got more than what we can handle, shoudn't 152 * happen. Reject, and stay async 153 */ 154 siop_target->flags &= ~TARF_WIDE; 155 siop_target->status = TARST_OK; 156 printf("%s: rejecting invalid wide negotiation from " 157 "target %d (%d)\n", sc->sc_dev.dv_xname, target, 158 siop_cmd->siop_table->msg_in[3]); 159 siop_cmd->siop_table->t_msgout.count= htole32(1); 160 siop_cmd->siop_table->t_msgout.addr = 161 htole32(siop_cmd->dsa); 162 siop_cmd->siop_table->msg_out[0] = MSG_MESSAGE_REJECT; 163 return SIOP_NEG_MSGOUT; 164 } 165 siop_cmd->siop_table->id = 166 htole32(sc->targets[target]->id); 167 bus_space_write_1(sc->sc_rt, sc->sc_rh, 168 SIOP_SCNTL3, 169 (sc->targets[target]->id >> 24) & 0xff); 170 /* we now need to do sync */ 171 siop_target->status = TARST_SYNC_NEG; 172 siop_cmd->siop_table->msg_out[0] = MSG_EXTENDED; 173 siop_cmd->siop_table->msg_out[1] = MSG_EXT_SDTR_LEN; 174 siop_cmd->siop_table->msg_out[2] = MSG_EXT_SDTR; 175 siop_cmd->siop_table->msg_out[3] = sc->minsync; 176 siop_cmd->siop_table->msg_out[4] = sc->maxoff; 177 siop_cmd->siop_table->t_msgout.count = 178 htole32(MSG_EXT_SDTR_LEN + 2); 179 siop_cmd->siop_table->t_msgout.addr = htole32(siop_cmd->dsa); 180 return SIOP_NEG_MSGOUT; 181 } else { 182 /* target initiated wide negotiation */ 183 if (siop_cmd->siop_table->msg_in[3] >= MSG_EXT_WDTR_BUS_16_BIT 184 && (sc->features & SF_BUS_WIDE)) { 185 printf("%s: target %d using 16bit transfers\n", 186 sc->sc_dev.dv_xname, target); 187 siop_target->flags |= TARF_WIDE; 188 sc->targets[target]->id |= SCNTL3_EWS << 24; 189 siop_cmd->siop_table->msg_out[3] = 190 MSG_EXT_WDTR_BUS_16_BIT; 191 } else { 192 printf("%s: target %d using 8bit transfers\n", 193 sc->sc_dev.dv_xname, target); 194 siop_target->flags &= ~SF_BUS_WIDE; 195 sc->targets[target]->id &= ~(SCNTL3_EWS << 24); 196 siop_cmd->siop_table->msg_out[3] = 197 MSG_EXT_WDTR_BUS_8_BIT; 198 } 199 siop_cmd->siop_table->id = 200 htole32(sc->targets[target]->id); 201 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3, 202 (sc->targets[target]->id >> 24) & 0xff); 203 /* 204 * we did reset wide parameters, so fall back to async, 205 * but don't shedule a sync neg, target should initiate it 206 */ 207 siop_target->status = TARST_OK; 208 siop_cmd->siop_table->msg_out[0] = MSG_EXTENDED; 209 siop_cmd->siop_table->msg_out[1] = MSG_EXT_WDTR_LEN; 210 siop_cmd->siop_table->msg_out[2] = MSG_EXT_WDTR; 211 siop_cmd->siop_table->t_msgout.count= 212 htole32(MSG_EXT_WDTR_LEN + 2); 213 siop_cmd->siop_table->t_msgout.addr = htole32(siop_cmd->dsa); 214 return SIOP_NEG_MSGOUT; 215 } 216 } 217 218 int 219 siop_sdtr_neg(siop_cmd) 220 struct siop_cmd *siop_cmd; 221 { 222 struct siop_softc *sc = siop_cmd->siop_target->siop_sc; 223 struct siop_target *siop_target = siop_cmd->siop_target; 224 int target = siop_cmd->xs->sc_link->scsipi_scsi.target; 225 int sync, offset, i; 226 int send_msgout = 0; 227 228 sync = siop_cmd->siop_table->msg_in[3]; 229 offset = siop_cmd->siop_table->msg_in[4]; 230 231 if (siop_target->status == TARST_SYNC_NEG) { 232 /* we initiated sync negotiation */ 233 siop_target->status = TARST_OK; 234 #ifdef DEBUG 235 printf("sdtr: sync %d offset %d\n", sync, offset); 236 #endif 237 if (offset > sc->maxoff || sync < sc->minsync || 238 sync > sc->maxsync) 239 goto reject; 240 for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); 241 i++) { 242 if (sc->clock_period != scf_period[i].clock) 243 continue; 244 if (scf_period[i].period == sync) { 245 /* ok, found it. we now are sync. */ 246 printf("%s: target %d now synchronous at " 247 "%sMhz, offset %d\n", sc->sc_dev.dv_xname, 248 target, scf_period[i].rate, offset); 249 sc->targets[target]->id &= 250 ~(SCNTL3_SCF_MASK << 24); 251 sc->targets[target]->id |= scf_period[i].scf 252 << (24 + SCNTL3_SCF_SHIFT); 253 if (sync < 25) /* Ultra */ 254 sc->targets[target]->id |= 255 SCNTL3_ULTRA << 24; 256 else 257 sc->targets[target]->id &= 258 ~(SCNTL3_ULTRA << 24); 259 sc->targets[target]->id &= 260 ~(SCXFER_MO_MASK << 8); 261 sc->targets[target]->id |= 262 (offset & SCXFER_MO_MASK) << 8; 263 goto end; 264 } 265 } 266 /* 267 * we didn't find it in our table, do async and send reject 268 * msg 269 */ 270 reject: 271 send_msgout = 1; 272 siop_cmd->siop_table->t_msgout.count= htole32(1); 273 siop_cmd->siop_table->msg_out[0] = MSG_MESSAGE_REJECT; 274 printf("%s: target %d asynchronous\n", sc->sc_dev.dv_xname, 275 target); 276 sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24); 277 sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24); 278 sc->targets[target]->id &= ~(SCXFER_MO_MASK << 8); 279 } else { /* target initiated sync neg */ 280 #ifdef DEBUG 281 printf("sdtr (target): sync %d offset %d\n", sync, offset); 282 #endif 283 if (offset == 0 || sync > sc->maxsync) { /* async */ 284 goto async; 285 } 286 if (offset > sc->maxoff) 287 offset = sc->maxoff; 288 if (sync < sc->minsync) 289 sync = sc->minsync; 290 /* look for sync period */ 291 for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); 292 i++) { 293 if (sc->clock_period != scf_period[i].clock) 294 continue; 295 if (scf_period[i].period == sync) { 296 /* ok, found it. we now are sync. */ 297 printf("%s: target %d now synchronous at " 298 "%sMhz, offset %d\n", sc->sc_dev.dv_xname, 299 target, scf_period[i].rate, offset); 300 sc->targets[target]->id &= 301 ~(SCNTL3_SCF_MASK << 24); 302 sc->targets[target]->id |= scf_period[i].scf 303 << (24 + SCNTL3_SCF_SHIFT); 304 if (sync < 25) /* Ultra */ 305 sc->targets[target]->id |= 306 SCNTL3_ULTRA << 24; 307 else 308 sc->targets[target]->id &= 309 ~(SCNTL3_ULTRA << 24); 310 sc->targets[target]->id &= 311 ~(SCXFER_MO_MASK << 8); 312 sc->targets[target]->id |= 313 (offset & SCXFER_MO_MASK) << 8; 314 siop_cmd->siop_table->msg_out[0] = MSG_EXTENDED; 315 siop_cmd->siop_table->msg_out[1] = 316 MSG_EXT_SDTR_LEN; 317 siop_cmd->siop_table->msg_out[2] = MSG_EXT_SDTR; 318 siop_cmd->siop_table->msg_out[3] = sync; 319 siop_cmd->siop_table->msg_out[4] = offset; 320 siop_cmd->siop_table->t_msgout.count= 321 htole32(MSG_EXT_SDTR_LEN + 2); 322 send_msgout = 1; 323 goto end; 324 } 325 } 326 async: 327 printf("%s: target %d asynchronous\n", 328 sc->sc_dev.dv_xname, target); 329 sc->targets[target]->id &= ~(SCNTL3_SCF_MASK << 24); 330 sc->targets[target]->id &= ~(SCNTL3_ULTRA << 24); 331 sc->targets[target]->id &= ~(SCXFER_MO_MASK << 8); 332 siop_cmd->siop_table->msg_out[0] = MSG_EXTENDED; 333 siop_cmd->siop_table->msg_out[1] = MSG_EXT_SDTR_LEN; 334 siop_cmd->siop_table->msg_out[2] = MSG_EXT_SDTR; 335 siop_cmd->siop_table->msg_out[3] = 0; 336 siop_cmd->siop_table->msg_out[4] = 0; 337 siop_cmd->siop_table->t_msgout.count= 338 htole32(MSG_EXT_SDTR_LEN + 2); 339 send_msgout = 1; 340 } 341 end: 342 #ifdef DEBUG 343 printf("id now 0x%x\n", sc->targets[target]->id); 344 #endif 345 siop_cmd->siop_table->id = htole32(sc->targets[target]->id); 346 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3, 347 (sc->targets[target]->id >> 24) & 0xff); 348 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCXFER, 349 (sc->targets[target]->id >> 8) & 0xff); 350 if (send_msgout) { 351 siop_cmd->siop_table->t_msgout.addr = htole32(siop_cmd->dsa); 352 return SIOP_NEG_MSGOUT; 353 } else { 354 return SIOP_NEG_ACK; 355 } 356 } 357 358 void 359 siop_minphys(bp) 360 struct buf *bp; 361 { 362 minphys(bp); 363 } 364 365 int 366 siop_ioctl(link, cmd, arg, flag, p) 367 struct scsipi_link *link; 368 u_long cmd; 369 caddr_t arg; 370 int flag; 371 struct proc *p; 372 { 373 struct siop_softc *sc = link->adapter_softc; 374 u_int8_t scntl1; 375 int s; 376 377 switch (cmd) { 378 case SCBUSIORESET: 379 s = splbio(); 380 scntl1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1); 381 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, 382 scntl1 | SCNTL1_RST); 383 /* minimum 25 us, more time won't hurt */ 384 delay(100); 385 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, scntl1); 386 splx(s); 387 return (0); 388 default: 389 return (ENOTTY); 390 } 391 } 392 393 void 394 siop_sdp(siop_cmd) 395 struct siop_cmd *siop_cmd; 396 { 397 /* save data pointer. Handle async only for now */ 398 int offset, dbc, sstat; 399 struct siop_softc *sc = siop_cmd->siop_target->siop_sc; 400 scr_table_t *table; /* table to patch */ 401 402 if ((siop_cmd->xs->xs_control & (XS_CTL_DATA_OUT | XS_CTL_DATA_IN)) 403 == 0) 404 return; /* no data pointers to save */ 405 offset = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SCRATCHA + 1); 406 if (offset >= SIOP_NSG) { 407 printf("%s: bad offset in siop_sdp (%d)\n", 408 sc->sc_dev.dv_xname, offset); 409 return; 410 } 411 table = &siop_cmd->siop_table->data[offset]; 412 #ifdef DEBUG_DR 413 printf("sdp: offset %d count=%d addr=0x%x ", offset, 414 table->count, table->addr); 415 #endif 416 dbc = bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DBC) & 0x00ffffff; 417 if (siop_cmd->xs->xs_control & XS_CTL_DATA_OUT) { 418 /* need to account stale data in FIFO */ 419 int dfifo = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DFIFO); 420 if (sc->features & SF_CHIP_FIFO) { 421 dfifo |= (bus_space_read_1(sc->sc_rt, sc->sc_rh, 422 SIOP_CTEST5) & CTEST5_BOMASK) << 8; 423 dbc += (dfifo - (dbc & 0x3ff)) & 0x3ff; 424 } else { 425 dbc += (dfifo - (dbc & 0x7f)) & 0x7f; 426 } 427 sstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT0); 428 if (sstat & SSTAT0_OLF) 429 dbc++; 430 if (sstat & SSTAT0_ORF) 431 dbc++; 432 if (siop_cmd->siop_target->flags & TARF_WIDE) { 433 sstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, 434 SIOP_SSTAT2); 435 if (sstat & SSTAT2_OLF1) 436 dbc++; 437 if (sstat & SSTAT2_ORF1) 438 dbc++; 439 } 440 /* clear the FIFO */ 441 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3, 442 bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) | 443 CTEST3_CLF); 444 } 445 table->addr = 446 htole32(le32toh(table->addr) + le32toh(table->count) - dbc); 447 table->count = htole32(dbc); 448 #ifdef DEBUG_DR 449 printf("now count=%d addr=0x%x\n", table->count, table->addr); 450 #endif 451 } 452 453 void 454 siop_clearfifo(sc) 455 struct siop_softc *sc; 456 { 457 int timeout = 0; 458 int ctest3 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3); 459 460 #ifdef DEBUG_INTR 461 printf("DMA fifo not empty !\n"); 462 #endif 463 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3, 464 ctest3 | CTEST3_CLF); 465 while ((bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) & 466 CTEST3_CLF) != 0) { 467 delay(1); 468 if (++timeout > 1000) { 469 printf("clear fifo failed\n"); 470 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3, 471 bus_space_read_1(sc->sc_rt, sc->sc_rh, 472 SIOP_CTEST3) & ~CTEST3_CLF); 473 return; 474 } 475 } 476 } 477 478 int 479 siop_modechange(sc) 480 struct siop_softc *sc; 481 { 482 int retry; 483 int sist0, sist1, stest2, stest4; 484 for (retry = 0; retry < 5; retry++) { 485 /* 486 * datasheet says to wait 100ms and re-read SIST1, 487 * to check that DIFFSENSE is srable. 488 * We may delay() 5 times for 100ms at interrupt time; 489 * hopefully this will not happen often. 490 */ 491 delay(100000); 492 sist0 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST0); 493 sist1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST1); 494 if (sist1 & SIEN1_SBMC) 495 continue; /* we got an irq again */ 496 stest4 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST4) & 497 STEST4_MODE_MASK; 498 stest2 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2); 499 switch(stest4) { 500 case STEST4_MODE_DIF: 501 printf("%s: switching to differential mode\n", 502 sc->sc_dev.dv_xname); 503 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2, 504 stest2 | STEST2_DIF); 505 break; 506 case STEST4_MODE_SE: 507 printf("%s: switching to single-ended mode\n", 508 sc->sc_dev.dv_xname); 509 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2, 510 stest2 & ~STEST2_DIF); 511 break; 512 case STEST4_MODE_LVD: 513 printf("%s: switching to LVD mode\n", 514 sc->sc_dev.dv_xname); 515 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2, 516 stest2 & ~STEST2_DIF); 517 break; 518 default: 519 printf("%s: invalid SCSI mode 0x%x\n", 520 sc->sc_dev.dv_xname, stest4); 521 return 0; 522 } 523 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST0, 524 stest4 >> 2); 525 return 1; 526 } 527 printf("%s: timeout waiting for DIFFSENSE to stabilise\n", 528 sc->sc_dev.dv_xname); 529 return 0; 530 } 531