Line data Source code
1 : /* $OpenBSD: aic79xx_openbsd.c,v 1.46 2017/12/12 12:33:36 krw 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 <dev/ic/aic79xx_openbsd.h>
64 : #include <dev/ic/aic79xx_inline.h>
65 : #include <dev/ic/aic79xx.h>
66 :
67 : #ifndef AHD_TMODE_ENABLE
68 : #define AHD_TMODE_ENABLE 0
69 : #endif
70 :
71 : /* XXX milos add ahd_ioctl */
72 : void ahd_action(struct scsi_xfer *);
73 : void ahd_execute_scb(void *, bus_dma_segment_t *, int);
74 : int ahd_poll(struct ahd_softc *, int);
75 : void ahd_setup_data(struct ahd_softc *, struct scsi_xfer *,
76 : struct scb *);
77 :
78 : void ahd_adapter_req_set_xfer_mode(struct ahd_softc *, struct scb *);
79 : void ahd_minphys(struct buf *, struct scsi_link *);
80 :
81 : struct cfdriver ahd_cd = {
82 : NULL, "ahd", DV_DULL
83 : };
84 :
85 : static struct scsi_adapter ahd_switch =
86 : {
87 : ahd_action,
88 : ahd_minphys,
89 : 0,
90 : 0,
91 : };
92 :
93 : /*
94 : * Attach all the sub-devices we can find
95 : */
96 : int
97 0 : ahd_attach(struct ahd_softc *ahd)
98 : {
99 0 : struct scsibus_attach_args saa;
100 0 : char ahd_info[256];
101 : int s;
102 :
103 0 : ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
104 0 : printf("%s\n", ahd_info);
105 0 : ahd_lock(ahd, &s);
106 :
107 : /*
108 : * fill in the prototype scsi_links.
109 : */
110 0 : ahd->sc_channel.adapter_target = ahd->our_id;
111 0 : if (ahd->features & AHD_WIDE)
112 0 : ahd->sc_channel.adapter_buswidth = 16;
113 0 : ahd->sc_channel.adapter_softc = ahd;
114 0 : ahd->sc_channel.adapter = &ahd_switch;
115 0 : ahd->sc_channel.openings = 16; /* Must ALWAYS be < 256!! */
116 0 : ahd->sc_channel.pool = &ahd->sc_iopool;
117 :
118 : if (bootverbose) {
119 : ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
120 : printf("%s: %s\n", ahd->sc_dev.dv_xname, ahd_info);
121 : }
122 :
123 0 : ahd_intr_enable(ahd, TRUE);
124 :
125 0 : if (ahd->flags & AHD_RESET_BUS_A)
126 0 : ahd_reset_channel(ahd, 'A', TRUE);
127 :
128 0 : bzero(&saa, sizeof(saa));
129 0 : saa.saa_sc_link = &ahd->sc_channel;
130 :
131 0 : ahd->sc_child = config_found((void *)&ahd->sc_dev, &saa, scsiprint);
132 :
133 0 : ahd_unlock(ahd, &s);
134 :
135 0 : return (1);
136 :
137 0 : }
138 :
139 : /*
140 : * Catch an interrupt from the adapter
141 : */
142 : int
143 0 : ahd_platform_intr(void *arg)
144 : {
145 : struct ahd_softc *ahd;
146 :
147 : /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
148 :
149 0 : ahd = (struct ahd_softc *)arg;
150 0 : return ahd_intr(ahd);
151 : }
152 :
153 : /*
154 : * We have an scb which has been processed by the
155 : * adaptor, now we look to see how the operation
156 : * went.
157 : */
158 : void
159 0 : ahd_done(struct ahd_softc *ahd, struct scb *scb)
160 : {
161 0 : struct scsi_xfer *xs = scb->xs;
162 :
163 : /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
164 :
165 0 : TAILQ_REMOVE(&ahd->pending_scbs, scb, next);
166 :
167 0 : timeout_del(&xs->stimeout);
168 :
169 0 : if (xs->datalen) {
170 : int op;
171 :
172 0 : if ((xs->flags & SCSI_DATA_IN) != 0)
173 0 : op = BUS_DMASYNC_POSTREAD;
174 : else
175 : op = BUS_DMASYNC_POSTWRITE;
176 0 : bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
177 : scb->dmamap->dm_mapsize, op);
178 0 : bus_dmamap_unload(ahd->parent_dmat, scb->dmamap);
179 0 : }
180 :
181 : /* Translate the CAM status code to a SCSI error code. */
182 0 : switch (xs->error) {
183 : case CAM_SCSI_STATUS_ERROR:
184 : case CAM_REQ_INPROG:
185 : case CAM_REQ_CMP:
186 0 : switch (xs->status) {
187 : case SCSI_TASKSET_FULL:
188 : case SCSI_BUSY:
189 0 : xs->error = XS_BUSY;
190 0 : break;
191 : case SCSI_CHECK:
192 : case SCSI_TERMINATED:
193 0 : if ((scb->flags & SCB_SENSE) == 0) {
194 : /* CHECK on CHECK? */
195 0 : xs->error = XS_DRIVER_STUFFUP;
196 0 : } else
197 0 : xs->error = XS_NOERROR;
198 : break;
199 : default:
200 0 : xs->error = XS_NOERROR;
201 0 : break;
202 : }
203 : break;
204 : case CAM_BUSY:
205 : case CAM_REQUEUE_REQ:
206 0 : xs->error = XS_BUSY;
207 0 : break;
208 : case CAM_CMD_TIMEOUT:
209 0 : xs->error = XS_TIMEOUT;
210 0 : break;
211 : case CAM_BDR_SENT:
212 : case CAM_SCSI_BUS_RESET:
213 0 : xs->error = XS_RESET;
214 0 : break;
215 : case CAM_SEL_TIMEOUT:
216 0 : xs->error = XS_SELTIMEOUT;
217 0 : break;
218 : default:
219 0 : xs->error = XS_DRIVER_STUFFUP;
220 0 : break;
221 : }
222 :
223 0 : if (xs->error != XS_NOERROR) {
224 : /* Don't clobber any existing error state */
225 0 : } else if ((scb->flags & SCB_SENSE) != 0) {
226 : /*
227 : * We performed autosense retrieval.
228 : *
229 : * Zero any sense not transferred by the
230 : * device. The SCSI spec mandates that any
231 : * untransferred data should be assumed to be
232 : * zero. Complete the 'bounce' of sense information
233 : * through buffers accessible via bus-space by
234 : * copying it into the clients csio.
235 : */
236 0 : memset(&xs->sense, 0, sizeof(struct scsi_sense_data));
237 0 : memcpy(&xs->sense, ahd_get_sense_buf(ahd, scb),
238 : sizeof(struct scsi_sense_data));
239 0 : xs->error = XS_SENSE;
240 0 : } else if ((scb->flags & SCB_PKT_SENSE) != 0) {
241 : struct scsi_status_iu_header *siu;
242 : u_int32_t len;
243 :
244 0 : siu = (struct scsi_status_iu_header *)scb->sense_data;
245 0 : len = SIU_SENSE_LENGTH(siu);
246 0 : memset(&xs->sense, 0, sizeof(xs->sense));
247 0 : memcpy(&xs->sense, SIU_SENSE_DATA(siu),
248 : ulmin(len, sizeof(xs->sense)));
249 0 : xs->error = XS_SENSE;
250 0 : }
251 :
252 0 : scsi_done(xs);
253 0 : }
254 :
255 : void
256 0 : ahd_minphys(struct buf *bp, struct scsi_link *sl)
257 : {
258 : /*
259 : * Even though the card can transfer up to 16megs per command
260 : * we are limited by the number of segments in the dma segment
261 : * list that we can hold. The worst case is that all pages are
262 : * discontinuous physically, hence the "page per segment" limit
263 : * enforced here.
264 : */
265 0 : if (bp->b_bcount > ((AHD_NSEG - 1) * PAGE_SIZE)) {
266 0 : bp->b_bcount = ((AHD_NSEG - 1) * PAGE_SIZE);
267 0 : }
268 0 : minphys(bp);
269 0 : }
270 :
271 : void
272 0 : ahd_action(struct scsi_xfer *xs)
273 : {
274 : struct ahd_softc *ahd;
275 : struct scb *scb;
276 : struct hardware_scb *hscb;
277 : u_int target_id;
278 : u_int our_id;
279 : int s;
280 : struct ahd_initiator_tinfo *tinfo;
281 0 : struct ahd_tmode_tstate *tstate;
282 : u_int16_t quirks;
283 :
284 : SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahd_action\n"));
285 0 : ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
286 :
287 0 : target_id = xs->sc_link->target;
288 0 : our_id = SCSI_SCSI_ID(ahd, xs->sc_link);
289 :
290 0 : ahd_lock(ahd, &s);
291 0 : if ((ahd->flags & AHD_INITIATORROLE) == 0) {
292 0 : xs->error = XS_DRIVER_STUFFUP;
293 0 : scsi_done(xs);
294 0 : ahd_unlock(ahd, &s);
295 0 : return;
296 : }
297 : /*
298 : * get an scb to use.
299 : */
300 0 : tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
301 :
302 0 : quirks = xs->sc_link->quirks;
303 :
304 0 : ahd_unlock(ahd, &s);
305 :
306 0 : scb = xs->io;
307 0 : hscb = scb->hscb;
308 0 : scb->flags = SCB_FLAG_NONE;
309 0 : scb->hscb->control = 0;
310 0 : ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL;
311 :
312 : SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
313 :
314 0 : scb->xs = xs;
315 0 : timeout_set(&xs->stimeout, ahd_timeout, scb);
316 :
317 : /*
318 : * Put all the arguments for the xfer in the scb
319 : */
320 0 : hscb->control = 0;
321 0 : hscb->scsiid = BUILD_SCSIID(ahd, xs->sc_link, target_id, our_id);
322 0 : hscb->lun = xs->sc_link->lun;
323 0 : if (xs->xs_control & XS_CTL_RESET) {
324 0 : hscb->cdb_len = 0;
325 0 : scb->flags |= SCB_DEVICE_RESET;
326 0 : hscb->control |= MK_MESSAGE;
327 0 : hscb->task_management = SIU_TASKMGMT_LUN_RESET;
328 0 : ahd_execute_scb(scb, NULL, 0);
329 0 : } else {
330 0 : hscb->task_management = 0;
331 0 : ahd_setup_data(ahd, xs, scb);
332 : }
333 0 : }
334 :
335 : void
336 0 : ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
337 : {
338 : struct scb *scb;
339 : struct scsi_xfer *xs;
340 : struct ahd_softc *ahd;
341 : struct ahd_initiator_tinfo *tinfo;
342 0 : struct ahd_tmode_tstate *tstate;
343 : u_int mask;
344 : int s;
345 :
346 0 : scb = (struct scb *)arg;
347 0 : xs = scb->xs;
348 0 : xs->error = CAM_REQ_INPROG;
349 0 : xs->status = 0;
350 0 : ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
351 :
352 0 : if (nsegments != 0) {
353 : void *sg;
354 : int op;
355 : u_int i;
356 :
357 0 : ahd_setup_data_scb(ahd, scb);
358 :
359 : /* Copy the segments into our SG list */
360 0 : for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
361 :
362 0 : sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
363 0 : dm_segs->ds_len,
364 0 : /*last*/i == 1);
365 0 : dm_segs++;
366 : }
367 :
368 0 : if ((xs->flags & SCSI_DATA_IN) != 0)
369 0 : op = BUS_DMASYNC_PREREAD;
370 : else
371 : op = BUS_DMASYNC_PREWRITE;
372 :
373 0 : bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
374 : scb->dmamap->dm_mapsize, op);
375 :
376 0 : }
377 :
378 0 : ahd_lock(ahd, &s);
379 :
380 : /*
381 : * Last time we need to check if this SCB needs to
382 : * be aborted.
383 : */
384 0 : if (xs->flags & ITSDONE) {
385 0 : if (nsegments != 0)
386 0 : bus_dmamap_unload(ahd->parent_dmat,
387 : scb->dmamap);
388 0 : ahd_unlock(ahd, &s);
389 0 : return;
390 : }
391 :
392 0 : tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
393 0 : SCSIID_OUR_ID(scb->hscb->scsiid),
394 0 : SCSIID_TARGET(ahd, scb->hscb->scsiid),
395 : &tstate);
396 :
397 0 : mask = SCB_GET_TARGET_MASK(ahd, scb);
398 :
399 0 : if ((tstate->discenable & mask) != 0)
400 0 : scb->hscb->control |= DISCENB;
401 :
402 0 : if ((tstate->tagenable & mask) != 0)
403 0 : scb->hscb->control |= TAG_ENB;
404 :
405 0 : if ((tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0) {
406 0 : scb->flags |= SCB_PACKETIZED;
407 0 : if (scb->hscb->task_management != 0)
408 0 : scb->hscb->control &= ~MK_MESSAGE;
409 : }
410 :
411 0 : if ((tstate->auto_negotiate & mask) != 0) {
412 0 : scb->flags |= SCB_AUTO_NEGOTIATE;
413 0 : scb->hscb->control |= MK_MESSAGE;
414 0 : }
415 :
416 : /* XXX with ahc there was some bus_dmamap_sync(PREREAD|PREWRITE); */
417 :
418 0 : TAILQ_INSERT_HEAD(&ahd->pending_scbs, scb, next);
419 :
420 0 : if (!(xs->flags & SCSI_POLL))
421 0 : timeout_add_msec(&xs->stimeout, xs->timeout);
422 :
423 0 : scb->flags |= SCB_ACTIVE;
424 :
425 0 : if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
426 : /* Define a mapping from our tag to the SCB. */
427 0 : ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
428 0 : ahd_pause(ahd);
429 0 : ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
430 0 : ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
431 0 : ahd_unpause(ahd);
432 0 : } else {
433 0 : ahd_queue_scb(ahd, scb);
434 : }
435 :
436 0 : if (!(xs->flags & SCSI_POLL)) {
437 0 : int target = xs->sc_link->target;
438 0 : int lun = SCB_GET_LUN(scb);
439 :
440 0 : if (ahd->inited_target[target] == 0) {
441 0 : struct ahd_devinfo devinfo;
442 :
443 0 : ahd_adapter_req_set_xfer_mode(ahd, scb);
444 0 : ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
445 : 'A', /*XXX milos*/ROLE_UNKNOWN);
446 0 : ahd_scb_devinfo(ahd, &devinfo, scb);
447 0 : ahd_update_neg_request(ahd, &devinfo, tstate, tinfo,
448 : AHD_NEG_IF_NON_ASYNC);
449 0 : ahd->inited_target[target] = 1;
450 0 : }
451 :
452 0 : ahd_unlock(ahd, &s);
453 : return;
454 : }
455 :
456 : /*
457 : * If we can't use interrupts, poll for completion
458 : */
459 : SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
460 :
461 0 : do {
462 0 : if (ahd_poll(ahd, xs->timeout)) {
463 0 : if (!(xs->flags & SCSI_SILENT))
464 0 : printf("cmd fail\n");
465 0 : ahd_timeout(scb);
466 0 : break;
467 : }
468 0 : } while (!(xs->flags & ITSDONE));
469 :
470 0 : ahd_unlock(ahd, &s);
471 0 : }
472 :
473 : int
474 0 : ahd_poll(struct ahd_softc *ahd, int wait)
475 : {
476 0 : while (--wait) {
477 0 : DELAY(1000);
478 0 : if (ahd_inb(ahd, INTSTAT) & INT_PEND)
479 : break;
480 : }
481 :
482 0 : if (wait == 0) {
483 0 : printf("%s: board is not responding\n", ahd_name(ahd));
484 0 : return (EIO);
485 : }
486 :
487 0 : ahd_intr((void *)ahd);
488 0 : return (0);
489 0 : }
490 :
491 : void
492 0 : ahd_setup_data(struct ahd_softc *ahd, struct scsi_xfer *xs,
493 : struct scb *scb)
494 : {
495 : struct hardware_scb *hscb;
496 :
497 0 : hscb = scb->hscb;
498 0 : xs->resid = xs->status = 0;
499 0 : xs->error = CAM_REQ_INPROG;
500 :
501 0 : hscb->cdb_len = xs->cmdlen;
502 0 : if (hscb->cdb_len > MAX_CDB_LEN) {
503 0 : xs->error = XS_DRIVER_STUFFUP;
504 0 : scsi_done(xs);
505 0 : return;
506 : }
507 :
508 0 : memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len);
509 :
510 : /* Only use S/G if there is a transfer */
511 0 : if (xs->datalen) {
512 : int error;
513 :
514 0 : error = bus_dmamap_load(ahd->parent_dmat,
515 : scb->dmamap, xs->data,
516 : xs->datalen, NULL,
517 : ((xs->flags & SCSI_NOSLEEP) ?
518 : BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
519 : BUS_DMA_STREAMING |
520 : ((xs->flags & XS_CTL_DATA_IN) ?
521 : BUS_DMA_READ : BUS_DMA_WRITE));
522 0 : if (error) {
523 : #ifdef AHD_DEBUG
524 : printf("%s: in ahd_setup_data(): bus_dmamap_load() "
525 : "= %d\n", ahd_name(ahd), error);
526 : #endif
527 0 : xs->error = XS_DRIVER_STUFFUP;
528 0 : scsi_done(xs);
529 0 : return;
530 : }
531 0 : ahd_execute_scb(scb, scb->dmamap->dm_segs,
532 0 : scb->dmamap->dm_nsegs);
533 0 : } else {
534 0 : ahd_execute_scb(scb, NULL, 0);
535 : }
536 0 : }
537 :
538 : void
539 0 : ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
540 : ahd_queue_alg alg)
541 : {
542 0 : struct ahd_tmode_tstate *tstate;
543 :
544 0 : ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
545 0 : devinfo->target, &tstate);
546 :
547 0 : if (alg != AHD_QUEUE_NONE)
548 0 : tstate->tagenable |= devinfo->target_mask;
549 : else
550 0 : tstate->tagenable &= ~devinfo->target_mask;
551 0 : }
552 :
553 : int
554 0 : ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
555 : {
556 : /* We don't sort softcs under OpenBSD so report equal always */
557 0 : return (0);
558 : }
559 :
560 : int
561 0 : ahd_detach(struct device *self, int flags)
562 : {
563 : int rv = 0;
564 :
565 0 : struct ahd_softc *ahd = (struct ahd_softc*)self;
566 :
567 0 : if (ahd->sc_child != NULL)
568 0 : rv = config_detach((void *)ahd->sc_child, flags);
569 :
570 0 : ahd_free(ahd);
571 :
572 0 : return rv;
573 : }
574 :
575 : void
576 0 : ahd_adapter_req_set_xfer_mode(struct ahd_softc *ahd, struct scb *scb)
577 : {
578 : struct ahd_initiator_tinfo *tinfo;
579 0 : struct ahd_tmode_tstate *tstate;
580 : int target_id, our_id;
581 0 : struct ahd_devinfo devinfo;
582 : u_int16_t quirks;
583 0 : u_int width, ppr_options, period, offset;
584 : int s;
585 :
586 0 : target_id = scb->xs->sc_link->target;
587 0 : our_id = SCSI_SCSI_ID(ahd, scb->xs->sc_link);
588 :
589 0 : s = splbio();
590 :
591 0 : quirks = scb->xs->sc_link->quirks;
592 0 : tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
593 0 : ahd_compile_devinfo(&devinfo, our_id, target_id, 0, 'A',
594 : ROLE_INITIATOR);
595 :
596 0 : tstate->discenable |= (ahd->user_discenable & devinfo.target_mask);
597 :
598 0 : if (quirks & SDEV_NOTAGS)
599 0 : tstate->tagenable &= ~devinfo.target_mask;
600 0 : else if (ahd->user_tagenable & devinfo.target_mask)
601 0 : tstate->tagenable |= devinfo.target_mask;
602 :
603 0 : if (quirks & SDEV_NOWIDE)
604 0 : width = MSG_EXT_WDTR_BUS_8_BIT;
605 : else
606 0 : width = MSG_EXT_WDTR_BUS_16_BIT;
607 :
608 0 : ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
609 0 : if (width > tinfo->user.width)
610 0 : width = tinfo->user.width;
611 0 : ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
612 :
613 0 : if (quirks & SDEV_NOSYNC) {
614 0 : period = 0;
615 0 : offset = 0;
616 0 : } else {
617 0 : period = tinfo->user.period;
618 0 : offset = tinfo->user.offset;
619 : }
620 :
621 : /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */
622 0 : ppr_options = tinfo->user.ppr_options;
623 : /* XXX Other reasons to avoid ppr? XXX */
624 0 : if (width < MSG_EXT_WDTR_BUS_16_BIT)
625 : ppr_options = 0;
626 :
627 0 : if ((tstate->discenable & devinfo.target_mask) == 0 ||
628 0 : (tstate->tagenable & devinfo.target_mask) == 0)
629 0 : ppr_options &= ~MSG_EXT_PPR_PROT_IUS;
630 :
631 0 : ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
632 0 : ahd_validate_offset(ahd, NULL, period, &offset, width, ROLE_UNKNOWN);
633 :
634 0 : if (offset == 0) {
635 0 : period = 0;
636 0 : ppr_options = 0;
637 0 : }
638 :
639 0 : if (ppr_options != 0 && tinfo->user.transport_version >= 3) {
640 0 : tinfo->goal.transport_version = tinfo->user.transport_version;
641 0 : tinfo->curr.transport_version = tinfo->user.transport_version;
642 0 : }
643 :
644 0 : ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
645 : AHD_TRANS_GOAL, FALSE);
646 :
647 0 : splx(s);
648 0 : }
649 :
650 : void
651 0 : aic_timer_reset(aic_timer_t *timer, u_int msec, ahd_callback_t *func,
652 : void *arg)
653 : {
654 : uint64_t nticks;
655 :
656 0 : nticks = msec;
657 0 : nticks *= hz;
658 0 : nticks /= 1000;
659 0 : callout_reset(timer, nticks, func, arg);
660 0 : }
661 :
662 : void
663 0 : aic_scb_timer_reset(struct scb *scb, u_int msec)
664 : {
665 : uint64_t nticks;
666 :
667 0 : nticks = msec;
668 0 : nticks *= hz;
669 0 : nticks /= 1000;
670 0 : if (!(scb->xs->xs_control & XS_CTL_POLL))
671 0 : callout_reset(&scb->xs->xs_callout, nticks, ahd_timeout, scb);
672 0 : }
673 :
674 : void
675 0 : ahd_flush_device_writes(struct ahd_softc *ahd)
676 : {
677 : /* XXX Is this sufficient for all architectures??? */
678 0 : ahd_inb(ahd, INTSTAT);
679 0 : }
680 :
681 : void
682 0 : aic_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
683 : {
684 : int s;
685 :
686 0 : ahd_lock(ahd, &s);
687 :
688 0 : if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0) {
689 0 : ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
690 0 : }
691 :
692 0 : if (!cold) {
693 : /* we are no longer in autoconf */
694 0 : timeout_del(&scb->xs->stimeout);
695 0 : }
696 :
697 0 : ahd_unlock(ahd, &s);
698 0 : }
699 :
700 : void
701 0 : ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
702 : {
703 0 : sc_print_addr(scb->xs->sc_link);
704 0 : }
705 :
706 : void
707 0 : ahd_platform_dump_card_state(struct ahd_softc *ahd)
708 : {
709 : /* Nothing to do here for OpenBSD */
710 0 : printf("FEATURES = 0x%x, FLAGS = 0x%x, CHIP = 0x%x BUGS =0x%x\n",
711 0 : ahd->features, ahd->flags, ahd->chip, ahd->bugs);
712 0 : }
713 :
|