1 /* $NetBSD: sc_wrap.c,v 1.20 2002/10/02 04:27:52 thorpej Exp $ */ 2 3 /* 4 * This driver is slow! Need to rewrite. 5 */ 6 7 #include <sys/types.h> 8 #include <sys/param.h> 9 #include <sys/systm.h> 10 #include <sys/kernel.h> 11 #include <sys/device.h> 12 #include <sys/proc.h> 13 #include <sys/buf.h> 14 #include <sys/malloc.h> 15 16 #include <dev/scsipi/scsi_all.h> 17 #include <dev/scsipi/scsipi_all.h> 18 #include <dev/scsipi/scsiconf.h> 19 #include <dev/scsipi/scsi_message.h> 20 21 #include <newsmips/dev/scsireg.h> 22 #include <newsmips/dev/dmac_0448.h> 23 #include <newsmips/dev/screg_1185.h> 24 25 #include <machine/adrsmap.h> 26 #include <machine/autoconf.h> 27 #include <machine/machConst.h> 28 29 #include <mips/cache.h> 30 31 static int cxd1185_match __P((struct device *, struct cfdata *, void *)); 32 static void cxd1185_attach __P((struct device *, struct device *, void *)); 33 34 CFATTACH_DECL(sc, sizeof(struct sc_softc), 35 cxd1185_match, cxd1185_attach, NULL, NULL); 36 37 void cxd1185_init __P((struct sc_softc *)); 38 static void free_scb __P((struct sc_softc *, struct sc_scb *)); 39 static struct sc_scb *get_scb __P((struct sc_softc *, int)); 40 static void sc_scsipi_request __P((struct scsipi_channel *, 41 scsipi_adapter_req_t, void *)); 42 static int sc_poll __P((struct sc_softc *, int, int)); 43 static void sc_sched __P((struct sc_softc *)); 44 void sc_done __P((struct sc_scb *)); 45 int sc_intr __P((void *)); 46 static void cxd1185_timeout __P((void *)); 47 48 extern void sc_send __P((struct sc_scb *, int, int)); 49 extern int scintr __P((void)); 50 extern void scsi_hardreset __P((void)); 51 extern int sc_busy __P((struct sc_softc *, int)); 52 extern paddr_t kvtophys __P((vaddr_t)); 53 54 static int sc_disconnect = IDT_DISCON; 55 56 int 57 cxd1185_match(parent, cf, aux) 58 struct device *parent; 59 struct cfdata *cf; 60 void *aux; 61 { 62 struct confargs *ca = aux; 63 64 if (strcmp(ca->ca_name, "sc")) 65 return 0; 66 67 return 1; 68 } 69 70 void 71 cxd1185_attach(parent, self, aux) 72 struct device *parent, *self; 73 void *aux; 74 { 75 struct sc_softc *sc = (void *)self; 76 struct sc_scb *scb; 77 int i, intlevel; 78 79 intlevel = sc->sc_dev.dv_cfdata->cf_level; 80 if (intlevel == -1) { 81 #if 0 82 printf(": interrupt level not configured\n"); 83 return; 84 #else 85 printf(": interrupt level not configured; using"); 86 intlevel = 0; 87 #endif 88 } 89 printf(" level %d\n", intlevel); 90 91 if (sc_idenr & 0x08) 92 sc->scsi_1185AQ = 1; 93 else 94 sc->scsi_1185AQ = 0; 95 96 sc->sc_adapter.adapt_dev = &sc->sc_dev; 97 sc->sc_adapter.adapt_nchannels = 1; 98 sc->sc_adapter.adapt_openings = 7; 99 sc->sc_adapter.adapt_max_periph = 1; 100 sc->sc_adapter.adapt_ioctl = NULL; 101 sc->sc_adapter.adapt_minphys = minphys; 102 sc->sc_adapter.adapt_request = sc_scsipi_request; 103 104 memset(&sc->sc_channel, 0, sizeof(sc->sc_channel)); 105 sc->sc_channel.chan_adapter = &sc->sc_adapter; 106 sc->sc_channel.chan_bustype = &scsi_bustype; 107 sc->sc_channel.chan_channel = 0; 108 sc->sc_channel.chan_ntargets = 8; 109 sc->sc_channel.chan_nluns = 8; 110 sc->sc_channel.chan_id = 7; 111 112 TAILQ_INIT(&sc->ready_list); 113 TAILQ_INIT(&sc->free_list); 114 115 scb = sc->sc_scb; 116 for (i = 0; i < 24; i++) { /* XXX 24 */ 117 TAILQ_INSERT_TAIL(&sc->free_list, scb, chain); 118 scb++; 119 } 120 121 cxd1185_init(sc); 122 DELAY(100000); 123 124 hb_intr_establish(intlevel, IPL_BIO, sc_intr, sc); 125 126 config_found(&sc->sc_dev, &sc->sc_channel, scsiprint); 127 } 128 129 void 130 cxd1185_init(sc) 131 struct sc_softc *sc; 132 { 133 int i; 134 135 for (i = 0; i < 8; i++) 136 sc->inuse[i] = 0; 137 138 scsi_hardreset(); 139 } 140 141 void 142 free_scb(sc, scb) 143 struct sc_softc *sc; 144 struct sc_scb *scb; 145 { 146 int s; 147 148 s = splbio(); 149 150 TAILQ_INSERT_HEAD(&sc->free_list, scb, chain); 151 152 /* 153 * If there were none, wake anybody waiting for one to come free, 154 * starting with queued entries. 155 */ 156 if (scb->chain.tqe_next == 0) 157 wakeup(&sc->free_list); 158 159 splx(s); 160 } 161 162 struct sc_scb * 163 get_scb(sc, flags) 164 struct sc_softc *sc; 165 int flags; 166 { 167 int s; 168 struct sc_scb *scb; 169 170 s = splbio(); 171 172 while ((scb = sc->free_list.tqh_first) == NULL && 173 (flags & XS_CTL_NOSLEEP) == 0) 174 tsleep(&sc->free_list, PRIBIO, "sc_scb", 0); 175 if (scb) { 176 TAILQ_REMOVE(&sc->free_list, scb, chain); 177 } 178 179 splx(s); 180 return scb; 181 } 182 183 void 184 sc_scsipi_request(chan, req, arg) 185 struct scsipi_channel *chan; 186 scsipi_adapter_req_t req; 187 void *arg; 188 { 189 struct scsipi_xfer *xs; 190 struct scsipi_periph *periph; 191 struct sc_softc *sc = (void *)chan->chan_adapter->adapt_dev; 192 struct sc_scb *scb; 193 int flags, s; 194 int target; 195 196 switch (req) { 197 case ADAPTER_REQ_RUN_XFER: 198 xs = arg; 199 periph = xs->xs_periph; 200 201 flags = xs->xs_control; 202 if ((scb = get_scb(sc, flags)) == NULL) 203 panic("sc_scsipi_request: no scb"); 204 205 scb->xs = xs; 206 scb->flags = 0; 207 scb->sc_ctag = 0; 208 scb->sc_coffset = 0; 209 scb->istatus = 0; 210 scb->tstatus = 0; 211 scb->message = 0; 212 bzero(scb->msgbuf, sizeof(scb->msgbuf)); 213 214 s = splbio(); 215 216 TAILQ_INSERT_TAIL(&sc->ready_list, scb, chain); 217 sc_sched(sc); 218 splx(s); 219 220 if (flags & XS_CTL_POLL) { 221 target = periph->periph_target; 222 if (sc_poll(sc, target, xs->timeout)) { 223 printf("sc: timeout (retry)\n"); 224 if (sc_poll(sc, target, xs->timeout)) { 225 printf("sc: timeout\n"); 226 } 227 } 228 /* called during autoconfig only... */ 229 mips_dcache_wbinv_all(); /* Flush DCache */ 230 } 231 return; 232 case ADAPTER_REQ_GROW_RESOURCES: 233 /* XXX Not supported. */ 234 return; 235 case ADAPTER_REQ_SET_XFER_MODE: 236 /* XXX Not supported. */ 237 return; 238 } 239 } 240 241 /* 242 * Used when interrupt driven I/O isn't allowed, e.g. during boot. 243 */ 244 int 245 sc_poll(sc, chan, count) 246 struct sc_softc *sc; 247 int chan, count; 248 { 249 volatile u_char *int_stat = (void *)INTST1; 250 volatile u_char *int_clear = (void *)INTCLR1; 251 252 while (sc_busy(sc, chan)) { 253 if (*int_stat & INTST1_DMA) { 254 *int_clear = INTST1_DMA; 255 if (dmac_gstat & CH_INT(CH_SCSI)) { 256 if (dmac_gstat & CH_MRQ(CH_SCSI)) { 257 DELAY(50); 258 if (dmac_gstat & CH_MRQ(CH_SCSI)) 259 printf("dma_poll\n"); 260 } 261 DELAY(10); 262 scintr(); 263 } 264 } 265 DELAY(1000); 266 count--; 267 if (count <= 0) 268 return 1; 269 } 270 return 0; 271 } 272 273 void 274 sc_sched(sc) 275 struct sc_softc *sc; 276 { 277 struct scsipi_xfer *xs; 278 struct scsipi_periph *periph; 279 int ie = 0; 280 int flags; 281 int chan, lun; 282 struct sc_scb *scb, *nextscb; 283 284 scb = sc->ready_list.tqh_first; 285 start: 286 if (scb == NULL) 287 return; 288 289 xs = scb->xs; 290 periph = xs->xs_periph; 291 chan = periph->periph_target; 292 flags = xs->xs_control; 293 294 if (cold) 295 flags |= XS_CTL_POLL; 296 297 if (sc->inuse[chan]) { 298 scb = scb->chain.tqe_next; 299 goto start; 300 } 301 sc->inuse[chan] = 1; 302 303 if (flags & XS_CTL_RESET) 304 printf("SCSI RESET\n"); 305 306 lun = periph->periph_lun; 307 308 scb->identify = MSG_IDENT | sc_disconnect | (lun & IDT_DRMASK); 309 scb->sc_ctrnscnt = xs->datalen; 310 311 /* make va->pa mapping table for dma */ 312 if (xs->datalen > 0) { 313 int pages, offset; 314 int i, pn; 315 vaddr_t va; 316 317 /* bzero(&sc->sc_map[chan], sizeof(struct sc_map)); */ 318 319 va = (vaddr_t)xs->data; 320 321 offset = va & PGOFSET; 322 pages = (offset + xs->datalen + NBPG -1 ) >> PGSHIFT; 323 if (pages >= NSCMAP) 324 panic("sc_map: Too many pages"); 325 326 for (i = 0; i < pages; i++) { 327 pn = kvtophys(va) >> PGSHIFT; 328 sc->sc_map[chan].mp_addr[i] = pn; 329 va += NBPG; 330 } 331 332 sc->sc_map[chan].mp_offset = offset; 333 sc->sc_map[chan].mp_pages = pages; 334 scb->sc_map = &sc->sc_map[chan]; 335 } 336 337 if ((flags & XS_CTL_POLL) == 0) 338 ie = SCSI_INTEN; 339 340 if (xs->data) 341 scb->sc_cpoint = (void *)xs->data; 342 else 343 scb->sc_cpoint = scb->msgbuf; 344 scb->scb_softc = sc; 345 346 callout_reset(&scb->xs->xs_callout, hz * 10, cxd1185_timeout, scb); 347 sc_send(scb, chan, ie); 348 callout_stop(&scb->xs->xs_callout); 349 350 nextscb = scb->chain.tqe_next; 351 352 TAILQ_REMOVE(&sc->ready_list, scb, chain); 353 354 scb = nextscb; 355 356 goto start; 357 } 358 359 void 360 sc_done(scb) 361 struct sc_scb *scb; 362 { 363 struct scsipi_xfer *xs = scb->xs; 364 struct scsipi_periph *periph = xs->xs_periph; 365 struct sc_softc *sc = (void *)periph->periph_channel->chan_adapter->adapt_dev; 366 367 xs->resid = 0; 368 xs->status = 0; 369 370 if (scb->istatus != INST_EP) { 371 if (scb->istatus == (INST_EP|INST_TO)) 372 xs->error = XS_SELTIMEOUT; 373 else { 374 printf("SC(i): [istatus=0x%x, tstatus=0x%x]\n", 375 scb->istatus, scb->tstatus); 376 xs->error = XS_DRIVER_STUFFUP; 377 } 378 } 379 380 switch (scb->tstatus) { 381 382 case TGST_GOOD: 383 break; 384 385 case TGST_CC: 386 xs->status = SCSI_CHECK; 387 if (xs->error == 0) 388 xs->error = XS_BUSY; 389 390 default: 391 printf("SC(t): [istatus=0x%x, tstatus=0x%x]\n", 392 scb->istatus, scb->tstatus); 393 break; 394 } 395 396 scsipi_done(xs); 397 free_scb(sc, scb); 398 sc->inuse[periph->periph_target] = 0; 399 sc_sched(sc); 400 } 401 402 int 403 sc_intr(v) 404 void *v; 405 { 406 /* struct sc_softc *sc = v; */ 407 volatile u_char *gsp = (u_char *)DMAC_GSTAT; 408 u_int gstat = *gsp; 409 int mrqb, i; 410 411 if ((gstat & CH_INT(CH_SCSI)) == 0) 412 return 0; 413 414 /* 415 * when DMA interrupt occurs there remain some untransferred data. 416 * wait data transfer completion. 417 */ 418 mrqb = (gstat & CH_INT(CH_SCSI)) << 1; 419 if (gstat & mrqb) { 420 /* 421 * XXX SHOULD USE DELAY() 422 */ 423 for (i = 0; i < 50; i++) 424 ; 425 if (*gsp & mrqb) 426 printf("sc_intr: MRQ\n"); 427 } 428 scintr(); 429 430 return 1; 431 } 432 433 434 #if 0 435 /* 436 * SCOP_RSENSE request 437 */ 438 void 439 scop_rsense(intr, sc_param, lun, ie, count, param) 440 register int intr; 441 register struct scsi *sc_param; 442 register int lun; 443 register int ie; 444 register int count; 445 register caddr_t param; 446 { 447 bzero(sc_param, sizeof(struct scsi)); 448 sc_param->identify = MSG_IDENT | sc_disconnect | (lun & IDT_DRMASK); 449 sc_param->sc_lun = lun; 450 451 sc_param->sc_cpoint = (u_char *)param; 452 sc_param->sc_ctrnscnt = count; 453 454 /* sc_cdb */ 455 sc_param->sc_opcode = SCOP_RSENSE; 456 sc_param->sc_count = count; 457 458 sc_go(intr, sc_param, ie, sc_param); 459 } 460 #endif 461 462 void 463 cxd1185_timeout(arg) 464 void *arg; 465 { 466 struct sc_scb *scb = arg; 467 struct scsipi_xfer *xs = scb->xs; 468 struct scsipi_periph *periph = xs->xs_periph; 469 int chan; 470 471 chan = periph->periph_target; 472 473 printf("sc: timeout ch=%d\n", chan); 474 475 /* XXX abort transfer and ... */ 476 } 477