This source file includes following definitions.
- uhaprint
- uha_attach
- uha_reset_mscp
- uha_free_mscp
- uha_init_mscp
- uha_get_mscp
- uha_mscp_phys_kv
- uha_done
- uhaminphys
- uha_scsi_cmd
- uha_timeout
1
2
3
4 #undef UHADEBUG
5 #ifdef DDB
6 #define integrate
7 #else
8 #define integrate static inline
9 #endif
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 #include <sys/types.h>
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/errno.h>
67 #include <sys/ioctl.h>
68 #include <sys/device.h>
69 #include <sys/malloc.h>
70 #include <sys/buf.h>
71 #include <sys/proc.h>
72 #include <sys/user.h>
73
74 #include <machine/bus.h>
75 #include <machine/intr.h>
76
77 #include <scsi/scsi_all.h>
78 #include <scsi/scsiconf.h>
79
80 #include <dev/ic/uhareg.h>
81 #include <dev/ic/uhavar.h>
82
83 #ifndef DDB
84 #define Debugger() panic("should call debugger here (ultra14f.c)")
85 #endif
86
87 #define KVTOPHYS(x) vtophys((vaddr_t)x)
88
89 integrate void uha_reset_mscp(struct uha_softc *, struct uha_mscp *);
90 void uha_free_mscp(struct uha_softc *, struct uha_mscp *);
91 integrate void uha_init_mscp(struct uha_softc *, struct uha_mscp *);
92 struct uha_mscp *uha_get_mscp(struct uha_softc *, int);
93 void uhaminphys(struct buf *);
94 int uha_scsi_cmd(struct scsi_xfer *);
95
96 struct scsi_adapter uha_switch = {
97 uha_scsi_cmd,
98 uhaminphys,
99 0,
100 0,
101 };
102
103
104 struct scsi_device uha_dev = {
105 NULL,
106 NULL,
107 NULL,
108 NULL,
109 };
110
111 struct cfdriver uha_cd = {
112 NULL, "uha", DV_DULL
113 };
114
115 #define UHA_ABORT_TIMEOUT 2000
116
117 #ifdef __OpenBSD__
118 int uhaprint(void *, const char *);
119
120 int
121 uhaprint(aux, name)
122 void *aux;
123 const char *name;
124 {
125
126 if (name != NULL)
127 printf("%s: scsibus ", name);
128 return UNCONF;
129 }
130 #endif
131
132
133
134
135 void
136 uha_attach(sc)
137 struct uha_softc *sc;
138 {
139 struct scsibus_attach_args saa;
140
141 (sc->init)(sc);
142 TAILQ_INIT(&sc->sc_free_mscp);
143
144
145
146
147 sc->sc_link.adapter_softc = sc;
148 sc->sc_link.adapter_target = sc->sc_scsi_dev;
149 sc->sc_link.adapter = &uha_switch;
150 sc->sc_link.device = &uha_dev;
151 sc->sc_link.openings = 2;
152
153 bzero(&saa, sizeof(saa));
154 saa.saa_sc_link = &sc->sc_link;
155
156
157
158
159 config_found(&sc->sc_dev, &saa, uhaprint);
160 }
161
162 integrate void
163 uha_reset_mscp(sc, mscp)
164 struct uha_softc *sc;
165 struct uha_mscp *mscp;
166 {
167
168 mscp->flags = 0;
169 }
170
171
172
173
174 void
175 uha_free_mscp(sc, mscp)
176 struct uha_softc *sc;
177 struct uha_mscp *mscp;
178 {
179 int s;
180
181 s = splbio();
182
183 uha_reset_mscp(sc, mscp);
184 TAILQ_INSERT_HEAD(&sc->sc_free_mscp, mscp, chain);
185
186
187
188
189
190 if (TAILQ_NEXT(mscp, chain) == NULL)
191 wakeup(&sc->sc_free_mscp);
192
193 splx(s);
194 }
195
196 integrate void
197 uha_init_mscp(sc, mscp)
198 struct uha_softc *sc;
199 struct uha_mscp *mscp;
200 {
201 int hashnum;
202
203 bzero(mscp, sizeof(struct uha_mscp));
204
205
206
207
208 mscp->hashkey = KVTOPHYS(mscp);
209 hashnum = MSCP_HASH(mscp->hashkey);
210 mscp->nexthash = sc->sc_mscphash[hashnum];
211 sc->sc_mscphash[hashnum] = mscp;
212 uha_reset_mscp(sc, mscp);
213 }
214
215
216
217
218
219
220
221 struct uha_mscp *
222 uha_get_mscp(sc, flags)
223 struct uha_softc *sc;
224 int flags;
225 {
226 struct uha_mscp *mscp;
227 int s;
228
229 s = splbio();
230
231
232
233
234
235 for (;;) {
236 mscp = TAILQ_FIRST(&sc->sc_free_mscp);
237 if (mscp) {
238 TAILQ_REMOVE(&sc->sc_free_mscp, mscp, chain);
239 break;
240 }
241 if (sc->sc_nummscps < UHA_MSCP_MAX) {
242 mscp = (struct uha_mscp *) malloc(sizeof(struct uha_mscp),
243 M_TEMP, M_NOWAIT);
244 if (!mscp) {
245 printf("%s: can't malloc mscp\n",
246 sc->sc_dev.dv_xname);
247 goto out;
248 }
249 uha_init_mscp(sc, mscp);
250 sc->sc_nummscps++;
251 break;
252 }
253 if ((flags & SCSI_NOSLEEP) != 0)
254 goto out;
255 tsleep(&sc->sc_free_mscp, PRIBIO, "uhamsc", 0);
256 }
257
258 mscp->flags |= MSCP_ALLOC;
259
260 out:
261 splx(s);
262 return (mscp);
263 }
264
265
266
267
268 struct uha_mscp *
269 uha_mscp_phys_kv(sc, mscp_phys)
270 struct uha_softc *sc;
271 u_long mscp_phys;
272 {
273 int hashnum = MSCP_HASH(mscp_phys);
274 struct uha_mscp *mscp = sc->sc_mscphash[hashnum];
275
276 while (mscp) {
277 if (mscp->hashkey == mscp_phys)
278 break;
279 mscp = mscp->nexthash;
280 }
281 return (mscp);
282 }
283
284
285
286
287
288 void
289 uha_done(sc, mscp)
290 struct uha_softc *sc;
291 struct uha_mscp *mscp;
292 {
293 struct scsi_sense_data *s1, *s2;
294 struct scsi_xfer *xs = mscp->xs;
295
296 SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n"));
297
298
299
300
301 if ((mscp->flags & MSCP_ALLOC) == 0) {
302 printf("%s: exiting ccb not allocated!\n", sc->sc_dev.dv_xname);
303 Debugger();
304 return;
305 }
306 if (xs->error == XS_NOERROR) {
307 if (mscp->host_stat != UHA_NO_ERR) {
308 switch (mscp->host_stat) {
309 case UHA_SBUS_TIMEOUT:
310 xs->error = XS_SELTIMEOUT;
311 break;
312 default:
313 printf("%s: host_stat %x\n",
314 sc->sc_dev.dv_xname, mscp->host_stat);
315 xs->error = XS_DRIVER_STUFFUP;
316 }
317 } else if (mscp->target_stat != SCSI_OK) {
318 switch (mscp->target_stat) {
319 case SCSI_CHECK:
320 s1 = &mscp->mscp_sense;
321 s2 = &xs->sense;
322 *s2 = *s1;
323 xs->error = XS_SENSE;
324 break;
325 case SCSI_BUSY:
326 xs->error = XS_BUSY;
327 break;
328 default:
329 printf("%s: target_stat %x\n",
330 sc->sc_dev.dv_xname, mscp->target_stat);
331 xs->error = XS_DRIVER_STUFFUP;
332 }
333 } else
334 xs->resid = 0;
335 }
336 uha_free_mscp(sc, mscp);
337 xs->flags |= ITSDONE;
338 scsi_done(xs);
339 }
340
341 void
342 uhaminphys(bp)
343 struct buf *bp;
344 {
345
346 if (bp->b_bcount > ((UHA_NSEG - 1) << PGSHIFT))
347 bp->b_bcount = ((UHA_NSEG - 1) << PGSHIFT);
348 minphys(bp);
349 }
350
351
352
353
354
355 int
356 uha_scsi_cmd(xs)
357 struct scsi_xfer *xs;
358 {
359 struct scsi_link *sc_link = xs->sc_link;
360 struct uha_softc *sc = sc_link->adapter_softc;
361 struct uha_mscp *mscp;
362 struct uha_dma_seg *sg;
363 int seg;
364 u_long thiskv, thisphys, nextphys;
365 int bytes_this_seg, bytes_this_page, datalen, flags;
366 int s;
367
368 SC_DEBUG(sc_link, SDEV_DB2, ("uha_scsi_cmd\n"));
369
370
371
372
373
374 flags = xs->flags;
375 if ((mscp = uha_get_mscp(sc, flags)) == NULL) {
376 return (TRY_AGAIN_LATER);
377 }
378 mscp->xs = xs;
379 mscp->timeout = xs->timeout;
380 timeout_set(&xs->stimeout, uha_timeout, xs);
381
382
383
384
385 if (flags & SCSI_RESET) {
386 mscp->opcode = UHA_SDR;
387 mscp->ca = 0x01;
388 } else {
389 mscp->opcode = UHA_TSP;
390
391 mscp->ca = 0x01;
392 bcopy(xs->cmd, &mscp->scsi_cmd, mscp->scsi_cmd_length);
393 }
394 mscp->xdir = UHA_SDET;
395 mscp->dcn = 0x00;
396 mscp->chan = 0x00;
397 mscp->target = sc_link->target;
398 mscp->lun = sc_link->lun;
399 mscp->scsi_cmd_length = xs->cmdlen;
400 mscp->sense_ptr = KVTOPHYS(&mscp->mscp_sense);
401 mscp->req_sense_length = sizeof(mscp->mscp_sense);
402 mscp->host_stat = 0x00;
403 mscp->target_stat = 0x00;
404
405 if (xs->datalen) {
406 sg = mscp->uha_dma;
407 seg = 0;
408 #ifdef TFS
409 if (flags & SCSI_DATA_UIO) {
410 struct iovec *iovp;
411 iovp = ((struct uio *) xs->data)->uio_iov;
412 datalen = ((struct uio *) xs->data)->uio_iovcnt;
413 xs->datalen = 0;
414 while (datalen && seg < UHA_NSEG) {
415 sg->seg_addr = (physaddr)iovp->iov_base;
416 sg->seg_len = iovp->iov_len;
417 xs->datalen += iovp->iov_len;
418 SC_DEBUGN(sc_link, SDEV_DB4, ("(0x%x@0x%x)",
419 iovp->iov_len, iovp->iov_base));
420 sg++;
421 iovp++;
422 seg++;
423 datalen--;
424 }
425 } else
426 #endif
427 {
428
429
430
431 SC_DEBUG(sc_link, SDEV_DB4,
432 ("%d @0x%x:- ", xs->datalen, xs->data));
433 datalen = xs->datalen;
434 thiskv = (int) xs->data;
435 thisphys = KVTOPHYS(thiskv);
436
437 while (datalen && seg < UHA_NSEG) {
438 bytes_this_seg = 0;
439
440
441 sg->seg_addr = thisphys;
442
443 SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
444
445
446 nextphys = thisphys;
447 while (datalen && thisphys == nextphys) {
448
449
450
451
452
453
454 nextphys = (thisphys & ~PGOFSET) + NBPG;
455 bytes_this_page = nextphys - thisphys;
456
457 bytes_this_page = min(bytes_this_page,
458 datalen);
459 bytes_this_seg += bytes_this_page;
460 datalen -= bytes_this_page;
461
462
463 thiskv = (thiskv & ~PGOFSET) + NBPG;
464 if (datalen)
465 thisphys = KVTOPHYS(thiskv);
466 }
467
468
469
470 SC_DEBUGN(sc_link, SDEV_DB4,
471 ("(0x%x)", bytes_this_seg));
472 sg->seg_len = bytes_this_seg;
473 sg++;
474 seg++;
475 }
476 }
477
478 SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
479 if (datalen) {
480
481
482
483 printf("%s: uha_scsi_cmd, more than %d dma segs\n",
484 sc->sc_dev.dv_xname, UHA_NSEG);
485 goto bad;
486 }
487 mscp->data_addr = KVTOPHYS(mscp->uha_dma);
488 mscp->data_length = xs->datalen;
489 mscp->sgth = 0x01;
490 mscp->sg_num = seg;
491 } else {
492 mscp->data_addr = (physaddr)0;
493 mscp->data_length = 0;
494 mscp->sgth = 0x00;
495 mscp->sg_num = 0;
496 }
497 mscp->link_id = 0;
498 mscp->link_addr = (physaddr)0;
499
500 s = splbio();
501 (sc->start_mbox)(sc, mscp);
502 splx(s);
503
504
505
506
507 if ((flags & SCSI_POLL) == 0)
508 return (SUCCESSFULLY_QUEUED);
509
510
511
512
513 if ((sc->poll)(sc, xs, mscp->timeout)) {
514 uha_timeout(mscp);
515 if ((sc->poll)(sc, xs, mscp->timeout))
516 uha_timeout(mscp);
517 }
518 return (COMPLETE);
519
520 bad:
521 xs->error = XS_DRIVER_STUFFUP;
522 uha_free_mscp(sc, mscp);
523 return (COMPLETE);
524 }
525
526 void
527 uha_timeout(arg)
528 void *arg;
529 {
530 struct uha_mscp *mscp = arg;
531 struct scsi_xfer *xs = mscp->xs;
532 struct scsi_link *sc_link = xs->sc_link;
533 struct uha_softc *sc = sc_link->adapter_softc;
534 int s;
535
536 sc_print_addr(sc_link);
537 printf("timed out");
538
539 s = splbio();
540
541 if (mscp->flags & MSCP_ABORT) {
542
543 printf(" AGAIN\n");
544
545 } else {
546
547 printf("\n");
548 mscp->xs->error = XS_TIMEOUT;
549 mscp->timeout = UHA_ABORT_TIMEOUT;
550 mscp->flags |= MSCP_ABORT;
551 (sc->start_mbox)(sc, mscp);
552 }
553
554 splx(s);
555 }