1 /* $NetBSD: uha.c,v 1.7 1997/03/29 02:32:31 mycroft Exp $ */ 2 3 #undef UHADEBUG 4 #ifdef DDB 5 #define integrate 6 #else 7 #define integrate static inline 8 #endif 9 10 /* 11 * Copyright (c) 1994, 1996, 1997 Charles M. Hannum. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by Charles M. Hannum. 24 * 4. The name of the author may not be used to endorse or promote products 25 * derived from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu) 41 * Slight fixes to timeouts to run with the 34F 42 * Thanks to Julian Elischer for advice and help with this port. 43 * 44 * Originally written by Julian Elischer (julian@tfs.com) 45 * for TRW Financial Systems for use under the MACH(2.5) operating system. 46 * 47 * TRW Financial Systems, in accordance with their agreement with Carnegie 48 * Mellon University, makes this software available to CMU to distribute 49 * or use in any manner that they see fit as long as this message is kept with 50 * the software. For this reason TFS also grants any other persons or 51 * organisations permission to use or modify this software. 52 * 53 * TFS supplies this software to be publicly redistributed 54 * on the understanding that TFS is not responsible for the correct 55 * functioning of this software in any circumstances. 56 * 57 * commenced: Sun Sep 27 18:14:01 PDT 1992 58 * slight mod to make work with 34F as well: Wed Jun 2 18:05:48 WST 1993 59 */ 60 61 #include <sys/types.h> 62 #include <sys/param.h> 63 #include <sys/systm.h> 64 #include <sys/kernel.h> 65 #include <sys/errno.h> 66 #include <sys/ioctl.h> 67 #include <sys/device.h> 68 #include <sys/malloc.h> 69 #include <sys/buf.h> 70 #include <sys/proc.h> 71 #include <sys/user.h> 72 73 #include <machine/bus.h> 74 #include <machine/intr.h> 75 76 #include <scsi/scsi_all.h> 77 #include <scsi/scsiconf.h> 78 79 #include <dev/ic/uhareg.h> 80 #include <dev/ic/uhavar.h> 81 82 #ifndef DDB 83 #define Debugger() panic("should call debugger here (uha.c)") 84 #endif /* ! DDB */ 85 86 #define KVTOPHYS(x) vtophys(x) 87 88 integrate void uha_reset_mscp __P((struct uha_softc *, struct uha_mscp *)); 89 void uha_free_mscp __P((struct uha_softc *, struct uha_mscp *)); 90 integrate void uha_init_mscp __P((struct uha_softc *, struct uha_mscp *)); 91 struct uha_mscp *uha_get_mscp __P((struct uha_softc *, int)); 92 void uhaminphys __P((struct buf *)); 93 int uha_scsi_cmd __P((struct scsi_xfer *)); 94 95 struct scsi_adapter uha_switch = { 96 uha_scsi_cmd, 97 uhaminphys, 98 0, 99 0, 100 }; 101 102 /* the below structure is so we have a default dev struct for out link struct */ 103 struct scsi_device uha_dev = { 104 NULL, /* Use default error handler */ 105 NULL, /* have a queue, served by this */ 106 NULL, /* have no async handler */ 107 NULL, /* Use default 'done' routine */ 108 }; 109 110 struct cfdriver uha_cd = { 111 NULL, "uha", DV_DULL 112 }; 113 114 #define UHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */ 115 116 /* 117 * Attach all the sub-devices we can find 118 */ 119 void 120 uha_attach(sc, upd) 121 struct uha_softc *sc; 122 struct uha_probe_data *upd; 123 { 124 125 (sc->init)(sc); 126 TAILQ_INIT(&sc->sc_free_mscp); 127 128 /* 129 * fill in the prototype scsi_link. 130 */ 131 sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE; 132 sc->sc_link.adapter_softc = sc; 133 sc->sc_link.adapter_target = upd->sc_scsi_dev; 134 sc->sc_link.adapter = &uha_switch; 135 sc->sc_link.device = &uha_dev; 136 sc->sc_link.openings = 2; 137 sc->sc_link.max_target = 7; 138 139 /* 140 * ask the adapter what subunits are present 141 */ 142 config_found(&sc->sc_dev, &sc->sc_link, scsiprint); 143 } 144 145 integrate void 146 uha_reset_mscp(sc, mscp) 147 struct uha_softc *sc; 148 struct uha_mscp *mscp; 149 { 150 151 mscp->flags = 0; 152 } 153 154 /* 155 * A mscp (and hence a mbx-out) is put onto the free list. 156 */ 157 void 158 uha_free_mscp(sc, mscp) 159 struct uha_softc *sc; 160 struct uha_mscp *mscp; 161 { 162 int s; 163 164 s = splbio(); 165 166 uha_reset_mscp(sc, mscp); 167 TAILQ_INSERT_HEAD(&sc->sc_free_mscp, mscp, chain); 168 169 /* 170 * If there were none, wake anybody waiting for one to come free, 171 * starting with queued entries. 172 */ 173 if (mscp->chain.tqe_next == 0) 174 wakeup(&sc->sc_free_mscp); 175 176 splx(s); 177 } 178 179 integrate void 180 uha_init_mscp(sc, mscp) 181 struct uha_softc *sc; 182 struct uha_mscp *mscp; 183 { 184 int hashnum; 185 186 bzero(mscp, sizeof(struct uha_mscp)); 187 /* 188 * put in the phystokv hash table 189 * Never gets taken out. 190 */ 191 mscp->hashkey = KVTOPHYS(mscp); 192 hashnum = MSCP_HASH(mscp->hashkey); 193 mscp->nexthash = sc->sc_mscphash[hashnum]; 194 sc->sc_mscphash[hashnum] = mscp; 195 uha_reset_mscp(sc, mscp); 196 } 197 198 /* 199 * Get a free mscp 200 * 201 * If there are none, see if we can allocate a new one. If so, put it in the 202 * hash table too otherwise either return an error or sleep. 203 */ 204 struct uha_mscp * 205 uha_get_mscp(sc, flags) 206 struct uha_softc *sc; 207 int flags; 208 { 209 struct uha_mscp *mscp; 210 int s; 211 212 s = splbio(); 213 214 /* 215 * If we can and have to, sleep waiting for one to come free 216 * but only if we can't allocate a new one 217 */ 218 for (;;) { 219 mscp = sc->sc_free_mscp.tqh_first; 220 if (mscp) { 221 TAILQ_REMOVE(&sc->sc_free_mscp, mscp, chain); 222 break; 223 } 224 if (sc->sc_nummscps < UHA_MSCP_MAX) { 225 mscp = (struct uha_mscp *) malloc(sizeof(struct uha_mscp), 226 M_TEMP, M_NOWAIT); 227 if (!mscp) { 228 printf("%s: can't malloc mscp\n", 229 sc->sc_dev.dv_xname); 230 goto out; 231 } 232 uha_init_mscp(sc, mscp); 233 sc->sc_nummscps++; 234 break; 235 } 236 if ((flags & SCSI_NOSLEEP) != 0) 237 goto out; 238 tsleep(&sc->sc_free_mscp, PRIBIO, "uhamsc", 0); 239 } 240 241 mscp->flags |= MSCP_ALLOC; 242 243 out: 244 splx(s); 245 return (mscp); 246 } 247 248 /* 249 * given a physical address, find the mscp that it corresponds to. 250 */ 251 struct uha_mscp * 252 uha_mscp_phys_kv(sc, mscp_phys) 253 struct uha_softc *sc; 254 u_long mscp_phys; 255 { 256 int hashnum = MSCP_HASH(mscp_phys); 257 struct uha_mscp *mscp = sc->sc_mscphash[hashnum]; 258 259 while (mscp) { 260 if (mscp->hashkey == mscp_phys) 261 break; 262 mscp = mscp->nexthash; 263 } 264 return (mscp); 265 } 266 267 /* 268 * We have a mscp which has been processed by the adaptor, now we look to see 269 * how the operation went. 270 */ 271 void 272 uha_done(sc, mscp) 273 struct uha_softc *sc; 274 struct uha_mscp *mscp; 275 { 276 struct scsi_sense_data *s1, *s2; 277 struct scsi_xfer *xs = mscp->xs; 278 279 SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n")); 280 /* 281 * Otherwise, put the results of the operation 282 * into the xfer and call whoever started it 283 */ 284 if ((mscp->flags & MSCP_ALLOC) == 0) { 285 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname); 286 Debugger(); 287 return; 288 } 289 if (xs->error == XS_NOERROR) { 290 if (mscp->host_stat != UHA_NO_ERR) { 291 switch (mscp->host_stat) { 292 case UHA_SBUS_TIMEOUT: /* No response */ 293 xs->error = XS_SELTIMEOUT; 294 break; 295 default: /* Other scsi protocol messes */ 296 printf("%s: host_stat %x\n", 297 sc->sc_dev.dv_xname, mscp->host_stat); 298 xs->error = XS_DRIVER_STUFFUP; 299 } 300 } else if (mscp->target_stat != SCSI_OK) { 301 switch (mscp->target_stat) { 302 case SCSI_CHECK: 303 s1 = &mscp->mscp_sense; 304 s2 = &xs->sense; 305 *s2 = *s1; 306 xs->error = XS_SENSE; 307 break; 308 case SCSI_BUSY: 309 xs->error = XS_BUSY; 310 break; 311 default: 312 printf("%s: target_stat %x\n", 313 sc->sc_dev.dv_xname, mscp->target_stat); 314 xs->error = XS_DRIVER_STUFFUP; 315 } 316 } else 317 xs->resid = 0; 318 } 319 uha_free_mscp(sc, mscp); 320 xs->flags |= ITSDONE; 321 scsi_done(xs); 322 } 323 324 void 325 uhaminphys(bp) 326 struct buf *bp; 327 { 328 329 if (bp->b_bcount > ((UHA_NSEG - 1) << PGSHIFT)) 330 bp->b_bcount = ((UHA_NSEG - 1) << PGSHIFT); 331 minphys(bp); 332 } 333 334 /* 335 * start a scsi operation given the command and the data address. Also 336 * needs the unit, target and lu. 337 */ 338 int 339 uha_scsi_cmd(xs) 340 struct scsi_xfer *xs; 341 { 342 struct scsi_link *sc_link = xs->sc_link; 343 struct uha_softc *sc = sc_link->adapter_softc; 344 struct uha_mscp *mscp; 345 struct uha_dma_seg *sg; 346 int seg; /* scatter gather seg being worked on */ 347 u_long thiskv, thisphys, nextphys; 348 int bytes_this_seg, bytes_this_page, datalen, flags; 349 int s; 350 351 SC_DEBUG(sc_link, SDEV_DB2, ("uha_scsi_cmd\n")); 352 /* 353 * get a mscp (mbox-out) to use. If the transfer 354 * is from a buf (possibly from interrupt time) 355 * then we can't allow it to sleep 356 */ 357 flags = xs->flags; 358 if ((mscp = uha_get_mscp(sc, flags)) == NULL) { 359 xs->error = XS_DRIVER_STUFFUP; 360 return (TRY_AGAIN_LATER); 361 } 362 mscp->xs = xs; 363 mscp->timeout = xs->timeout; 364 365 /* 366 * Put all the arguments for the xfer in the mscp 367 */ 368 if (flags & SCSI_RESET) { 369 mscp->opcode = UHA_SDR; 370 mscp->ca = 0x01; 371 } else { 372 mscp->opcode = UHA_TSP; 373 /* XXX Not for tapes. */ 374 mscp->ca = 0x01; 375 bcopy(xs->cmd, &mscp->scsi_cmd, mscp->scsi_cmd_length); 376 } 377 mscp->xdir = UHA_SDET; 378 mscp->dcn = 0x00; 379 mscp->chan = 0x00; 380 mscp->target = sc_link->target; 381 mscp->lun = sc_link->lun; 382 mscp->scsi_cmd_length = xs->cmdlen; 383 mscp->sense_ptr = KVTOPHYS(&mscp->mscp_sense); 384 mscp->req_sense_length = sizeof(mscp->mscp_sense); 385 mscp->host_stat = 0x00; 386 mscp->target_stat = 0x00; 387 388 if (xs->datalen) { 389 sg = mscp->uha_dma; 390 seg = 0; 391 #ifdef TFS 392 if (flags & SCSI_DATA_UIO) { 393 struct iovec *iovp; 394 iovp = ((struct uio *) xs->data)->uio_iov; 395 datalen = ((struct uio *) xs->data)->uio_iovcnt; 396 xs->datalen = 0; 397 while (datalen && seg < UHA_NSEG) { 398 sg->seg_addr = (physaddr)iovp->iov_base; 399 sg->seg_len = iovp->iov_len; 400 xs->datalen += iovp->iov_len; 401 SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)", 402 iovp->iov_len, iovp->iov_base)); 403 sg++; 404 iovp++; 405 seg++; 406 datalen--; 407 } 408 } else 409 #endif /*TFS */ 410 { 411 /* 412 * Set up the scatter gather block 413 */ 414 SC_DEBUG(sc_link, SDEV_DB4, 415 ("%d @0x%x:- ", xs->datalen, xs->data)); 416 datalen = xs->datalen; 417 thiskv = (int) xs->data; 418 thisphys = KVTOPHYS(thiskv); 419 420 while (datalen && seg < UHA_NSEG) { 421 bytes_this_seg = 0; 422 423 /* put in the base address */ 424 sg->seg_addr = thisphys; 425 426 SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys)); 427 428 /* do it at least once */ 429 nextphys = thisphys; 430 while (datalen && thisphys == nextphys) { 431 /* 432 * This page is contiguous (physically) 433 * with the the last, just extend the 434 * length 435 */ 436 /* how far to the end of the page */ 437 nextphys = (thisphys & ~PGOFSET) + NBPG; 438 bytes_this_page = nextphys - thisphys; 439 /**** or the data ****/ 440 bytes_this_page = min(bytes_this_page, 441 datalen); 442 bytes_this_seg += bytes_this_page; 443 datalen -= bytes_this_page; 444 445 /* get more ready for the next page */ 446 thiskv = (thiskv & ~PGOFSET) + NBPG; 447 if (datalen) 448 thisphys = KVTOPHYS(thiskv); 449 } 450 /* 451 * next page isn't contiguous, finish the seg 452 */ 453 SC_DEBUGN(sc_link, SDEV_DB4, 454 ("(0x%x)", bytes_this_seg)); 455 sg->seg_len = bytes_this_seg; 456 sg++; 457 seg++; 458 } 459 } 460 /* end of iov/kv decision */ 461 SC_DEBUGN(sc_link, SDEV_DB4, ("\n")); 462 if (datalen) { 463 /* 464 * there's still data, must have run out of segs! 465 */ 466 printf("%s: uha_scsi_cmd, more than %d dma segs\n", 467 sc->sc_dev.dv_xname, UHA_NSEG); 468 goto bad; 469 } 470 mscp->data_addr = KVTOPHYS(mscp->uha_dma); 471 mscp->data_length = xs->datalen; 472 mscp->sgth = 0x01; 473 mscp->sg_num = seg; 474 } else { /* No data xfer, use non S/G values */ 475 mscp->data_addr = (physaddr)0; 476 mscp->data_length = 0; 477 mscp->sgth = 0x00; 478 mscp->sg_num = 0; 479 } 480 mscp->link_id = 0; 481 mscp->link_addr = (physaddr)0; 482 483 s = splbio(); 484 (sc->start_mbox)(sc, mscp); 485 splx(s); 486 487 /* 488 * Usually return SUCCESSFULLY QUEUED 489 */ 490 if ((flags & SCSI_POLL) == 0) 491 return (SUCCESSFULLY_QUEUED); 492 493 /* 494 * If we can't use interrupts, poll on completion 495 */ 496 if ((sc->poll)(sc, xs, mscp->timeout)) { 497 uha_timeout(mscp); 498 if ((sc->poll)(sc, xs, mscp->timeout)) 499 uha_timeout(mscp); 500 } 501 return (COMPLETE); 502 503 bad: 504 xs->error = XS_DRIVER_STUFFUP; 505 uha_free_mscp(sc, mscp); 506 return (COMPLETE); 507 } 508 509 void 510 uha_timeout(arg) 511 void *arg; 512 { 513 struct uha_mscp *mscp = arg; 514 struct scsi_xfer *xs = mscp->xs; 515 struct scsi_link *sc_link = xs->sc_link; 516 struct uha_softc *sc = sc_link->adapter_softc; 517 int s; 518 519 sc_print_addr(sc_link); 520 printf("timed out"); 521 522 s = splbio(); 523 524 if (mscp->flags & MSCP_ABORT) { 525 /* abort timed out */ 526 printf(" AGAIN\n"); 527 /* XXX Must reset! */ 528 } else { 529 /* abort the operation that has timed out */ 530 printf("\n"); 531 mscp->xs->error = XS_TIMEOUT; 532 mscp->timeout = UHA_ABORT_TIMEOUT; 533 mscp->flags |= MSCP_ABORT; 534 (sc->start_mbox)(sc, mscp); 535 } 536 537 splx(s); 538 } 539