1/* $NetBSD: aic79xx_osm.c,v 1.33 2016/07/14 04:00:45 msaitoh Exp $ */
2
3/*
4 * Bus independent NetBSD shim for the aic7xxx based adaptec SCSI controllers
5 *
6 * Copyright (c) 1994-2002 Justin T. Gibbs.
7 * Copyright (c) 2001-2002 Adaptec Inc.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions, and the following disclaimer,
15 * without modification.
16 * 2. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU Public License ("GPL").
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#26 $
35 *
36 * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.11 2003/05/04 00:20:07 gibbs Exp $
37 */
38/*
39 * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc.
40 * - April 2003
41 */
42
43#include <sys/cdefs.h>
44__KERNEL_RCSID(0, "$NetBSD: aic79xx_osm.c,v 1.33 2016/07/14 04:00:45 msaitoh Exp $");
45
46#include <dev/ic/aic79xx_osm.h>
47#include <dev/ic/aic79xx_inline.h>
48
49#ifndef AHD_TMODE_ENABLE
50#define AHD_TMODE_ENABLE 0
51#endif
52
53static int ahd_ioctl(struct scsipi_channel *channel, u_long cmd,
54 void *addr, int flag, struct proc *p);
55static void ahd_action(struct scsipi_channel *chan,
56 scsipi_adapter_req_t req, void *arg);
57static void ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
58 int nsegments);
59static int ahd_poll(struct ahd_softc *ahd, int wait);
60static void ahd_setup_data(struct ahd_softc *ahd, struct scsipi_xfer *xs,
61 struct scb *scb);
62
63#if NOT_YET
64static void ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb);
65#endif
66
67static bool ahd_pmf_suspend(device_t, const pmf_qual_t *);
68static bool ahd_pmf_resume(device_t, const pmf_qual_t *);
69static bool ahd_pmf_shutdown(device_t, int);
70
71/*
72 * Attach all the sub-devices we can find
73 */
74int
75ahd_attach(struct ahd_softc *ahd)
76{
77 int s;
78 char ahd_info[256];
79
80 ahd_controller_info(ahd, ahd_info, sizeof(ahd_info));
81 aprint_normal("%s: %s\n", ahd_name(ahd), ahd_info);
82
83 ahd_lock(ahd, &s);
84
85 ahd->sc_adapter.adapt_dev = ahd->sc_dev;
86 ahd->sc_adapter.adapt_nchannels = 1;
87
88 ahd->sc_adapter.adapt_openings = ahd->scb_data.numscbs - 1;
89 ahd->sc_adapter.adapt_max_periph = 32;
90
91 ahd->sc_adapter.adapt_ioctl = ahd_ioctl;
92 ahd->sc_adapter.adapt_minphys = ahd_minphys;
93 ahd->sc_adapter.adapt_request = ahd_action;
94
95 ahd->sc_channel.chan_adapter = &ahd->sc_adapter;
96 ahd->sc_channel.chan_bustype = &scsi_bustype;
97 ahd->sc_channel.chan_channel = 0;
98 ahd->sc_channel.chan_ntargets = AHD_NUM_TARGETS;
99 ahd->sc_channel.chan_nluns = 8 /*AHD_NUM_LUNS*/;
100 ahd->sc_channel.chan_id = ahd->our_id;
101 ahd->sc_channel.chan_flags |= SCSIPI_CHAN_CANGROW;
102
103 ahd->sc_child = config_found(ahd->sc_dev, &ahd->sc_channel, scsiprint);
104
105 ahd_intr_enable(ahd, TRUE);
106
107 if (ahd->flags & AHD_RESET_BUS_A)
108 ahd_reset_channel(ahd, 'A', TRUE);
109
110 if (!pmf_device_register1(ahd->sc_dev,
111 ahd_pmf_suspend, ahd_pmf_resume, ahd_pmf_shutdown))
112 aprint_error_dev(ahd->sc_dev,
113 "couldn't establish power handler\n");
114
115 ahd_unlock(ahd, &s);
116
117 return (1);
118}
119
120static bool
121ahd_pmf_suspend(device_t dev, const pmf_qual_t *qual)
122{
123 struct ahd_softc *sc = device_private(dev);
124#if 0
125 return (ahd_suspend(sc) == 0);
126#else
127 ahd_shutdown(sc);
128 return true;
129#endif
130}
131
132static bool
133ahd_pmf_resume(device_t dev, const pmf_qual_t *qual)
134{
135#if 0
136 struct ahd_softc *sc = device_private(dev);
137
138 return (ahd_resume(sc) == 0);
139#else
140 return true;
141#endif
142}
143
144static bool
145ahd_pmf_shutdown(device_t dev, int howto)
146{
147 struct ahd_softc *sc = device_private(dev);
148
149 /* Disable all interrupt sources by resetting the controller */
150 ahd_shutdown(sc);
151
152 return true;
153}
154
155static int
156ahd_ioctl(struct scsipi_channel *channel, u_long cmd,
157 void *addr, int flag, struct proc *p)
158{
159 struct ahd_softc *ahd;
160 int s, ret = ENOTTY;
161
162 ahd = device_private(channel->chan_adapter->adapt_dev);
163
164 switch (cmd) {
165 case SCBUSIORESET:
166 s = splbio();
167 ahd_reset_channel(ahd, channel->chan_channel == 1 ? 'B' : 'A', TRUE);
168 splx(s);
169 ret = 0;
170 break;
171 default:
172 break;
173 }
174
175 return ret;
176}
177
178/*
179 * Catch an interrupt from the adapter
180 */
181void
182ahd_platform_intr(void *arg)
183{
184 struct ahd_softc *ahd;
185
186 ahd = arg;
187
188 printf("%s; ahd_platform_intr\n", ahd_name(ahd));
189
190 ahd_intr(ahd);
191}
192
193/*
194 * We have an scb which has been processed by the
195 * adaptor, now we look to see how the operation * went.
196 */
197void
198ahd_done(struct ahd_softc *ahd, struct scb *scb)
199{
200 struct scsipi_xfer *xs;
201 struct scsipi_periph *periph;
202 int s;
203
204 LIST_REMOVE(scb, pending_links);
205
206 xs = scb->xs;
207 periph = xs->xs_periph;
208
209 callout_stop(&scb->xs->xs_callout);
210
211 if (xs->datalen) {
212 int op;
213
214 if (xs->xs_control & XS_CTL_DATA_IN)
215 op = BUS_DMASYNC_POSTREAD;
216 else
217 op = BUS_DMASYNC_POSTWRITE;
218
219 bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
220 scb->dmamap->dm_mapsize, op);
221 bus_dmamap_unload(ahd->parent_dmat, scb->dmamap);
222 }
223
224 /*
225 * If the recovery SCB completes, we have to be
226 * out of our timeout.
227 */
228 if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
229 struct scb *list_scb;
230
231 /*
232 * We were able to complete the command successfully,
233 * so reinstate the timeouts for all other pending
234 * commands.
235 */
236 LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) {
237 struct scsipi_xfer *txs = list_scb->xs;
238
239 if (!(txs->xs_control & XS_CTL_POLL)) {
240 callout_reset(&txs->xs_callout,
241 (txs->timeout > 1000000) ?
242 (txs->timeout / 1000) * hz :
243 (txs->timeout * hz) / 1000,
244 ahd_timeout, list_scb);
245 }
246 }
247
248 if (ahd_get_transaction_status(scb) != XS_NOERROR)
249 ahd_set_transaction_status(scb, XS_TIMEOUT);
250 scsipi_printaddr(xs->xs_periph);
251 printf("%s: no longer in timeout, status = %x\n",
252 ahd_name(ahd), xs->status);
253 }
254
255 if (xs->error != XS_NOERROR) {
256 /* Don't clobber any existing error state */
257 } else if ((xs->status == SCSI_STATUS_BUSY) ||
258 (xs->status == SCSI_STATUS_QUEUE_FULL)) {
259 ahd_set_transaction_status(scb, XS_BUSY);
260 printf("%s: drive (ID %d, LUN %d) queue full (SCB 0x%x)\n",
261 ahd_name(ahd), SCB_GET_TARGET(ahd,scb), SCB_GET_LUN(scb), SCB_GET_TAG(scb));
262 } else if ((scb->flags & SCB_SENSE) != 0) {
263 /*
264 * We performed autosense retrieval.
265 *
266 * zero the sense data before having
267 * the drive fill it. The SCSI spec mandates
268 * that any untransferred data should be
269 * assumed to be zero. Complete the 'bounce'
270 * of sense information through buffers accessible
271 * via bus-space by copying it into the clients
272 * csio.
273 */
274 memset(&xs->sense.scsi_sense, 0, sizeof(xs->sense.scsi_sense));
275 memcpy(&xs->sense.scsi_sense, ahd_get_sense_buf(ahd, scb),
276 sizeof(struct scsi_sense_data));
277
278 ahd_set_transaction_status(scb, XS_SENSE);
279 } else if ((scb->flags & SCB_PKT_SENSE) != 0) {
280 struct scsi_status_iu_header *siu;
281 u_int sense_len;
282#ifdef AHD_DEBUG
283 int i;
284#endif
285 /*
286 * Copy only the sense data into the provided buffer.
287 */
288 siu = (struct scsi_status_iu_header *)scb->sense_data;
289 sense_len = MIN(scsi_4btoul(siu->sense_length),
290 sizeof(xs->sense.scsi_sense));
291 memset(&xs->sense.scsi_sense, 0, sizeof(xs->sense.scsi_sense));
292 memcpy(&xs->sense.scsi_sense,
293 scb->sense_data + SIU_SENSE_OFFSET(siu), sense_len);
294#ifdef AHD_DEBUG
295 printf("Copied %d bytes of sense data offset %d:", sense_len,
296 SIU_SENSE_OFFSET(siu));
297 for (i = 0; i < sense_len; i++)
298 printf(" 0x%x", ((uint8_t *)&xs->sense.scsi_sense)[i]);
299 printf("\n");
300#endif
301 ahd_set_transaction_status(scb, XS_SENSE);
302 }
303
304 if (scb->flags & SCB_FREEZE_QUEUE) {
305 scsipi_periph_thaw(periph, 1);
306 scb->flags &= ~SCB_FREEZE_QUEUE;
307 }
308
309 if (scb->flags & SCB_REQUEUE)
310 ahd_set_transaction_status(scb, XS_REQUEUE);
311
312 ahd_lock(ahd, &s);
313 ahd_free_scb(ahd, scb);
314 ahd_unlock(ahd, &s);
315
316 scsipi_done(xs);
317}
318
319static void
320ahd_action(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
321{
322 struct ahd_softc *ahd;
323 struct ahd_initiator_tinfo *tinfo;
324 struct ahd_tmode_tstate *tstate;
325
326 ahd = device_private(chan->chan_adapter->adapt_dev);
327
328 switch(req) {
329
330 case ADAPTER_REQ_RUN_XFER:
331 {
332 struct scsipi_xfer *xs;
333 struct scsipi_periph *periph;
334 struct scb *scb;
335 struct hardware_scb *hscb;
336 u_int target_id;
337 u_int our_id;
338 u_int col_idx;
339 char channel;
340 int s;
341
342 xs = arg;
343 periph = xs->xs_periph;
344
345 SC_DEBUG(periph, SCSIPI_DB3, ("ahd_action\n"));
346
347 target_id = periph->periph_target;
348 our_id = ahd->our_id;
349 channel = (chan->chan_channel == 1) ? 'B' : 'A';
350
351 /*
352 * get an scb to use.
353 */
354 ahd_lock(ahd, &s);
355 tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
356 target_id, &tstate);
357
358 if (xs->xs_tag_type != 0 ||
359 (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
360 col_idx = AHD_NEVER_COL_IDX;
361 else
362 col_idx = AHD_BUILD_COL_IDX(target_id,
363 periph->periph_lun);
364
365 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
366 xs->error = XS_RESOURCE_SHORTAGE;
367 ahd_unlock(ahd, &s);
368 scsipi_done(xs);
369 return;
370 }
371 ahd_unlock(ahd, &s);
372
373 hscb = scb->hscb;
374
375 SC_DEBUG(periph, SCSIPI_DB3, ("start scb(%p)\n", scb));
376 scb->xs = xs;
377
378 /*
379 * Put all the arguments for the xfer in the scb
380 */
381 hscb->control = 0;
382 hscb->scsiid = BUILD_SCSIID(ahd, sim, target_id, our_id);
383 hscb->lun = periph->periph_lun;
384 if (xs->xs_control & XS_CTL_RESET) {
385 hscb->cdb_len = 0;
386 scb->flags |= SCB_DEVICE_RESET;
387 hscb->control |= MK_MESSAGE;
388 hscb->task_management = SIU_TASKMGMT_LUN_RESET;
389 ahd_execute_scb(scb, NULL, 0);
390 } else {
391 hscb->task_management = 0;
392 }
393
394 ahd_setup_data(ahd, xs, scb);
395 break;
396 }
397
398 case ADAPTER_REQ_GROW_RESOURCES:
399#ifdef AHC_DEBUG
400 printf("%s: ADAPTER_REQ_GROW_RESOURCES\n", ahd_name(ahd));
401#endif
402 chan->chan_adapter->adapt_openings += ahd_alloc_scbs(ahd);
403 if (ahd->scb_data.numscbs >= AHD_SCB_MAX_ALLOC)
404 chan->chan_flags &= ~SCSIPI_CHAN_CANGROW;
405 break;
406
407 case ADAPTER_REQ_SET_XFER_MODE:
408 {
409 struct scsipi_xfer_mode *xm = arg;
410 struct ahd_devinfo devinfo;
411 int target_id, our_id, first;
412 u_int width;
413 int s;
414 char channel;
415 u_int ppr_options = 0, period, offset;
416 uint16_t old_autoneg;
417
418 target_id = xm->xm_target;
419 our_id = chan->chan_id;
420 channel = 'A';
421 s = splbio();
422 tinfo = ahd_fetch_transinfo(ahd, channel, our_id, target_id,
423 &tstate);
424 ahd_compile_devinfo(&devinfo, our_id, target_id,
425 0, channel, ROLE_INITIATOR);
426
427 old_autoneg = tstate->auto_negotiate;
428
429 /*
430 * XXX since the period and offset are not provided here,
431 * fake things by forcing a renegotiation using the user
432 * settings if this is called for the first time (i.e.
433 * during probe). Also, cap various values at the user
434 * values, assuming that the user set it up that way.
435 */
436 if (ahd->inited_target[target_id] == 0) {
437 period = tinfo->user.period;
438 offset = tinfo->user.offset;
439 ppr_options = tinfo->user.ppr_options;
440 width = tinfo->user.width;
441 tstate->tagenable |=
442 (ahd->user_tagenable & devinfo.target_mask);
443 tstate->discenable |=
444 (ahd->user_discenable & devinfo.target_mask);
445 ahd->inited_target[target_id] = 1;
446 first = 1;
447 } else
448 first = 0;
449
450 if (xm->xm_mode & (PERIPH_CAP_WIDE16 | PERIPH_CAP_DT))
451 width = MSG_EXT_WDTR_BUS_16_BIT;
452 else
453 width = MSG_EXT_WDTR_BUS_8_BIT;
454
455 ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
456 if (width > tinfo->user.width)
457 width = tinfo->user.width;
458 ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
459
460 if (!(xm->xm_mode & (PERIPH_CAP_SYNC | PERIPH_CAP_DT))) {
461 period = 0;
462 offset = 0;
463 ppr_options = 0;
464 }
465
466 if ((xm->xm_mode & PERIPH_CAP_DT) &&
467 (tinfo->user.ppr_options & MSG_EXT_PPR_DT_REQ))
468 ppr_options |= MSG_EXT_PPR_DT_REQ;
469 else
470 ppr_options &= ~MSG_EXT_PPR_DT_REQ;
471
472 if ((tstate->discenable & devinfo.target_mask) == 0 ||
473 (tstate->tagenable & devinfo.target_mask) == 0)
474 ppr_options &= ~MSG_EXT_PPR_IU_REQ;
475
476 if ((xm->xm_mode & PERIPH_CAP_TQING) &&
477 (ahd->user_tagenable & devinfo.target_mask))
478 tstate->tagenable |= devinfo.target_mask;
479 else
480 tstate->tagenable &= ~devinfo.target_mask;
481
482 ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
483 ahd_validate_offset(ahd, NULL, period, &offset,
484 MSG_EXT_WDTR_BUS_8_BIT, ROLE_UNKNOWN);
485 if (offset == 0) {
486 period = 0;
487 ppr_options = 0;
488 }
489 if (ppr_options != 0
490 && tinfo->user.transport_version >= 3) {
491 tinfo->goal.transport_version =
492 tinfo->user.transport_version;
493 tinfo->curr.transport_version =
494 tinfo->user.transport_version;
495 }
496
497 ahd_set_syncrate(ahd, &devinfo, period, offset,
498 ppr_options, AHD_TRANS_GOAL, FALSE);
499
500 /*
501 * If this is the first request, and no negotiation is
502 * needed, just confirm the state to the scsipi layer,
503 * so that it can print a message.
504 */
505 if (old_autoneg == tstate->auto_negotiate && first) {
506 xm->xm_mode = 0;
507 xm->xm_period = tinfo->curr.period;
508 xm->xm_offset = tinfo->curr.offset;
509 if (tinfo->curr.width == MSG_EXT_WDTR_BUS_16_BIT)
510 xm->xm_mode |= PERIPH_CAP_WIDE16;
511 if (tinfo->curr.period)
512 xm->xm_mode |= PERIPH_CAP_SYNC;
513 if (tstate->tagenable & devinfo.target_mask)
514 xm->xm_mode |= PERIPH_CAP_TQING;
515 if (tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ)
516 xm->xm_mode |= PERIPH_CAP_DT;
517 scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
518 }
519 splx(s);
520 }
521 }
522
523 return;
524}
525
526static void
527ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
528{
529 struct scb *scb;
530 struct scsipi_xfer *xs;
531 struct ahd_softc *ahd;
532 struct ahd_initiator_tinfo *tinfo;
533 struct ahd_tmode_tstate *tstate;
534 u_int mask;
535 int s;
536
537 scb = arg;
538 xs = scb->xs;
539 xs->error = 0;
540 xs->status = 0;
541 xs->xs_status = 0;
542 ahd = device_private(
543 xs->xs_periph->periph_channel->chan_adapter->adapt_dev);
544
545 scb->sg_count = 0;
546 if (nsegments != 0) {
547 void *sg;
548 int op;
549 u_int i;
550
551 ahd_setup_data_scb(ahd, scb);
552
553 /* Copy the segments into our SG list */
554 for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
555
556 sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
557 dm_segs->ds_len,
558 /*last*/i == 1);
559 dm_segs++;
560 }
561
562 if (xs->xs_control & XS_CTL_DATA_IN)
563 op = BUS_DMASYNC_PREREAD;
564 else
565 op = BUS_DMASYNC_PREWRITE;
566
567 bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
568 scb->dmamap->dm_mapsize, op);
569 }
570
571 ahd_lock(ahd, &s);
572
573 /*
574 * Last time we need to check if this SCB needs to
575 * be aborted.
576 */
577 if (ahd_get_scsi_status(scb) == XS_STS_DONE) {
578 if (nsegments != 0)
579 bus_dmamap_unload(ahd->parent_dmat,
580 scb->dmamap);
581 ahd_free_scb(ahd, scb);
582 ahd_unlock(ahd, &s);
583 return;
584 }
585
586 tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
587 SCSIID_OUR_ID(scb->hscb->scsiid),
588 SCSIID_TARGET(ahd, scb->hscb->scsiid),
589 &tstate);
590
591 mask = SCB_GET_TARGET_MASK(ahd, scb);
592
593 if ((tstate->discenable & mask) != 0)
594 scb->hscb->control |= DISCENB;
595
596 if ((tstate->tagenable & mask) != 0)
597 scb->hscb->control |= xs->xs_tag_type|TAG_ENB;
598
599 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU) != 0) {
600 scb->flags |= SCB_PACKETIZED;
601 if (scb->hscb->task_management != 0)
602 scb->hscb->control &= ~MK_MESSAGE;
603 }
604
605#if 0 /* This looks like it makes sense at first, but it can loop */
606 if ((xs->xs_control & XS_CTL_DISCOVERY) &&
607 (tinfo->goal.width != 0
608 || tinfo->goal.period != 0
609 || tinfo->goal.ppr_options != 0)) {
610 scb->flags |= SCB_NEGOTIATE;
611 scb->hscb->control |= MK_MESSAGE;
612 } else
613#endif
614 if ((tstate->auto_negotiate & mask) != 0) {
615 scb->flags |= SCB_AUTO_NEGOTIATE;
616 scb->hscb->control |= MK_MESSAGE;
617 }
618
619 LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
620
621 scb->flags |= SCB_ACTIVE;
622
623 if (!(xs->xs_control & XS_CTL_POLL)) {
624 callout_reset(&scb->xs->xs_callout, xs->timeout > 1000000 ?
625 (xs->timeout / 1000) * hz : (xs->timeout * hz) / 1000,
626 ahd_timeout, scb);
627 }
628
629 if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
630 /* Define a mapping from our tag to the SCB. */
631 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
632 ahd_pause(ahd);
633 ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
634 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
635 ahd_unpause(ahd);
636 } else {
637 ahd_queue_scb(ahd, scb);
638 }
639
640 if (!(xs->xs_control & XS_CTL_POLL)) {
641 ahd_unlock(ahd, &s);
642 return;
643 }
644 /*
645 * If we can't use interrupts, poll for completion
646 */
647 SC_DEBUG(xs->xs_periph, SCSIPI_DB3, ("cmd_poll\n"));
648 do {
649 if (ahd_poll(ahd, xs->timeout)) {
650 if (!(xs->xs_control & XS_CTL_SILENT))
651 printf("cmd fail\n");
652 ahd_timeout(scb);
653 break;
654 }
655 } while (!(xs->xs_status & XS_STS_DONE));
656
657 ahd_unlock(ahd, &s);
658}
659
660static int
661ahd_poll(struct ahd_softc *ahd, int wait)
662{
663
664 while (--wait) {
665 DELAY(1000);
666 if (ahd_inb(ahd, INTSTAT) & INT_PEND)
667 break;
668 }
669
670 if (wait == 0) {
671 printf("%s: board is not responding\n", ahd_name(ahd));
672 return (EIO);
673 }
674
675 ahd_intr(ahd);
676 return (0);
677}
678
679
680static void
681ahd_setup_data(struct ahd_softc *ahd, struct scsipi_xfer *xs,
682 struct scb *scb)
683{
684 struct hardware_scb *hscb;
685
686 hscb = scb->hscb;
687 xs->resid = xs->status = 0;
688
689 hscb->cdb_len = xs->cmdlen;
690 if (hscb->cdb_len > MAX_CDB_LEN) {
691 int s;
692 /*
693 * Should CAM start to support CDB sizes
694 * greater than 16 bytes, we could use
695 * the sense buffer to store the CDB.
696 */
697 ahd_set_transaction_status(scb,
698 XS_DRIVER_STUFFUP);
699
700 ahd_lock(ahd, &s);
701 ahd_free_scb(ahd, scb);
702 ahd_unlock(ahd, &s);
703 scsipi_done(xs);
704 }
705 memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len);
706
707 /* Only use S/G if there is a transfer */
708 if (xs->datalen) {
709 int error;
710
711 error = bus_dmamap_load(ahd->parent_dmat,
712 scb->dmamap, xs->data,
713 xs->datalen, NULL,
714 ((xs->xs_control & XS_CTL_NOSLEEP) ?
715 BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
716 BUS_DMA_STREAMING |
717 ((xs->xs_control & XS_CTL_DATA_IN) ?
718 BUS_DMA_READ : BUS_DMA_WRITE));
719 if (error) {
720#ifdef AHD_DEBUG
721 printf("%s: in ahd_setup_data(): bus_dmamap_load() "
722 "= %d\n",
723 ahd_name(ahd), error);
724#endif
725 xs->error = XS_RESOURCE_SHORTAGE;
726 scsipi_done(xs);
727 return;
728 }
729 ahd_execute_scb(scb,
730 scb->dmamap->dm_segs,
731 scb->dmamap->dm_nsegs);
732 } else {
733 ahd_execute_scb(scb, NULL, 0);
734 }
735}
736
737void
738ahd_timeout(void *arg)
739{
740 struct scb *scb;
741 struct ahd_softc *ahd;
742 int s;
743
744 scb = arg;
745 ahd = scb->ahd_softc;
746
747 printf("%s: ahd_timeout\n", ahd_name(ahd));
748
749 ahd_lock(ahd, &s);
750
751 ahd_pause_and_flushwork(ahd);
752 (void)ahd_save_modes(ahd);
753#if 0
754 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
755 ahd_outb(ahd, SCSISIGO, ACKO);
756 printf("set ACK\n");
757 ahd_outb(ahd, SCSISIGO, 0);
758 printf("clearing Ack\n");
759 ahd_restore_modes(ahd, saved_modes);
760#endif
761 if ((scb->flags & SCB_ACTIVE) == 0) {
762 /* Previous timeout took care of me already */
763 printf("%s: Timedout SCB already complete. "
764 "Interrupts may not be functioning.\n", ahd_name(ahd));
765 ahd_unpause(ahd);
766 ahd_unlock(ahd, &s);
767 return;
768 }
769
770 ahd_print_path(ahd, scb);
771 printf("SCB 0x%x - timed out\n", SCB_GET_TAG(scb));
772 ahd_dump_card_state(ahd);
773 ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
774 /*initiate reset*/TRUE);
775 ahd_unlock(ahd, &s);
776 return;
777}
778
779int
780ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
781{
782 ahd->platform_data = malloc(sizeof(struct ahd_platform_data), M_DEVBUF,
783 M_NOWAIT /*| M_ZERO*/);
784 if (ahd->platform_data == NULL)
785 return (ENOMEM);
786
787 memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
788
789 return (0);
790}
791
792void
793ahd_platform_free(struct ahd_softc *ahd)
794{
795 free(ahd->platform_data, M_DEVBUF);
796}
797
798int
799ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
800{
801 /* We don't sort softcs under NetBSD so report equal always */
802 return (0);
803}
804
805int
806ahd_detach(struct ahd_softc *ahd, int flags)
807{
808 int rv = 0;
809
810 if (ahd->sc_child != NULL)
811 rv = config_detach(ahd->sc_child, flags);
812
813 pmf_device_deregister(ahd->sc_dev);
814
815 ahd_free(ahd);
816
817 return rv;
818}
819
820void
821ahd_platform_set_tags(struct ahd_softc *ahd,
822 struct ahd_devinfo *devinfo, ahd_queue_alg alg)
823{
824 struct ahd_tmode_tstate *tstate;
825
826 ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
827 devinfo->target, &tstate);
828
829 if (alg != AHD_QUEUE_NONE)
830 tstate->tagenable |= devinfo->target_mask;
831 else
832 tstate->tagenable &= ~devinfo->target_mask;
833}
834
835void
836ahd_send_async(struct ahd_softc *ahd, char channel, u_int target, u_int lun,
837 ac_code code, void *opt_arg)
838{
839 struct ahd_tmode_tstate *tstate;
840 struct ahd_initiator_tinfo *tinfo;
841 struct ahd_devinfo devinfo;
842 struct scsipi_channel *chan;
843 struct scsipi_xfer_mode xm;
844
845#ifdef DIAGNOSTIC
846 if (channel != 'A')
847 panic("ahd_send_async: not channel A");
848#endif
849 chan = &ahd->sc_channel;
850 switch (code) {
851 case AC_TRANSFER_NEG:
852 tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id, target,
853 &tstate);
854 ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
855 channel, ROLE_UNKNOWN);
856 /*
857 * Don't bother if negotiating. XXX?
858 */
859 if (tinfo->curr.period != tinfo->goal.period
860 || tinfo->curr.width != tinfo->goal.width
861 || tinfo->curr.offset != tinfo->goal.offset
862 || tinfo->curr.ppr_options != tinfo->goal.ppr_options)
863 break;
864 xm.xm_target = target;
865 xm.xm_mode = 0;
866 xm.xm_period = tinfo->curr.period;
867 xm.xm_offset = tinfo->curr.offset;
868 if (tinfo->goal.ppr_options & MSG_EXT_PPR_DT_REQ)
869 xm.xm_mode |= PERIPH_CAP_DT;
870 if (tinfo->curr.width == MSG_EXT_WDTR_BUS_16_BIT)
871 xm.xm_mode |= PERIPH_CAP_WIDE16;
872 if (tinfo->curr.period)
873 xm.xm_mode |= PERIPH_CAP_SYNC;
874 if (tstate->tagenable & devinfo.target_mask)
875 xm.xm_mode |= PERIPH_CAP_TQING;
876 scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, &xm);
877 break;
878 case AC_BUS_RESET:
879 scsipi_async_event(chan, ASYNC_EVENT_RESET, NULL);
880 case AC_SENT_BDR:
881 default:
882 break;
883 }
884}
885