Annotation of sys/dev/ic/aic79xx_openbsd.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: aic79xx_openbsd.c,v 1.26 2006/11/28 23:59:45 dlg Exp $ */
2:
3: /*
4: * Copyright (c) 2004 Milos Urbanek, Kenneth R. Westerback & Marco Peereboom
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
20: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: *
28: */
29:
30: /*
31: * Bus independent OpenBSD shim for the aic79xx based Adaptec SCSI controllers
32: *
33: * Copyright (c) 1994-2002 Justin T. Gibbs.
34: * Copyright (c) 2001-2002 Adaptec Inc.
35: * All rights reserved.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions, and the following disclaimer,
42: * without modification.
43: * 2. The name of the author may not be used to endorse or promote products
44: * derived from this software without specific prior written permission.
45: *
46: * Alternatively, this software may be distributed under the terms of the
47: * GNU Public License ("GPL").
48: *
49: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
53: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59: * SUCH DAMAGE.
60: *
61: */
62:
63: #include <sys/cdefs.h>
64: /*
65: __FBSDID("$FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.16 2003/12/17 00:02:09 gibbs Exp $");
66: */
67:
68: #include <dev/ic/aic79xx_openbsd.h>
69: #include <dev/ic/aic79xx_inline.h>
70: #include <dev/ic/aic79xx.h>
71:
72: #ifndef AHD_TMODE_ENABLE
73: #define AHD_TMODE_ENABLE 0
74: #endif
75:
76: /* XXX milos add ahd_ioctl */
77: int ahd_action(struct scsi_xfer *);
78: int ahd_execute_scb(void *, bus_dma_segment_t *, int);
79: int ahd_poll(struct ahd_softc *, int);
80: int ahd_setup_data(struct ahd_softc *, struct scsi_xfer *,
81: struct scb *);
82:
83: void ahd_adapter_req_set_xfer_mode(struct ahd_softc *, struct scb *);
84: void ahd_minphys(struct buf *);
85:
86: struct cfdriver ahd_cd = {
87: NULL, "ahd", DV_DULL
88: };
89:
90: static struct scsi_adapter ahd_switch =
91: {
92: ahd_action,
93: ahd_minphys,
94: 0,
95: 0,
96: };
97:
98: /* the below structure is so we have a default dev struct for our link struct */
99: static struct scsi_device ahd_dev =
100: {
101: NULL, /* Use default error handler */
102: NULL, /* have a queue, served by this */
103: NULL, /* have no async handler */
104: NULL, /* Use default 'done' routine */
105: };
106:
107: /*
108: * Attach all the sub-devices we can find
109: */
110: int
111: ahd_attach(struct ahd_softc *ahd)
112: {
113: struct scsibus_attach_args saa;
114: char ahd_info[256];
115: int s;
116:
117: ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
118: printf("%s\n", ahd_info);
119: ahd_lock(ahd, &s);
120:
121: /*
122: * fill in the prototype scsi_links.
123: */
124: ahd->sc_channel.adapter_target = ahd->our_id;
125: if (ahd->features & AHD_WIDE)
126: ahd->sc_channel.adapter_buswidth = 16;
127: ahd->sc_channel.adapter_softc = ahd;
128: ahd->sc_channel.adapter = &ahd_switch;
129: ahd->sc_channel.openings = 16;
130: ahd->sc_channel.device = &ahd_dev;
131:
132: if (bootverbose) {
133: ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
134: printf("%s: %s\n", ahd->sc_dev.dv_xname, ahd_info);
135: }
136:
137: ahd_intr_enable(ahd, TRUE);
138:
139: if (ahd->flags & AHD_RESET_BUS_A)
140: ahd_reset_channel(ahd, 'A', TRUE);
141:
142: bzero(&saa, sizeof(saa));
143: saa.saa_sc_link = &ahd->sc_channel;
144:
145: ahd->sc_child = config_found((void *)&ahd->sc_dev, &saa, scsiprint);
146:
147: ahd_unlock(ahd, &s);
148:
149: return (1);
150:
151: }
152:
153: /*
154: * Catch an interrupt from the adapter
155: */
156: int
157: ahd_platform_intr(void *arg)
158: {
159: struct ahd_softc *ahd;
160:
161: /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
162:
163: ahd = (struct ahd_softc *)arg;
164: return ahd_intr(ahd);
165: }
166:
167: /*
168: * We have an scb which has been processed by the
169: * adaptor, now we look to see how the operation
170: * went.
171: */
172: void
173: ahd_done(struct ahd_softc *ahd, struct scb *scb)
174: {
175: struct scsi_xfer *xs = scb->xs;
176: int s;
177:
178: /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
179:
180: LIST_REMOVE(scb, pending_links);
181:
182: timeout_del(&xs->stimeout);
183:
184: if (xs->datalen) {
185: int op;
186:
187: if ((xs->flags & SCSI_DATA_IN) != 0)
188: op = BUS_DMASYNC_POSTREAD;
189: else
190: op = BUS_DMASYNC_POSTWRITE;
191: bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
192: scb->dmamap->dm_mapsize, op);
193: bus_dmamap_unload(ahd->parent_dmat, scb->dmamap);
194: }
195:
196: /* Translate the CAM status code to a SCSI error code. */
197: switch (xs->error) {
198: case CAM_SCSI_STATUS_ERROR:
199: case CAM_REQ_INPROG:
200: case CAM_REQ_CMP:
201: switch (xs->status) {
202: case SCSI_TASKSET_FULL:
203: /* SCSI Layer won't requeue, so we force infinite
204: * retries until queue space is available. XS_BUSY
205: * is dangerous because if the NOSLEEP flag is set
206: * it can cause the I/O to return EIO. XS_BUSY code
207: * falls through to XS_TIMEOUT anyway.
208: */
209: xs->error = XS_TIMEOUT;
210: xs->retries++;
211: break;
212: case SCSI_BUSY:
213: xs->error = XS_BUSY;
214: break;
215: case SCSI_CHECK:
216: case SCSI_TERMINATED:
217: if ((scb->flags & SCB_SENSE) == 0) {
218: /* CHECK on CHECK? */
219: xs->error = XS_DRIVER_STUFFUP;
220: } else
221: xs->error = XS_NOERROR;
222: break;
223: default:
224: xs->error = XS_NOERROR;
225: break;
226: }
227: break;
228: case CAM_BUSY:
229: xs->error = XS_BUSY;
230: break;
231: case CAM_CMD_TIMEOUT:
232: xs->error = XS_TIMEOUT;
233: break;
234: case CAM_BDR_SENT:
235: case CAM_SCSI_BUS_RESET:
236: xs->error = XS_RESET;
237: break;
238: case CAM_REQUEUE_REQ:
239: xs->error = XS_TIMEOUT;
240: xs->retries++;
241: break;
242: case CAM_SEL_TIMEOUT:
243: xs->error = XS_SELTIMEOUT;
244: break;
245: default:
246: xs->error = XS_DRIVER_STUFFUP;
247: break;
248: }
249:
250: if (xs->error != XS_NOERROR) {
251: /* Don't clobber any existing error state */
252: } else if ((scb->flags & SCB_SENSE) != 0) {
253: /*
254: * We performed autosense retrieval.
255: *
256: * Zero any sense not transferred by the
257: * device. The SCSI spec mandates that any
258: * untransfered data should be assumed to be
259: * zero. Complete the 'bounce' of sense information
260: * through buffers accessible via bus-space by
261: * copying it into the clients csio.
262: */
263: memset(&xs->sense, 0, sizeof(struct scsi_sense_data));
264: memcpy(&xs->sense, ahd_get_sense_buf(ahd, scb),
265: sizeof(struct scsi_sense_data));
266: xs->error = XS_SENSE;
267: } else if ((scb->flags & SCB_PKT_SENSE) != 0) {
268: struct scsi_status_iu_header *siu;
269: u_int32_t len;
270:
271: siu = (struct scsi_status_iu_header *)scb->sense_data;
272: len = SIU_SENSE_LENGTH(siu);
273: memset(&xs->sense, 0, sizeof(xs->sense));
274: memcpy(&xs->sense, SIU_SENSE_DATA(siu),
275: ulmin(len, sizeof(xs->sense)));
276: xs->error = XS_SENSE;
277: }
278:
279: ahd_lock(ahd, &s);
280: ahd_free_scb(ahd, scb);
281: ahd_unlock(ahd, &s);
282:
283: xs->flags |= ITSDONE;
284: scsi_done(xs);
285: }
286:
287: void
288: ahd_minphys(struct buf *bp)
289: {
290: /*
291: * Even though the card can transfer up to 16megs per command
292: * we are limited by the number of segments in the dma segment
293: * list that we can hold. The worst case is that all pages are
294: * discontinuous physically, hence the "page per segment" limit
295: * enforced here.
296: */
297: if (bp->b_bcount > ((AHD_NSEG - 1) * PAGE_SIZE)) {
298: bp->b_bcount = ((AHD_NSEG - 1) * PAGE_SIZE);
299: }
300: minphys(bp);
301: }
302:
303: int32_t
304: ahd_action(struct scsi_xfer *xs)
305: {
306: struct ahd_softc *ahd;
307: struct scb *scb;
308: struct hardware_scb *hscb;
309: u_int target_id;
310: u_int our_id;
311: int s;
312: int dontqueue = 0;
313: struct ahd_initiator_tinfo *tinfo;
314: struct ahd_tmode_tstate *tstate;
315: u_int col_idx;
316: u_int16_t quirks;
317:
318: SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahd_action\n"));
319: ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
320:
321: /* determine safety of software queueing */
322: dontqueue = xs->flags & SCSI_POLL;
323:
324: target_id = xs->sc_link->target;
325: our_id = SCSI_SCSI_ID(ahd, xs->sc_link);
326:
327: if ((ahd->flags & AHD_INITIATORROLE) == 0) {
328: xs->error = XS_DRIVER_STUFFUP;
329: xs->flags |= ITSDONE;
330: scsi_done(xs);
331: return (COMPLETE);
332: /* return ccb->ccb_h.status = CAM_PROVIDE_FAIL; */
333: }
334: /*
335: * get an scb to use.
336: */
337: ahd_lock(ahd, &s);
338: tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
339:
340: quirks = xs->sc_link->quirks;
341:
342: if ((quirks & SDEV_NOTAGS) != 0 ||
343: (tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0)
344: col_idx = AHD_NEVER_COL_IDX;
345: else
346: col_idx = AHD_BUILD_COL_IDX(target_id, xs->sc_link->lun);
347:
348: if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
349: ahd->flags |= AHD_RESOURCE_SHORTAGE;
350: ahd_unlock(ahd, &s);
351: return (TRY_AGAIN_LATER);
352: }
353: ahd_unlock(ahd, &s);
354:
355: hscb = scb->hscb;
356:
357: SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
358:
359: scb->xs = xs;
360: timeout_set(&xs->stimeout, ahd_timeout, scb);
361:
362: /*
363: * Put all the arguments for the xfer in the scb
364: */
365: hscb->control = 0;
366: hscb->scsiid = BUILD_SCSIID(ahd, xs->sc_link, target_id, our_id);
367: hscb->lun = xs->sc_link->lun;
368: if (xs->xs_control & XS_CTL_RESET) {
369: hscb->cdb_len = 0;
370: scb->flags |= SCB_DEVICE_RESET;
371: hscb->control |= MK_MESSAGE;
372: hscb->task_management = SIU_TASKMGMT_LUN_RESET;
373: return (ahd_execute_scb(scb, NULL, 0));
374: } else {
375: hscb->task_management = 0;
376: return (ahd_setup_data(ahd, xs, scb));
377: }
378: }
379:
380: int
381: ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
382: {
383: struct scb *scb;
384: struct scsi_xfer *xs;
385: struct ahd_softc *ahd;
386: struct ahd_initiator_tinfo *tinfo;
387: struct ahd_tmode_tstate *tstate;
388: u_int mask;
389: int s;
390:
391: scb = (struct scb *)arg;
392: xs = scb->xs;
393: xs->error = CAM_REQ_INPROG;
394: xs->status = 0;
395: ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
396:
397: if (nsegments != 0) {
398: void *sg;
399: int op;
400: u_int i;
401:
402: ahd_setup_data_scb(ahd, scb);
403:
404: /* Copy the segments into our SG list */
405: for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
406:
407: sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
408: dm_segs->ds_len,
409: /*last*/i == 1);
410: dm_segs++;
411: }
412:
413: if ((xs->flags & SCSI_DATA_IN) != 0)
414: op = BUS_DMASYNC_PREREAD;
415: else
416: op = BUS_DMASYNC_PREWRITE;
417:
418: bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
419: scb->dmamap->dm_mapsize, op);
420:
421: }
422:
423: ahd_lock(ahd, &s);
424:
425: /*
426: * Last time we need to check if this SCB needs to
427: * be aborted.
428: */
429: if (xs->flags & ITSDONE) {
430: if (nsegments != 0)
431: bus_dmamap_unload(ahd->parent_dmat,
432: scb->dmamap);
433: ahd_free_scb(ahd, scb);
434: ahd_unlock(ahd, &s);
435: return (COMPLETE);
436: }
437:
438: tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
439: SCSIID_OUR_ID(scb->hscb->scsiid),
440: SCSIID_TARGET(ahd, scb->hscb->scsiid),
441: &tstate);
442:
443: mask = SCB_GET_TARGET_MASK(ahd, scb);
444:
445: if ((tstate->discenable & mask) != 0)
446: scb->hscb->control |= DISCENB;
447:
448: if ((tstate->tagenable & mask) != 0)
449: scb->hscb->control |= TAG_ENB;
450:
451: if ((tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0) {
452: scb->flags |= SCB_PACKETIZED;
453: if (scb->hscb->task_management != 0)
454: scb->hscb->control &= ~MK_MESSAGE;
455: }
456:
457: if ((tstate->auto_negotiate & mask) != 0) {
458: scb->flags |= SCB_AUTO_NEGOTIATE;
459: scb->hscb->control |= MK_MESSAGE;
460: }
461:
462: /* XXX with ahc there was some bus_dmamap_sync(PREREAD|PREWRITE); */
463:
464: LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
465:
466: if (!(xs->flags & SCSI_POLL))
467: timeout_add(&xs->stimeout, (xs->timeout * hz) / 1000);
468:
469: scb->flags |= SCB_ACTIVE;
470:
471: if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
472: /* Define a mapping from our tag to the SCB. */
473: ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
474: ahd_pause(ahd);
475: ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
476: ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
477: ahd_unpause(ahd);
478: } else {
479: ahd_queue_scb(ahd, scb);
480: }
481:
482: if (!(xs->flags & SCSI_POLL)) {
483: int target = xs->sc_link->target;
484: int lun = SCB_GET_LUN(scb);
485:
486: if (ahd->inited_target[target] == 0) {
487: struct ahd_devinfo devinfo;
488:
489: ahd_adapter_req_set_xfer_mode(ahd, scb);
490: ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
491: 'A', /*XXX milos*/ROLE_UNKNOWN);
492: ahd_scb_devinfo(ahd, &devinfo, scb);
493: ahd_update_neg_request(ahd, &devinfo, tstate, tinfo,
494: AHD_NEG_IF_NON_ASYNC);
495: ahd->inited_target[target] = 1;
496: }
497:
498: ahd_unlock(ahd, &s);
499: return (SUCCESSFULLY_QUEUED);
500: }
501:
502: /*
503: * If we can't use interrupts, poll for completion
504: */
505: SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
506:
507: do {
508: if (ahd_poll(ahd, xs->timeout)) {
509: if (!(xs->flags & SCSI_SILENT))
510: printf("cmd fail\n");
511: ahd_timeout(scb);
512: break;
513: }
514: } while (!(xs->flags & ITSDONE));
515:
516: ahd_unlock(ahd, &s);
517: return (COMPLETE);
518: }
519:
520: int
521: ahd_poll(struct ahd_softc *ahd, int wait)
522: {
523: while (--wait) {
524: DELAY(1000);
525: if (ahd_inb(ahd, INTSTAT) & INT_PEND)
526: break;
527: }
528:
529: if (wait == 0) {
530: printf("%s: board is not responding\n", ahd_name(ahd));
531: return (EIO);
532: }
533:
534: ahd_intr((void *)ahd);
535: return (0);
536: }
537:
538: int
539: ahd_setup_data(struct ahd_softc *ahd, struct scsi_xfer *xs,
540: struct scb *scb)
541: {
542: struct hardware_scb *hscb;
543: int s;
544:
545: hscb = scb->hscb;
546: xs->resid = xs->status = 0;
547: xs->error = CAM_REQ_INPROG;
548:
549: hscb->cdb_len = xs->cmdlen;
550: if (hscb->cdb_len > MAX_CDB_LEN) {
551: ahd_lock(ahd, &s);
552: ahd_free_scb(ahd, scb);
553: ahd_unlock(ahd, &s);
554: xs->error = XS_DRIVER_STUFFUP;
555: xs->flags |= ITSDONE;
556: scsi_done(xs);
557: return (COMPLETE);
558: }
559:
560: memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len);
561:
562: /* Only use S/G if there is a transfer */
563: if (xs->datalen) {
564: int error;
565:
566: error = bus_dmamap_load(ahd->parent_dmat,
567: scb->dmamap, xs->data,
568: xs->datalen, NULL,
569: ((xs->flags & SCSI_NOSLEEP) ?
570: BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
571: BUS_DMA_STREAMING |
572: ((xs->flags & XS_CTL_DATA_IN) ?
573: BUS_DMA_READ : BUS_DMA_WRITE));
574: if (error) {
575: #ifdef AHD_DEBUG
576: printf("%s: in ahd_setup_data(): bus_dmamap_load() "
577: "= %d\n", ahd_name(ahd), error);
578: #endif
579: ahd_lock(ahd, &s);
580: ahd_free_scb(ahd, scb);
581: ahd_unlock(ahd, &s);
582: return (TRY_AGAIN_LATER); /* XXX fvdl */
583: }
584: error = ahd_execute_scb(scb, scb->dmamap->dm_segs,
585: scb->dmamap->dm_nsegs);
586: return error;
587: } else {
588: return ahd_execute_scb(scb, NULL, 0);
589: }
590: }
591:
592: void
593: ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
594: ahd_queue_alg alg)
595: {
596: struct ahd_tmode_tstate *tstate;
597:
598: ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
599: devinfo->target, &tstate);
600:
601: if (alg != AHD_QUEUE_NONE)
602: tstate->tagenable |= devinfo->target_mask;
603: else
604: tstate->tagenable &= ~devinfo->target_mask;
605: }
606:
607: int
608: ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
609: {
610: if (sizeof(struct ahd_platform_data) > 0) {
611: ahd->platform_data = malloc(sizeof(struct ahd_platform_data),
612: M_DEVBUF, M_NOWAIT);
613: if (ahd->platform_data == NULL)
614: return (ENOMEM);
615: bzero(ahd->platform_data, sizeof(struct ahd_platform_data));
616: }
617:
618: return (0);
619: }
620:
621: void
622: ahd_platform_free(struct ahd_softc *ahd)
623: {
624: if (sizeof(struct ahd_platform_data) > 0)
625: free(ahd->platform_data, M_DEVBUF);
626: }
627:
628: int
629: ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
630: {
631: /* We don't sort softcs under OpenBSD so report equal always */
632: return (0);
633: }
634:
635: int
636: ahd_detach(struct device *self, int flags)
637: {
638: int rv = 0;
639:
640: struct ahd_softc *ahd = (struct ahd_softc*)self;
641:
642: if (ahd->sc_child != NULL)
643: rv = config_detach((void *)ahd->sc_child, flags);
644:
645: if (ahd->shutdown_hook != NULL)
646: shutdownhook_disestablish(ahd->shutdown_hook);
647:
648: ahd_free(ahd);
649:
650: return rv;
651: }
652:
653: void
654: ahd_adapter_req_set_xfer_mode(struct ahd_softc *ahd, struct scb *scb)
655: {
656: struct ahd_initiator_tinfo *tinfo;
657: struct ahd_tmode_tstate *tstate;
658: int target_id, our_id;
659: struct ahd_devinfo devinfo;
660: u_int16_t quirks;
661: u_int width, ppr_options, period, offset;
662: int s;
663:
664: target_id = scb->xs->sc_link->target;
665: our_id = SCSI_SCSI_ID(ahd, scb->xs->sc_link);
666:
667: s = splbio();
668:
669: quirks = scb->xs->sc_link->quirks;
670: tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
671: ahd_compile_devinfo(&devinfo, our_id, target_id, 0, 'A',
672: ROLE_INITIATOR);
673:
674: tstate->discenable |= (ahd->user_discenable & devinfo.target_mask);
675:
676: if (quirks & SDEV_NOTAGS)
677: tstate->tagenable &= ~devinfo.target_mask;
678: else if (ahd->user_tagenable & devinfo.target_mask)
679: tstate->tagenable |= devinfo.target_mask;
680:
681: if (quirks & SDEV_NOWIDE)
682: width = MSG_EXT_WDTR_BUS_8_BIT;
683: else
684: width = MSG_EXT_WDTR_BUS_16_BIT;
685:
686: ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
687: if (width > tinfo->user.width)
688: width = tinfo->user.width;
689: ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
690:
691: if (quirks & SDEV_NOSYNC) {
692: period = 0;
693: offset = 0;
694: } else {
695: period = tinfo->user.period;
696: offset = tinfo->user.offset;
697: }
698:
699: /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */
700: ppr_options = tinfo->user.ppr_options;
701: /* XXX Other reasons to avoid ppr? XXX */
702: if (width < MSG_EXT_WDTR_BUS_16_BIT)
703: ppr_options = 0;
704:
705: if ((tstate->discenable & devinfo.target_mask) == 0 ||
706: (tstate->tagenable & devinfo.target_mask) == 0)
707: ppr_options &= ~MSG_EXT_PPR_PROT_IUS;
708:
709: ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
710: ahd_validate_offset(ahd, NULL, period, &offset, width, ROLE_UNKNOWN);
711:
712: if (offset == 0) {
713: period = 0;
714: ppr_options = 0;
715: }
716:
717: if (ppr_options != 0 && tinfo->user.transport_version >= 3) {
718: tinfo->goal.transport_version = tinfo->user.transport_version;
719: tinfo->curr.transport_version = tinfo->user.transport_version;
720: }
721:
722: ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
723: AHD_TRANS_GOAL, FALSE);
724:
725: splx(s);
726: }
727:
728: void
729: aic_timer_reset(aic_timer_t *timer, u_int msec, ahd_callback_t *func,
730: void *arg)
731: {
732: uint64_t ticks;
733:
734: ticks = msec;
735: ticks *= hz;
736: ticks /= 1000;
737: callout_reset(timer, ticks, func, arg);
738: }
739:
740: void
741: aic_scb_timer_reset(struct scb *scb, u_int msec)
742: {
743: uint64_t ticks;
744:
745: ticks = msec;
746: ticks *= hz;
747: ticks /= 1000;
748: if (!(scb->xs->xs_control & XS_CTL_POLL))
749: callout_reset(&scb->xs->xs_callout, ticks, ahd_timeout, scb);
750: }
751:
752: void
753: ahd_flush_device_writes(struct ahd_softc *ahd)
754: {
755: /* XXX Is this sufficient for all architectures??? */
756: ahd_inb(ahd, INTSTAT);
757: }
758:
759: void
760: aic_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
761: {
762: int s;
763:
764: ahd_lock(ahd, &s);
765:
766: if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0) {
767: ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
768: }
769:
770: if (!cold) {
771: /* we are no longer in autoconf */
772: timeout_del(&scb->xs->stimeout);
773: }
774:
775: ahd_unlock(ahd, &s);
776: }
777:
778: void
779: ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
780: {
781: sc_print_addr(scb->xs->sc_link);
782: }
783:
784: void
785: ahd_platform_dump_card_state(struct ahd_softc *ahd)
786: {
787: /* Nothing to do here for OpenBSD */
788: printf("FEATURES = 0x%x, FLAGS = 0x%x, CHIP = 0x%x BUGS =0x%x\n",
789: ahd->features, ahd->flags, ahd->chip, ahd->bugs);
790: }
791:
792: void
793: ahd_platform_flushwork(struct ahd_softc *ahd)
794: {
795: }
CVSweb