1 /* $NetBSD: uha.c,v 1.2 1996/10/10 19:59:17 christos 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 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 (ultra14f.c)") 84 #endif /* ! DDB */ 85 86 #define KVTOPHYS(x) vtophys(x) 87 88 void uha_reset_mscp __P((struct uha_softc *, struct uha_mscp *)); 89 void uha_free_mscp __P((struct uha_softc *, struct uha_mscp *)); 90 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) 121 struct uha_softc *sc; 122 { 123 124 (sc->init)(sc); 125 TAILQ_INIT(&sc->sc_free_mscp); 126 127 /* 128 * fill in the prototype scsi_link. 129 */ 130 sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE; 131 sc->sc_link.adapter_softc = sc; 132 sc->sc_link.adapter_target = sc->sc_scsi_dev; 133 sc->sc_link.adapter = &uha_switch; 134 sc->sc_link.device = &uha_dev; 135 sc->sc_link.openings = 2; 136 137 /* 138 * ask the adapter what subunits are present 139 */ 140 config_found(&sc->sc_dev, &sc->sc_link, scsiprint); 141 } 142 143 integrate void 144 uha_reset_mscp(sc, mscp) 145 struct uha_softc *sc; 146 struct uha_mscp *mscp; 147 { 148 149 mscp->flags = 0; 150 } 151 152 /* 153 * A mscp (and hence a mbx-out) is put onto the free list. 154 */ 155 void 156 uha_free_mscp(sc, mscp) 157 struct uha_softc *sc; 158 struct uha_mscp *mscp; 159 { 160 int s; 161 162 s = splbio(); 163 164 uha_reset_mscp(sc, mscp); 165 TAILQ_INSERT_HEAD(&sc->sc_free_mscp, mscp, chain); 166 167 /* 168 * If there were none, wake anybody waiting for one to come free, 169 * starting with queued entries. 170 */ 171 if (mscp->chain.tqe_next == 0) 172 wakeup(&sc->sc_free_mscp); 173 174 splx(s); 175 } 176 177 integrate void 178 uha_init_mscp(sc, mscp) 179 struct uha_softc *sc; 180 struct uha_mscp *mscp; 181 { 182 int hashnum; 183 184 bzero(mscp, sizeof(struct uha_mscp)); 185 /* 186 * put in the phystokv hash table 187 * Never gets taken out. 188 */ 189 mscp->hashkey = KVTOPHYS(mscp); 190 hashnum = MSCP_HASH(mscp->hashkey); 191 mscp->nexthash = sc->sc_mscphash[hashnum]; 192 sc->sc_mscphash[hashnum] = mscp; 193 uha_reset_mscp(sc, mscp); 194 } 195 196 /* 197 * Get a free mscp 198 * 199 * If there are none, see if we can allocate a new one. If so, put it in the 200 * hash table too otherwise either return an error or sleep. 201 */ 202 struct uha_mscp * 203 uha_get_mscp(sc, flags) 204 struct uha_softc *sc; 205 int flags; 206 { 207 struct uha_mscp *mscp; 208 int s; 209 210 s = splbio(); 211 212 /* 213 * If we can and have to, sleep waiting for one to come free 214 * but only if we can't allocate a new one 215 */ 216 for (;;) { 217 mscp = sc->sc_free_mscp.tqh_first; 218 if (mscp) { 219 TAILQ_REMOVE(&sc->sc_free_mscp, mscp, chain); 220 break; 221 } 222 if (sc->sc_nummscps < UHA_MSCP_MAX) { 223 mscp = (struct uha_mscp *) malloc(sizeof(struct uha_mscp), 224 M_TEMP, M_NOWAIT); 225 if (!mscp) { 226 kprintf("%s: can't malloc mscp\n", 227 sc->sc_dev.dv_xname); 228 goto out; 229 } 230 uha_init_mscp(sc, mscp); 231 sc->sc_nummscps++; 232 break; 233 } 234 if ((flags & SCSI_NOSLEEP) != 0) 235 goto out; 236 tsleep(&sc->sc_free_mscp, PRIBIO, "uhamsc", 0); 237 } 238 239 mscp->flags |= MSCP_ALLOC; 240 241 out: 242 splx(s); 243 return (mscp); 244 } 245 246 /* 247 * given a physical address, find the mscp that it corresponds to. 248 */ 249 struct uha_mscp * 250 uha_mscp_phys_kv(sc, mscp_phys) 251 struct uha_softc *sc; 252 u_long mscp_phys; 253 { 254 int hashnum = MSCP_HASH(mscp_phys); 255 struct uha_mscp *mscp = sc->sc_mscphash[hashnum]; 256 257 while (mscp) { 258 if (mscp->hashkey == mscp_phys) 259 break; 260 mscp = mscp->nexthash; 261 } 262 return (mscp); 263 } 264 265 /* 266 * We have a mscp which has been processed by the adaptor, now we look to see 267 * how the operation went. 268 */ 269 void 270 uha_done(sc, mscp) 271 struct uha_softc *sc; 272 struct uha_mscp *mscp; 273 { 274 struct scsi_sense_data *s1, *s2; 275 struct scsi_xfer *xs = mscp->xs; 276 277 SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n")); 278 /* 279 * Otherwise, put the results of the operation 280 * into the xfer and call whoever started it 281 */ 282 if ((mscp->flags & MSCP_ALLOC) == 0) { 283 kprintf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname); 284 Debugger(); 285 return; 286 } 287 if (xs->error == XS_NOERROR) { 288 if (mscp->host_stat != UHA_NO_ERR) { 289 switch (mscp->host_stat) { 290 case UHA_SBUS_TIMEOUT: /* No response */ 291 xs->error = XS_SELTIMEOUT; 292 break; 293 default: /* Other scsi protocol messes */ 294 kprintf("%s: host_stat %x\n", 295 sc->sc_dev.dv_xname, mscp->host_stat); 296 xs->error = XS_DRIVER_STUFFUP; 297 } 298 } else if (mscp->target_stat != SCSI_OK) { 299 switch (mscp->target_stat) { 300 case SCSI_CHECK: 301 s1 = &mscp->mscp_sense; 302 s2 = &xs->sense; 303 *s2 = *s1; 304 xs->error = XS_SENSE; 305 break; 306 case SCSI_BUSY: 307 xs->error = XS_BUSY; 308 break; 309 default: 310 kprintf("%s: target_stat %x\n", 311 sc->sc_dev.dv_xname, mscp->target_stat); 312 xs->error = XS_DRIVER_STUFFUP; 313 } 314 } else 315 xs->resid = 0; 316 } 317 uha_free_mscp(sc, mscp); 318 xs->flags |= ITSDONE; 319 scsi_done(xs); 320 } 321 322 void 323 uhaminphys(bp) 324 struct buf *bp; 325 { 326 327 if (bp->b_bcount > ((UHA_NSEG - 1) << PGSHIFT)) 328 bp->b_bcount = ((UHA_NSEG - 1) << PGSHIFT); 329 minphys(bp); 330 } 331 332 /* 333 * start a scsi operation given the command and the data address. Also 334 * needs the unit, target and lu. 335 */ 336 int 337 uha_scsi_cmd(xs) 338 struct scsi_xfer *xs; 339 { 340 struct scsi_link *sc_link = xs->sc_link; 341 struct uha_softc *sc = sc_link->adapter_softc; 342 struct uha_mscp *mscp; 343 struct uha_dma_seg *sg; 344 int seg; /* scatter gather seg being worked on */ 345 u_long thiskv, thisphys, nextphys; 346 int bytes_this_seg, bytes_this_page, datalen, flags; 347 int s; 348 349 SC_DEBUG(sc_link, SDEV_DB2, ("uha_scsi_cmd\n")); 350 /* 351 * get a mscp (mbox-out) to use. If the transfer 352 * is from a buf (possibly from interrupt time) 353 * then we can't allow it to sleep 354 */ 355 flags = xs->flags; 356 if ((mscp = uha_get_mscp(sc, flags)) == NULL) { 357 xs->error = XS_DRIVER_STUFFUP; 358 return (TRY_AGAIN_LATER); 359 } 360 mscp->xs = xs; 361 mscp->timeout = xs->timeout; 362 363 /* 364 * Put all the arguments for the xfer in the mscp 365 */ 366 if (flags & SCSI_RESET) { 367 mscp->opcode = UHA_SDR; 368 mscp->ca = 0x01; 369 } else { 370 mscp->opcode = UHA_TSP; 371 /* XXX Not for tapes. */ 372 mscp->ca = 0x01; 373 bcopy(xs->cmd, &mscp->scsi_cmd, mscp->scsi_cmd_length); 374 } 375 mscp->xdir = UHA_SDET; 376 mscp->dcn = 0x00; 377 mscp->chan = 0x00; 378 mscp->target = sc_link->target; 379 mscp->lun = sc_link->lun; 380 mscp->scsi_cmd_length = xs->cmdlen; 381 mscp->sense_ptr = KVTOPHYS(&mscp->mscp_sense); 382 mscp->req_sense_length = sizeof(mscp->mscp_sense); 383 mscp->host_stat = 0x00; 384 mscp->target_stat = 0x00; 385 386 if (xs->datalen) { 387 sg = mscp->uha_dma; 388 seg = 0; 389 #ifdef TFS 390 if (flags & SCSI_DATA_UIO) { 391 struct iovec *iovp; 392 iovp = ((struct uio *) xs->data)->uio_iov; 393 datalen = ((struct uio *) xs->data)->uio_iovcnt; 394 xs->datalen = 0; 395 while (datalen && seg < UHA_NSEG) { 396 sg->seg_addr = (physaddr)iovp->iov_base; 397 sg->seg_len = iovp->iov_len; 398 xs->datalen += iovp->iov_len; 399 SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)", 400 iovp->iov_len, iovp->iov_base)); 401 sg++; 402 iovp++; 403 seg++; 404 datalen--; 405 } 406 } else 407 #endif /*TFS */ 408 { 409 /* 410 * Set up the scatter gather block 411 */ 412 SC_DEBUG(sc_link, SDEV_DB4, 413 ("%d @0x%x:- ", xs->datalen, xs->data)); 414 datalen = xs->datalen; 415 thiskv = (int) xs->data; 416 thisphys = KVTOPHYS(thiskv); 417 418 while (datalen && seg < UHA_NSEG) { 419 bytes_this_seg = 0; 420 421 /* put in the base address */ 422 sg->seg_addr = thisphys; 423 424 SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys)); 425 426 /* do it at least once */ 427 nextphys = thisphys; 428 while (datalen && thisphys == nextphys) { 429 /* 430 * This page is contiguous (physically) 431 * with the the last, just extend the 432 * length 433 */ 434 /* how far to the end of the page */ 435 nextphys = (thisphys & ~PGOFSET) + NBPG; 436 bytes_this_page = nextphys - thisphys; 437 /**** or the data ****/ 438 bytes_this_page = min(bytes_this_page, 439 datalen); 440 bytes_this_seg += bytes_this_page; 441 datalen -= bytes_this_page; 442 443 /* get more ready for the next page */ 444 thiskv = (thiskv & ~PGOFSET) + NBPG; 445 if (datalen) 446 thisphys = KVTOPHYS(thiskv); 447 } 448 /* 449 * next page isn't contiguous, finish the seg 450 */ 451 SC_DEBUGN(sc_link, SDEV_DB4, 452 ("(0x%x)", bytes_this_seg)); 453 sg->seg_len = bytes_this_seg; 454 sg++; 455 seg++; 456 } 457 } 458 /* end of iov/kv decision */ 459 SC_DEBUGN(sc_link, SDEV_DB4, ("\n")); 460 if (datalen) { 461 /* 462 * there's still data, must have run out of segs! 463 */ 464 kprintf("%s: uha_scsi_cmd, more than %d dma segs\n", 465 sc->sc_dev.dv_xname, UHA_NSEG); 466 goto bad; 467 } 468 mscp->data_addr = KVTOPHYS(mscp->uha_dma); 469 mscp->data_length = xs->datalen; 470 mscp->sgth = 0x01; 471 mscp->sg_num = seg; 472 } else { /* No data xfer, use non S/G values */ 473 mscp->data_addr = (physaddr)0; 474 mscp->data_length = 0; 475 mscp->sgth = 0x00; 476 mscp->sg_num = 0; 477 } 478 mscp->link_id = 0; 479 mscp->link_addr = (physaddr)0; 480 481 s = splbio(); 482 (sc->start_mbox)(sc, mscp); 483 splx(s); 484 485 /* 486 * Usually return SUCCESSFULLY QUEUED 487 */ 488 if ((flags & SCSI_POLL) == 0) 489 return (SUCCESSFULLY_QUEUED); 490 491 /* 492 * If we can't use interrupts, poll on completion 493 */ 494 if ((sc->poll)(sc, xs, mscp->timeout)) { 495 uha_timeout(mscp); 496 if ((sc->poll)(sc, xs, mscp->timeout)) 497 uha_timeout(mscp); 498 } 499 return (COMPLETE); 500 501 bad: 502 xs->error = XS_DRIVER_STUFFUP; 503 uha_free_mscp(sc, mscp); 504 return (COMPLETE); 505 } 506 507 void 508 uha_timeout(arg) 509 void *arg; 510 { 511 struct uha_mscp *mscp = arg; 512 struct scsi_xfer *xs = mscp->xs; 513 struct scsi_link *sc_link = xs->sc_link; 514 struct uha_softc *sc = sc_link->adapter_softc; 515 int s; 516 517 sc_print_addr(sc_link); 518 kprintf("timed out"); 519 520 s = splbio(); 521 522 if (mscp->flags & MSCP_ABORT) { 523 /* abort timed out */ 524 kprintf(" AGAIN\n"); 525 /* XXX Must reset! */ 526 } else { 527 /* abort the operation that has timed out */ 528 kprintf("\n"); 529 mscp->xs->error = XS_TIMEOUT; 530 mscp->timeout = UHA_ABORT_TIMEOUT; 531 mscp->flags |= MSCP_ABORT; 532 (sc->start_mbox)(sc, mscp); 533 } 534 535 splx(s); 536 } 537