1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Van Jacobson of Lawrence Berkeley Laboratory and the Systems 8 * Programming Group of the University of Utah Computer Science Department. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: scsi.c 1.3 90/01/27$ 13 * 14 * @(#)scsi.c 7.2 (Berkeley) 12/16/90 15 */ 16 17 /* 18 * SCSI bus driver for standalone programs. 19 */ 20 21 #include "sys/types.h" 22 #include "sys/reboot.h" 23 #include "../dev/device.h" 24 #include "../dev/scsireg.h" 25 #include "scsivar.h" 26 27 #include "saio.h" 28 #include "samachdep.h" 29 30 struct scsi_softc scsi_softc[NSCSI]; 31 32 #define scsiunit(x) ((x) >> 3) 33 #define scsislave(x) ((x) & 7) 34 35 void scsireset(); 36 int scsi_cmd_wait = 500; 37 int scsi_data_wait = 300000; 38 39 scsiinit() 40 { 41 extern struct hp_hw sc_table[]; 42 register struct hp_hw *hw; 43 register struct scsi_softc *hs; 44 register int i, addr; 45 static int first = 1; 46 47 i = 0; 48 for (hw = sc_table; i < NSCSI && hw < &sc_table[MAX_CTLR]; hw++) { 49 if (hw->hw_type != SCSI) 50 continue; 51 hs = &scsi_softc[i]; 52 hs->sc_addr = hw->hw_addr; 53 scsireset(i); 54 if (howto & RB_ASKNAME) 55 printf("scsi%d at sc%d\n", i, hw->hw_sc); 56 /* 57 * Adjust devtype on first call. This routine assumes that 58 * adaptor is in the high byte of devtype. 59 */ 60 if (first && ((devtype >> 24) & 0xff) == hw->hw_sc) { 61 devtype = (devtype & 0x00ffffff) | (i << 24); 62 first = 0; 63 } 64 hs->sc_alive = 1; 65 i++; 66 } 67 } 68 69 scsialive(unit) 70 register int unit; 71 { 72 unit = scsiunit(unit); 73 if (unit >= NSCSI || scsi_softc[unit].sc_alive == 0) 74 return (0); 75 return (1); 76 } 77 78 void 79 scsireset(unit) 80 register int unit; 81 { 82 volatile register struct scsidevice *hd; 83 register struct scsi_softc *hs; 84 u_int i; 85 86 unit = scsiunit(unit); 87 hs = &scsi_softc[unit]; 88 hd = (struct scsidevice *)hs->sc_addr; 89 hd->scsi_id = 0xFF; 90 DELAY(100); 91 /* 92 * Disable interrupts then reset the FUJI chip. 93 */ 94 hd->scsi_csr = 0; 95 hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST; 96 hd->scsi_scmd = 0; 97 hd->scsi_tmod = 0; 98 hd->scsi_pctl = 0; 99 hd->scsi_temp = 0; 100 hd->scsi_tch = 0; 101 hd->scsi_tcm = 0; 102 hd->scsi_tcl = 0; 103 hd->scsi_ints = 0; 104 105 /* 106 * Configure the FUJI chip with its SCSI address, all 107 * interrupts enabled & appropriate parity. 108 */ 109 i = (~hd->scsi_hconf) & 0x7; 110 hs->sc_scsi_addr = 1 << i; 111 hd->scsi_bdid = i; 112 if (hd->scsi_hconf & HCONF_PARITY) 113 hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 114 SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 115 SCTL_INTR_ENAB | SCTL_PARITY_ENAB; 116 else 117 hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB | 118 SCTL_SEL_ENAB | SCTL_RESEL_ENAB | 119 SCTL_INTR_ENAB; 120 hd->scsi_sctl &=~ SCTL_DISABLE; 121 } 122 123 124 int 125 scsiabort(hs, hd) 126 register struct scsi_softc *hs; 127 volatile register struct scsidevice *hd; 128 { 129 printf("scsi error: scsiabort\n"); 130 return (0); 131 } 132 133 static int 134 issue_select(hd, target, our_addr) 135 volatile register struct scsidevice *hd; 136 u_char target, our_addr; 137 { 138 if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY)) 139 return (1); 140 141 if (hd->scsi_ints & INTS_DISCON) 142 hd->scsi_ints = INTS_DISCON; 143 144 hd->scsi_pctl = 0; 145 hd->scsi_temp = (1 << target) | our_addr; 146 /* select timeout is hardcoded to 2ms */ 147 hd->scsi_tch = 0; 148 hd->scsi_tcm = 32; 149 hd->scsi_tcl = 4; 150 151 hd->scsi_scmd = SCMD_SELECT; 152 return (0); 153 } 154 155 static int 156 wait_for_select(hd) 157 volatile register struct scsidevice *hd; 158 { 159 u_char ints; 160 161 while ((ints = hd->scsi_ints) == 0) 162 DELAY(1); 163 hd->scsi_ints = ints; 164 return (!(hd->scsi_ssts & SSTS_INITIATOR)); 165 } 166 167 static int 168 ixfer_start(hd, len, phase, wait) 169 volatile register struct scsidevice *hd; 170 int len; 171 u_char phase; 172 register int wait; 173 { 174 175 hd->scsi_tch = len >> 16; 176 hd->scsi_tcm = len >> 8; 177 hd->scsi_tcl = len; 178 hd->scsi_pctl = phase; 179 hd->scsi_tmod = 0; /*XXX*/ 180 hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR; 181 182 /* wait for xfer to start or svc_req interrupt */ 183 while ((hd->scsi_ssts & SSTS_BUSY) == 0) { 184 if (hd->scsi_ints || --wait < 0) 185 return (0); 186 DELAY(1); 187 } 188 return (1); 189 } 190 191 static int 192 ixfer_out(hd, len, buf) 193 volatile register struct scsidevice *hd; 194 int len; 195 register u_char *buf; 196 { 197 register int wait = scsi_data_wait; 198 199 for (; len > 0; --len) { 200 while (hd->scsi_ssts & SSTS_DREG_FULL) { 201 if (hd->scsi_ints || --wait < 0) 202 return (len); 203 DELAY(1); 204 } 205 hd->scsi_dreg = *buf++; 206 } 207 return (0); 208 } 209 210 static int 211 ixfer_in(hd, len, buf) 212 volatile register struct scsidevice *hd; 213 int len; 214 register u_char *buf; 215 { 216 register int wait = scsi_data_wait; 217 218 for (; len > 0; --len) { 219 while (hd->scsi_ssts & SSTS_DREG_EMPTY) { 220 if (hd->scsi_ints || --wait < 0) { 221 while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) { 222 *buf++ = hd->scsi_dreg; 223 --len; 224 } 225 return (len); 226 } 227 DELAY(1); 228 } 229 *buf++ = hd->scsi_dreg; 230 } 231 return (len); 232 } 233 234 static int 235 scsiicmd(hs, target, cbuf, clen, buf, len, xferphase) 236 struct scsi_softc *hs; 237 int target; 238 u_char *cbuf; 239 int clen; 240 u_char *buf; 241 int len; 242 u_char xferphase; 243 { 244 volatile register struct scsidevice *hd = 245 (struct scsidevice *)hs->sc_addr; 246 int i; 247 u_char phase, ints; 248 register int wait; 249 250 /* select the SCSI bus (it's an error if bus isn't free) */ 251 if (issue_select(hd, target, hs->sc_scsi_addr)) 252 return (0); 253 if (wait_for_select(hd)) 254 return (0); 255 /* 256 * Wait for a phase change (or error) then let the device 257 * sequence us through the various SCSI phases. 258 */ 259 phase = CMD_PHASE; 260 while (1) { 261 wait = scsi_cmd_wait; 262 switch (phase) { 263 264 case CMD_PHASE: 265 if (ixfer_start(hd, clen, phase, wait)) 266 if (ixfer_out(hd, clen, cbuf)) 267 goto abort; 268 phase = xferphase; 269 break; 270 271 case DATA_IN_PHASE: 272 if (len <= 0) 273 goto abort; 274 wait = scsi_data_wait; 275 if (ixfer_start(hd, len, phase, wait) || 276 !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 277 ixfer_in(hd, len, buf); 278 phase = STATUS_PHASE; 279 break; 280 281 case DATA_OUT_PHASE: 282 if (len <= 0) 283 goto abort; 284 wait = scsi_data_wait; 285 if (ixfer_start(hd, len, phase, wait)) 286 if (ixfer_out(hd, len, buf)) 287 goto abort; 288 phase = STATUS_PHASE; 289 break; 290 291 case STATUS_PHASE: 292 wait = scsi_data_wait; 293 if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) || 294 !(hd->scsi_ssts & SSTS_DREG_EMPTY)) 295 ixfer_in(hd, sizeof(hs->sc_stat), &hs->sc_stat); 296 phase = MESG_IN_PHASE; 297 break; 298 299 case MESG_IN_PHASE: 300 if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) || 301 !(hd->scsi_ssts & SSTS_DREG_EMPTY)) { 302 ixfer_in(hd, sizeof(hs->sc_msg), &hs->sc_msg); 303 hd->scsi_scmd = SCMD_RST_ACK; 304 } 305 phase = BUS_FREE_PHASE; 306 break; 307 308 case BUS_FREE_PHASE: 309 return (1); 310 311 default: 312 printf("unexpected scsi phase %d\n", phase); 313 goto abort; 314 } 315 /* wait for last command to complete */ 316 while ((ints = hd->scsi_ints) == 0) { 317 if (--wait < 0) 318 goto abort; 319 DELAY(1); 320 } 321 hd->scsi_ints = ints; 322 if (ints & INTS_SRV_REQ) 323 phase = hd->scsi_psns & PHASE; 324 else if (ints & INTS_DISCON) 325 return (1); 326 else if ((ints & INTS_CMD_DONE) == 0) { 327 goto abort; 328 } 329 } 330 abort: 331 scsiabort(hs, hd); 332 return (0); 333 } 334 335 int 336 scsi_test_unit_rdy(unit) 337 { 338 int ctlr = scsiunit(unit); 339 int slave = scsislave(unit); 340 register struct scsi_softc *hs = &scsi_softc[ctlr]; 341 static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY }; 342 343 if (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0, 344 STATUS_PHASE) == 0) 345 return (0); 346 347 return (hs->sc_stat == 0); 348 } 349 350 int 351 scsi_request_sense(unit, buf, len) 352 int unit; 353 u_char *buf; 354 unsigned len; 355 { 356 int ctlr = scsiunit(unit); 357 int slave = scsislave(unit); 358 register struct scsi_softc *hs = &scsi_softc[ctlr]; 359 static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE }; 360 361 cdb.len = len; 362 return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE)); 363 } 364 365 int 366 scsi_read_capacity(unit, buf, len) 367 int unit; 368 u_char *buf; 369 unsigned len; 370 { 371 int ctlr = scsiunit(unit); 372 int slave = scsislave(unit); 373 register struct scsi_softc *hs = &scsi_softc[ctlr]; 374 static struct scsi_cdb10 cdb = { CMD_READ_CAPACITY }; 375 376 return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE)); 377 } 378 379 int 380 scsi_tt_read(unit, buf, len, blk, nblk) 381 int unit; 382 u_char *buf; 383 u_int len; 384 daddr_t blk; 385 u_int nblk; 386 { 387 int ctlr = scsiunit(unit); 388 int slave = scsislave(unit); 389 register struct scsi_softc *hs = &scsi_softc[ctlr]; 390 struct scsi_cdb10 cdb; 391 int stat; 392 393 bzero(&cdb, sizeof(cdb)); 394 cdb.cmd = CMD_READ_EXT; 395 cdb.lbah = blk >> 24; 396 cdb.lbahm = blk >> 16; 397 cdb.lbalm = blk >> 8; 398 cdb.lbal = blk; 399 cdb.lenh = nblk >> (8 + DEV_BSHIFT); 400 cdb.lenl = nblk >> DEV_BSHIFT; 401 stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE); 402 if (stat == 0) 403 return (1); 404 return (hs->sc_stat); 405 } 406 407 int 408 scsi_tt_write(unit, buf, len, blk, nblk) 409 int unit; 410 u_char *buf; 411 u_int len; 412 daddr_t blk; 413 u_int nblk; 414 { 415 int ctlr = scsiunit(unit); 416 int slave = scsislave(unit); 417 register struct scsi_softc *hs = &scsi_softc[ctlr]; 418 struct scsi_cdb10 cdb; 419 int stat; 420 421 bzero(&cdb, sizeof(cdb)); 422 cdb.cmd = CMD_WRITE_EXT; 423 cdb.lbah = blk >> 24; 424 cdb.lbahm = blk >> 16; 425 cdb.lbalm = blk >> 8; 426 cdb.lbal = blk; 427 cdb.lenh = nblk >> (8 + DEV_BSHIFT); 428 cdb.lenl = nblk >> DEV_BSHIFT; 429 stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE); 430 if (stat == 0) 431 return (1); 432 return (hs->sc_stat); 433 } 434