1 1.13 tsutsui /* $NetBSD: scsi.c,v 1.13 2024/05/09 15:11:11 tsutsui Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /* 4 1.1 thorpej * This is reported to fix some odd failures when disklabeling 5 1.1 thorpej * SCSI disks in SYS_INST. 6 1.1 thorpej */ 7 1.1 thorpej #define SLOWSCSI 8 1.1 thorpej 9 1.1 thorpej /* 10 1.10 rmind * Copyright (c) 1988 University of Utah. 11 1.1 thorpej * Copyright (c) 1990, 1993 12 1.1 thorpej * The Regents of the University of California. All rights reserved. 13 1.4 agc * 14 1.4 agc * This code is derived from software contributed to Berkeley by 15 1.4 agc * Van Jacobson of Lawrence Berkeley Laboratory and the Systems 16 1.4 agc * Programming Group of the University of Utah Computer Science Department. 17 1.4 agc * 18 1.4 agc * Redistribution and use in source and binary forms, with or without 19 1.4 agc * modification, are permitted provided that the following conditions 20 1.4 agc * are met: 21 1.4 agc * 1. Redistributions of source code must retain the above copyright 22 1.4 agc * notice, this list of conditions and the following disclaimer. 23 1.4 agc * 2. Redistributions in binary form must reproduce the above copyright 24 1.4 agc * notice, this list of conditions and the following disclaimer in the 25 1.4 agc * documentation and/or other materials provided with the distribution. 26 1.4 agc * 3. Neither the name of the University nor the names of its contributors 27 1.4 agc * may be used to endorse or promote products derived from this software 28 1.4 agc * without specific prior written permission. 29 1.4 agc * 30 1.4 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 31 1.4 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 1.4 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 1.4 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 34 1.4 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 1.4 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 1.4 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 1.4 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38 1.4 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39 1.4 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40 1.4 agc * SUCH DAMAGE. 41 1.4 agc * 42 1.4 agc * from: Utah $Hdr: scsi.c 1.3 90/01/27$ 43 1.4 agc * 44 1.4 agc * @(#)scsi.c 8.1 (Berkeley) 6/10/93 45 1.4 agc */ 46 1.1 thorpej 47 1.1 thorpej /* 48 1.1 thorpej * SCSI bus driver for standalone programs. 49 1.1 thorpej */ 50 1.1 thorpej 51 1.1 thorpej #include <sys/param.h> 52 1.1 thorpej #include <sys/reboot.h> 53 1.1 thorpej 54 1.1 thorpej #include <lib/libsa/stand.h> 55 1.1 thorpej 56 1.1 thorpej #define _IOCTL_ 57 1.1 thorpej 58 1.1 thorpej #include <hp300/stand/common/device.h> 59 1.3 tsutsui #include <hp300/stand/common/scsireg.h> 60 1.1 thorpej #include <hp300/stand/common/scsivar.h> 61 1.1 thorpej #include <hp300/stand/common/samachdep.h> 62 1.1 thorpej 63 1.5 tsutsui static void scsireset(int); 64 1.8 tsutsui static int issue_select(volatile struct scsidevice *, uint8_t, uint8_t); 65 1.5 tsutsui static int wait_for_select(volatile struct scsidevice *hd); 66 1.8 tsutsui static int ixfer_start(volatile struct scsidevice *, int, uint8_t, int); 67 1.8 tsutsui static int ixfer_out(volatile struct scsidevice *, int, uint8_t *); 68 1.8 tsutsui static int ixfer_in(volatile struct scsidevice *hd, int, uint8_t *); 69 1.8 tsutsui static int scsiicmd(struct scsi_softc *, int, uint8_t *, int, uint8_t *, int, 70 1.8 tsutsui uint8_t); 71 1.5 tsutsui 72 1.1 thorpej struct scsi_softc scsi_softc[NSCSI]; 73 1.1 thorpej 74 1.5 tsutsui 75 1.1 thorpej int scsi_cmd_wait = 50000; /* use the "real" driver init_wait value */ 76 1.1 thorpej int scsi_data_wait = 50000; /* use the "real" driver init_wait value */ 77 1.1 thorpej 78 1.5 tsutsui void 79 1.6 tsutsui scsiinit(void) 80 1.1 thorpej { 81 1.5 tsutsui struct hp_hw *hw; 82 1.5 tsutsui struct scsi_softc *hs; 83 1.5 tsutsui int i; 84 1.1 thorpej static int waitset = 0; 85 1.12 tsutsui 86 1.1 thorpej i = 0; 87 1.1 thorpej for (hw = sc_table; i < NSCSI && hw < &sc_table[MAXCTLRS]; hw++) { 88 1.1 thorpej if (!HW_ISSCSI(hw)) 89 1.1 thorpej continue; 90 1.1 thorpej hs = &scsi_softc[i]; 91 1.1 thorpej hs->sc_addr = hw->hw_kva; 92 1.1 thorpej scsireset(i); 93 1.1 thorpej if (howto & RB_ASKNAME) 94 1.1 thorpej printf("scsi%d at sc%d\n", i, hw->hw_sc); 95 1.9 christos hw->hw_pa = (void *) i; /* XXX for autoconfig */ 96 1.1 thorpej hs->sc_alive = 1; 97 1.1 thorpej i++; 98 1.1 thorpej } 99 1.1 thorpej /* 100 1.1 thorpej * Adjust the wait values 101 1.1 thorpej */ 102 1.1 thorpej if (!waitset) { 103 1.1 thorpej scsi_cmd_wait *= cpuspeed; 104 1.1 thorpej scsi_data_wait *= cpuspeed; 105 1.1 thorpej waitset = 1; 106 1.1 thorpej } 107 1.1 thorpej } 108 1.1 thorpej 109 1.5 tsutsui int 110 1.6 tsutsui scsialive(int unit) 111 1.1 thorpej { 112 1.6 tsutsui 113 1.1 thorpej if (unit >= NSCSI || scsi_softc[unit].sc_alive == 0) 114 1.5 tsutsui return 0; 115 1.5 tsutsui return 1; 116 1.1 thorpej } 117 1.1 thorpej 118 1.5 tsutsui static void 119 1.6 tsutsui scsireset(int unit) 120 1.1 thorpej { 121 1.5 tsutsui volatile struct scsidevice *hd; 122 1.5 tsutsui struct scsi_softc *hs; 123 1.1 thorpej u_int i; 124 1.1 thorpej 125 1.1 thorpej hs = &scsi_softc[unit]; 126 1.5 tsutsui hd = (void *)hs->sc_addr; 127 1.1 thorpej hd->scsi_id = 0xFF; 128 1.1 thorpej DELAY(100); 129 1.1 thorpej /* 130 1.1 thorpej * Disable interrupts then reset the FUJI chip. 131 1.1 thorpej */ 132 1.1 thorpej hd->scsi_csr = 0; 133 1.1 thorpej hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; 134 1.1 thorpej hd->scsi_scmd = 0; 135 1.1 thorpej hd->scsi_tmod = 0; 136 1.1 thorpej hd->scsi_pctl = 0; 137 1.1 thorpej hd->scsi_temp = 0; 138 1.1 thorpej hd->scsi_tch = 0; 139 1.1 thorpej hd->scsi_tcm = 0; 140 1.1 thorpej hd->scsi_tcl = 0; 141 1.1 thorpej hd->scsi_ints = 0; 142 1.1 thorpej 143 1.1 thorpej /* 144 1.1 thorpej * Configure the FUJI chip with its SCSI address, all 145 1.1 thorpej * interrupts enabled & appropriate parity. 146 1.1 thorpej */ 147 1.1 thorpej i = (~hd->scsi_hconf) & 0x7; 148 1.1 thorpej hs->sc_scsi_addr = 1 << i; 149 1.1 thorpej hd->scsi_bdid = i; 150 1.1 thorpej if (hd->scsi_hconf & HCONF_PARITY) 151 1.1 thorpej hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 152 1.1 thorpej SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 153 1.1 thorpej SCTL_INTR_ENAB | SCTL_PARITY_ENAB; 154 1.1 thorpej else 155 1.1 thorpej hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 156 1.1 thorpej SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 157 1.1 thorpej SCTL_INTR_ENAB; 158 1.1 thorpej hd->scsi_sctl &=~ SCTL_DISABLE; 159 1.1 thorpej } 160 1.1 thorpej 161 1.1 thorpej 162 1.5 tsutsui void 163 1.6 tsutsui scsiabort(struct scsi_softc *hs, volatile struct scsidevice *hd) 164 1.1 thorpej { 165 1.6 tsutsui 166 1.1 thorpej printf("scsi%d error: scsiabort\n", hs - scsi_softc); 167 1.1 thorpej 168 1.1 thorpej scsireset(hs - scsi_softc); 169 1.1 thorpej DELAY(1000000); 170 1.1 thorpej } 171 1.1 thorpej 172 1.1 thorpej static int 173 1.8 tsutsui issue_select(volatile struct scsidevice *hd, uint8_t target, uint8_t our_addr) 174 1.1 thorpej { 175 1.6 tsutsui 176 1.1 thorpej if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) 177 1.5 tsutsui return 1; 178 1.1 thorpej 179 1.1 thorpej if (hd->scsi_ints & INTS_DISCON) 180 1.1 thorpej hd->scsi_ints = INTS_DISCON; 181 1.1 thorpej 182 1.1 thorpej hd->scsi_pctl = 0; 183 1.1 thorpej hd->scsi_temp = (1 << target) | our_addr; 184 1.11 tsutsui /* select timeout is hardcoded to 250ms */ 185 1.11 tsutsui hd->scsi_tch = 2; 186 1.11 tsutsui hd->scsi_tcm = 113; 187 1.11 tsutsui hd->scsi_tcl = 3; 188 1.1 thorpej 189 1.1 thorpej hd->scsi_scmd = SCMD_SELECT; 190 1.5 tsutsui return 0; 191 1.1 thorpej } 192 1.1 thorpej 193 1.1 thorpej static int 194 1.6 tsutsui wait_for_select(volatile struct scsidevice *hd) 195 1.1 thorpej { 196 1.5 tsutsui int wait; 197 1.8 tsutsui uint8_t ints; 198 1.1 thorpej 199 1.1 thorpej wait = scsi_data_wait; 200 1.1 thorpej while ((ints = hd->scsi_ints) == 0) { 201 1.1 thorpej if (--wait < 0) 202 1.5 tsutsui return 1; 203 1.1 thorpej DELAY(1); 204 1.1 thorpej } 205 1.1 thorpej hd->scsi_ints = ints; 206 1.5 tsutsui return !(hd->scsi_ssts & SSTS_INITIATOR); 207 1.1 thorpej } 208 1.1 thorpej 209 1.1 thorpej static int 210 1.8 tsutsui ixfer_start(volatile struct scsidevice *hd, int len, uint8_t phase, int wait) 211 1.1 thorpej { 212 1.1 thorpej 213 1.1 thorpej hd->scsi_tch = len >> 16; 214 1.1 thorpej hd->scsi_tcm = len >> 8; 215 1.1 thorpej hd->scsi_tcl = len; 216 1.1 thorpej hd->scsi_pctl = phase; 217 1.1 thorpej hd->scsi_tmod = 0; /*XXX*/ 218 1.1 thorpej hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 219 1.1 thorpej 220 1.1 thorpej /* wait for xfer to start or svc_req interrupt */ 221 1.1 thorpej while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 222 1.1 thorpej if (hd->scsi_ints || --wait < 0) 223 1.5 tsutsui return 0; 224 1.1 thorpej DELAY(1); 225 1.1 thorpej } 226 1.5 tsutsui return 1; 227 1.1 thorpej } 228 1.1 thorpej 229 1.1 thorpej static int 230 1.8 tsutsui ixfer_out(volatile struct scsidevice *hd, int len, uint8_t *buf) 231 1.1 thorpej { 232 1.5 tsutsui int wait = scsi_data_wait; 233 1.1 thorpej 234 1.1 thorpej for (; len > 0; --len) { 235 1.1 thorpej while (hd->scsi_ssts & SSTS_DREG_FULL) { 236 1.1 thorpej if (hd->scsi_ints || --wait < 0) 237 1.5 tsutsui return len; 238 1.1 thorpej DELAY(1); 239 1.1 thorpej } 240 1.1 thorpej hd->scsi_dreg = *buf++; 241 1.1 thorpej } 242 1.5 tsutsui return 0; 243 1.1 thorpej } 244 1.1 thorpej 245 1.1 thorpej static int 246 1.8 tsutsui ixfer_in(volatile struct scsidevice *hd, int len, uint8_t *buf) 247 1.1 thorpej { 248 1.5 tsutsui int wait = scsi_data_wait; 249 1.1 thorpej 250 1.1 thorpej for (; len > 0; --len) { 251 1.1 thorpej while (hd->scsi_ssts & SSTS_DREG_EMPTY) { 252 1.1 thorpej if (hd->scsi_ints || --wait < 0) { 253 1.1 thorpej while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) { 254 1.1 thorpej *buf++ = hd->scsi_dreg; 255 1.1 thorpej --len; 256 1.1 thorpej } 257 1.5 tsutsui return len; 258 1.1 thorpej } 259 1.1 thorpej DELAY(1); 260 1.1 thorpej } 261 1.1 thorpej *buf++ = hd->scsi_dreg; 262 1.1 thorpej } 263 1.5 tsutsui return len; 264 1.1 thorpej } 265 1.1 thorpej 266 1.1 thorpej static int 267 1.8 tsutsui scsiicmd(struct scsi_softc *hs, int target, uint8_t *cbuf, int clen, 268 1.8 tsutsui uint8_t *buf, int len, uint8_t xferphase) 269 1.1 thorpej { 270 1.5 tsutsui volatile struct scsidevice *hd = (void *)hs->sc_addr; 271 1.8 tsutsui uint8_t phase, ints; 272 1.5 tsutsui int wait; 273 1.1 thorpej 274 1.1 thorpej /* select the SCSI bus (it's an error if bus isn't free) */ 275 1.1 thorpej if (issue_select(hd, target, hs->sc_scsi_addr)) 276 1.5 tsutsui return -2; 277 1.1 thorpej if (wait_for_select(hd)) 278 1.5 tsutsui return -2; 279 1.1 thorpej /* 280 1.1 thorpej * Wait for a phase change (or error) then let the device 281 1.1 thorpej * sequence us through the various SCSI phases. 282 1.1 thorpej */ 283 1.1 thorpej hs->sc_stat = -1; 284 1.1 thorpej phase = CMD_PHASE; 285 1.1 thorpej while (1) { 286 1.1 thorpej wait = scsi_cmd_wait; 287 1.1 thorpej switch (phase) { 288 1.1 thorpej 289 1.1 thorpej case CMD_PHASE: 290 1.1 thorpej if (ixfer_start(hd, clen, phase, wait)) 291 1.1 thorpej if (ixfer_out(hd, clen, cbuf)) 292 1.1 thorpej goto abort; 293 1.1 thorpej phase = xferphase; 294 1.1 thorpej break; 295 1.1 thorpej 296 1.1 thorpej case DATA_IN_PHASE: 297 1.1 thorpej if (len <= 0) 298 1.1 thorpej goto abort; 299 1.1 thorpej wait = scsi_data_wait; 300 1.1 thorpej if (ixfer_start(hd, len, phase, wait) || 301 1.1 thorpej !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 302 1.1 thorpej ixfer_in(hd, len, buf); 303 1.1 thorpej phase = STATUS_PHASE; 304 1.1 thorpej break; 305 1.1 thorpej 306 1.1 thorpej case DATA_OUT_PHASE: 307 1.1 thorpej if (len <= 0) 308 1.1 thorpej goto abort; 309 1.1 thorpej wait = scsi_data_wait; 310 1.1 thorpej if (ixfer_start(hd, len, phase, wait)) 311 1.1 thorpej if (ixfer_out(hd, len, buf)) 312 1.1 thorpej goto abort; 313 1.1 thorpej phase = STATUS_PHASE; 314 1.1 thorpej break; 315 1.1 thorpej 316 1.1 thorpej case STATUS_PHASE: 317 1.1 thorpej wait = scsi_data_wait; 318 1.1 thorpej if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) || 319 1.1 thorpej !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 320 1.8 tsutsui ixfer_in(hd, sizeof(hs->sc_stat), 321 1.8 tsutsui (uint8_t *)&hs->sc_stat); 322 1.1 thorpej phase = MESG_IN_PHASE; 323 1.1 thorpej break; 324 1.1 thorpej 325 1.1 thorpej case MESG_IN_PHASE: 326 1.1 thorpej if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) || 327 1.1 thorpej !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { 328 1.5 tsutsui ixfer_in(hd, sizeof(hs->sc_msg), 329 1.8 tsutsui (uint8_t *)&hs->sc_msg); 330 1.1 thorpej hd->scsi_scmd = SCMD_RST_ACK; 331 1.1 thorpej } 332 1.1 thorpej phase = BUS_FREE_PHASE; 333 1.1 thorpej break; 334 1.1 thorpej 335 1.1 thorpej case BUS_FREE_PHASE: 336 1.1 thorpej goto out; 337 1.1 thorpej 338 1.1 thorpej default: 339 1.1 thorpej printf("scsi%d: unexpected scsi phase %d\n", 340 1.1 thorpej hs - scsi_softc, phase); 341 1.1 thorpej goto abort; 342 1.1 thorpej } 343 1.1 thorpej #ifdef SLOWSCSI 344 1.1 thorpej /* 345 1.2 wiz * XXX we have weird transient problems with booting from 346 1.1 thorpej * slow scsi disks on fast machines. I have never been 347 1.1 thorpej * able to pin the problem down, but a large delay here 348 1.1 thorpej * seems to always work. 349 1.1 thorpej */ 350 1.1 thorpej DELAY(1000); 351 1.1 thorpej #endif 352 1.1 thorpej /* wait for last command to complete */ 353 1.1 thorpej while ((ints = hd->scsi_ints) == 0) { 354 1.1 thorpej if (--wait < 0) 355 1.1 thorpej goto abort; 356 1.1 thorpej DELAY(1); 357 1.1 thorpej } 358 1.1 thorpej hd->scsi_ints = ints; 359 1.1 thorpej if (ints & INTS_SRV_REQ) 360 1.1 thorpej phase = hd->scsi_psns & PHASE; 361 1.1 thorpej else if (ints & INTS_DISCON) 362 1.1 thorpej goto out; 363 1.1 thorpej else if ((ints & INTS_CMD_DONE) == 0) 364 1.1 thorpej goto abort; 365 1.1 thorpej } 366 1.1 thorpej abort: 367 1.1 thorpej scsiabort(hs, hd); 368 1.1 thorpej out: 369 1.5 tsutsui return hs->sc_stat; 370 1.1 thorpej } 371 1.1 thorpej 372 1.1 thorpej int 373 1.6 tsutsui scsi_test_unit_rdy(int ctlr, int slave) 374 1.1 thorpej { 375 1.5 tsutsui struct scsi_softc *hs = &scsi_softc[ctlr]; 376 1.1 thorpej static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY }; 377 1.1 thorpej 378 1.8 tsutsui return scsiicmd(hs, slave, (uint8_t *)&cdb, sizeof(cdb), NULL, 0, 379 1.5 tsutsui STATUS_PHASE); 380 1.1 thorpej } 381 1.1 thorpej 382 1.1 thorpej int 383 1.8 tsutsui scsi_request_sense(int ctlr, int slave, uint8_t *buf, unsigned int len) 384 1.1 thorpej { 385 1.5 tsutsui struct scsi_softc *hs = &scsi_softc[ctlr]; 386 1.1 thorpej static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE }; 387 1.1 thorpej 388 1.1 thorpej cdb.len = len; 389 1.8 tsutsui return scsiicmd(hs, slave, (uint8_t *)&cdb, sizeof(cdb), buf, len, 390 1.5 tsutsui DATA_IN_PHASE); 391 1.1 thorpej } 392 1.1 thorpej 393 1.1 thorpej int 394 1.8 tsutsui scsi_read_capacity(int ctlr, int slave, uint8_t *buf, unsigned int len) 395 1.1 thorpej { 396 1.5 tsutsui struct scsi_softc *hs = &scsi_softc[ctlr]; 397 1.1 thorpej static struct scsi_cdb10 cdb = { CMD_READ_CAPACITY }; 398 1.1 thorpej 399 1.8 tsutsui return scsiicmd(hs, slave, (uint8_t *)&cdb, sizeof(cdb), buf, len, 400 1.5 tsutsui DATA_IN_PHASE); 401 1.1 thorpej } 402 1.1 thorpej 403 1.13 tsutsui #ifdef SUPPORT_CD 404 1.13 tsutsui int 405 1.13 tsutsui scsi_inquiry(int ctlr, int slave, uint8_t *buf, unsigned int len) 406 1.13 tsutsui { 407 1.13 tsutsui struct scsi_softc *hs = &scsi_softc[ctlr]; 408 1.13 tsutsui static struct scsi_cdb6 cdb = { CMD_INQUIRY }; 409 1.13 tsutsui 410 1.13 tsutsui cdb.len = len; 411 1.13 tsutsui return scsiicmd(hs, slave, (uint8_t *)&cdb, sizeof(cdb), buf, len, 412 1.13 tsutsui DATA_IN_PHASE); 413 1.13 tsutsui } 414 1.13 tsutsui #endif 415 1.13 tsutsui 416 1.1 thorpej int 417 1.8 tsutsui scsi_tt_read(int ctlr, int slave, uint8_t *buf, u_int len, daddr_t blk, 418 1.6 tsutsui u_int nblk) 419 1.1 thorpej { 420 1.5 tsutsui struct scsi_softc *hs = &scsi_softc[ctlr]; 421 1.1 thorpej struct scsi_cdb10 cdb; 422 1.1 thorpej 423 1.5 tsutsui memset(&cdb, 0, sizeof(cdb)); 424 1.1 thorpej cdb.cmd = CMD_READ_EXT; 425 1.1 thorpej cdb.lbah = blk >> 24; 426 1.1 thorpej cdb.lbahm = blk >> 16; 427 1.1 thorpej cdb.lbalm = blk >> 8; 428 1.1 thorpej cdb.lbal = blk; 429 1.1 thorpej cdb.lenh = nblk >> (8 + DEV_BSHIFT); 430 1.1 thorpej cdb.lenl = nblk >> DEV_BSHIFT; 431 1.8 tsutsui return scsiicmd(hs, slave, (uint8_t *)&cdb, sizeof(cdb), buf, len, 432 1.5 tsutsui DATA_IN_PHASE); 433 1.1 thorpej } 434 1.1 thorpej 435 1.1 thorpej int 436 1.8 tsutsui scsi_tt_write(int ctlr, int slave, uint8_t *buf, u_int len, daddr_t blk, 437 1.6 tsutsui u_int nblk) 438 1.1 thorpej { 439 1.5 tsutsui struct scsi_softc *hs = &scsi_softc[ctlr]; 440 1.1 thorpej struct scsi_cdb10 cdb; 441 1.1 thorpej 442 1.5 tsutsui memset(&cdb, 0, sizeof(cdb)); 443 1.1 thorpej cdb.cmd = CMD_WRITE_EXT; 444 1.1 thorpej cdb.lbah = blk >> 24; 445 1.1 thorpej cdb.lbahm = blk >> 16; 446 1.1 thorpej cdb.lbalm = blk >> 8; 447 1.1 thorpej cdb.lbal = blk; 448 1.1 thorpej cdb.lenh = nblk >> (8 + DEV_BSHIFT); 449 1.1 thorpej cdb.lenl = nblk >> DEV_BSHIFT; 450 1.8 tsutsui return scsiicmd(hs, slave, (uint8_t *)&cdb, sizeof(cdb), buf, len, 451 1.5 tsutsui DATA_OUT_PHASE); 452 1.1 thorpej } 453