]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/aic7xxx/aic79xx_osm.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / aic7xxx / aic79xx_osm.c
1 /*-
2  * Bus independent FreeBSD shim for the aic79xx based Adaptec SCSI controllers
3  *
4  * Copyright (c) 1994-2002, 2004 Justin T. Gibbs.
5  * Copyright (c) 2001-2002 Adaptec Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions, and the following disclaimer,
13  *    without modification.
14  * 2. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * Alternatively, this software may be distributed under the terms of the
18  * GNU Public License ("GPL").
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/aic79xx_osm.c#35 $
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <dev/aic7xxx/aic79xx_osm.h>
39 #include <dev/aic7xxx/aic79xx_inline.h>
40
41 #include <sys/kthread.h>
42
43 #include "opt_ddb.h"
44 #ifdef DDB
45 #include <ddb/ddb.h>
46 #endif
47
48 #ifndef AHD_TMODE_ENABLE
49 #define AHD_TMODE_ENABLE 0
50 #endif
51
52 #include <dev/aic7xxx/aic_osm_lib.c>
53
54 #define ccb_scb_ptr spriv_ptr0
55
56 #if 0
57 static void     ahd_dump_targcmd(struct target_cmd *cmd);
58 #endif
59 static int      ahd_modevent(module_t mod, int type, void *data);
60 static void     ahd_action(struct cam_sim *sim, union ccb *ccb);
61 static void     ahd_set_tran_settings(struct ahd_softc *ahd,
62                                       int our_id, char channel,
63                                       struct ccb_trans_settings *cts);
64 static void     ahd_get_tran_settings(struct ahd_softc *ahd,
65                                       int our_id, char channel,
66                                       struct ccb_trans_settings *cts);
67 static void     ahd_async(void *callback_arg, uint32_t code,
68                           struct cam_path *path, void *arg);
69 static void     ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
70                                 int nsegments, int error);
71 static void     ahd_poll(struct cam_sim *sim);
72 static void     ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
73                                struct ccb_scsiio *csio, struct scb *scb);
74 static void     ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim,
75                               union ccb *ccb);
76 static int      ahd_create_path(struct ahd_softc *ahd,
77                                 char channel, u_int target, u_int lun,
78                                 struct cam_path **path);
79
80 static int
81 ahd_create_path(struct ahd_softc *ahd, char channel, u_int target,
82                 u_int lun, struct cam_path **path)
83 {
84         path_id_t path_id;
85
86         path_id = cam_sim_path(ahd->platform_data->sim);
87         return (xpt_create_path(path, /*periph*/NULL,
88                                 path_id, target, lun));
89 }
90
91 int
92 ahd_map_int(struct ahd_softc *ahd)
93 {
94         int error;
95
96         /* Hook up our interrupt handler */
97         error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq,
98                                INTR_TYPE_CAM|INTR_MPSAFE, NULL,
99                                ahd_platform_intr, ahd, &ahd->platform_data->ih);
100         if (error != 0)
101                 device_printf(ahd->dev_softc, "bus_setup_intr() failed: %d\n",
102                               error);
103         return (error);
104 }
105
106 /*
107  * Attach all the sub-devices we can find
108  */
109 int
110 ahd_attach(struct ahd_softc *ahd)
111 {
112         char   ahd_info[256];
113         struct ccb_setasync csa;
114         struct cam_devq *devq;
115         struct cam_sim *sim;
116         struct cam_path *path;
117         int count;
118
119         count = 0;
120         devq = NULL;
121         sim = NULL;
122
123         /*
124          * Create a thread to perform all recovery.
125          */
126         if (ahd_spawn_recovery_thread(ahd) != 0)
127                 goto fail;
128
129         ahd_controller_info(ahd, ahd_info);
130         printf("%s\n", ahd_info);
131         ahd_lock(ahd);
132
133         /*
134          * Create the device queue for our SIM(s).
135          */
136         devq = cam_simq_alloc(AHD_MAX_QUEUE);
137         if (devq == NULL)
138                 goto fail;
139
140         /*
141          * Construct our SIM entry
142          */
143         sim = cam_sim_alloc(ahd_action, ahd_poll, "ahd", ahd,
144                             device_get_unit(ahd->dev_softc),
145                             &ahd->platform_data->mtx, 1, /*XXX*/256, devq);
146         if (sim == NULL) {
147                 cam_simq_free(devq);
148                 goto fail;
149         }
150
151         if (xpt_bus_register(sim, ahd->dev_softc, /*bus_id*/0) != CAM_SUCCESS) {
152                 cam_sim_free(sim, /*free_devq*/TRUE);
153                 sim = NULL;
154                 goto fail;
155         }
156         
157         if (xpt_create_path(&path, /*periph*/NULL,
158                             cam_sim_path(sim), CAM_TARGET_WILDCARD,
159                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
160                 xpt_bus_deregister(cam_sim_path(sim));
161                 cam_sim_free(sim, /*free_devq*/TRUE);
162                 sim = NULL;
163                 goto fail;
164         }
165                 
166         xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
167         csa.ccb_h.func_code = XPT_SASYNC_CB;
168         csa.event_enable = AC_LOST_DEVICE;
169         csa.callback = ahd_async;
170         csa.callback_arg = sim;
171         xpt_action((union ccb *)&csa);
172         count++;
173
174 fail:
175         ahd->platform_data->sim = sim;
176         ahd->platform_data->path = path;
177         ahd_unlock(ahd);
178         if (count != 0) {
179                 /* We have to wait until after any system dumps... */
180                 ahd->platform_data->eh =
181                     EVENTHANDLER_REGISTER(shutdown_final, ahd_shutdown,
182                                           ahd, SHUTDOWN_PRI_DEFAULT);
183                 ahd_intr_enable(ahd, TRUE);
184         }
185
186
187         return (count);
188 }
189
190 /*
191  * Catch an interrupt from the adapter
192  */
193 void
194 ahd_platform_intr(void *arg)
195 {
196         struct  ahd_softc *ahd;
197
198         ahd = (struct ahd_softc *)arg; 
199         ahd_lock(ahd);
200         ahd_intr(ahd);
201         ahd_unlock(ahd);
202 }
203
204 /*
205  * We have an scb which has been processed by the
206  * adaptor, now we look to see how the operation
207  * went.
208  */
209 void
210 ahd_done(struct ahd_softc *ahd, struct scb *scb)
211 {
212         union ccb *ccb;
213
214         CAM_DEBUG(scb->io_ctx->ccb_h.path, CAM_DEBUG_TRACE,
215                   ("ahd_done - scb %d\n", SCB_GET_TAG(scb)));
216
217         ccb = scb->io_ctx;
218         LIST_REMOVE(scb, pending_links);
219         if ((scb->flags & SCB_TIMEDOUT) != 0)
220                 LIST_REMOVE(scb, timedout_links);
221
222         callout_stop(&scb->io_timer);
223
224         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
225                 bus_dmasync_op_t op;
226
227                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
228                         op = BUS_DMASYNC_POSTREAD;
229                 else
230                         op = BUS_DMASYNC_POSTWRITE;
231                 bus_dmamap_sync(ahd->buffer_dmat, scb->dmamap, op);
232                 bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap);
233         }
234
235 #ifdef AHD_TARGET_MODE
236         if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
237                 struct cam_path *ccb_path;
238
239                 /*
240                  * If we have finally disconnected, clean up our
241                  * pending device state.
242                  * XXX - There may be error states that cause where
243                  *       we will remain connected.
244                  */
245                 ccb_path = ccb->ccb_h.path;
246                 if (ahd->pending_device != NULL
247                  && xpt_path_comp(ahd->pending_device->path, ccb_path) == 0) {
248
249                         if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
250                                 ahd->pending_device = NULL;
251                         } else {
252                                 xpt_print_path(ccb->ccb_h.path);
253                                 printf("Still disconnected\n");
254                                 ahd_freeze_ccb(ccb);
255                         }
256                 }
257
258                 if (aic_get_transaction_status(scb) == CAM_REQ_INPROG)
259                         ccb->ccb_h.status |= CAM_REQ_CMP;
260                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
261                 ahd_free_scb(ahd, scb);
262                 xpt_done(ccb);
263                 return;
264         }
265 #endif
266
267         if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
268                 struct  scb *list_scb;
269
270                 ahd->scb_data.recovery_scbs--;
271
272                 if (aic_get_transaction_status(scb) == CAM_BDR_SENT
273                  || aic_get_transaction_status(scb) == CAM_REQ_ABORTED)
274                         aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
275
276                 if (ahd->scb_data.recovery_scbs == 0) {
277                         /*
278                          * All recovery actions have completed successfully,
279                          * so reinstate the timeouts for all other pending
280                          * commands.
281                          */
282                         LIST_FOREACH(list_scb,
283                                      &ahd->pending_scbs, pending_links) {
284
285                                 aic_scb_timer_reset(list_scb,
286                                                     aic_get_timeout(scb));
287                         }
288
289                         ahd_print_path(ahd, scb);
290                         printf("no longer in timeout, status = %x\n",
291                                ccb->ccb_h.status);
292                 }
293         }
294
295         /* Don't clobber any existing error state */
296         if (aic_get_transaction_status(scb) == CAM_REQ_INPROG) {
297                 ccb->ccb_h.status |= CAM_REQ_CMP;
298         } else if ((scb->flags & SCB_SENSE) != 0) {
299                 /*
300                  * We performed autosense retrieval.
301                  *
302                  * Zero any sense not transferred by the
303                  * device.  The SCSI spec mandates that any
304                  * untransfered data should be assumed to be
305                  * zero.  Complete the 'bounce' of sense information
306                  * through buffers accessible via bus-space by
307                  * copying it into the clients csio.
308                  */
309                 memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
310                 memcpy(&ccb->csio.sense_data,
311                        ahd_get_sense_buf(ahd, scb),
312 /* XXX What size do we want to use??? */
313                         sizeof(ccb->csio.sense_data)
314                        - ccb->csio.sense_resid);
315                 scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID;
316         } else if ((scb->flags & SCB_PKT_SENSE) != 0) {
317                 struct scsi_status_iu_header *siu;
318                 u_int sense_len;
319
320                 /*
321                  * Copy only the sense data into the provided buffer.
322                  */
323                 siu = (struct scsi_status_iu_header *)scb->sense_data;
324                 sense_len = MIN(scsi_4btoul(siu->sense_length),
325                                 sizeof(ccb->csio.sense_data));
326                 memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
327                 memcpy(&ccb->csio.sense_data,
328                        ahd_get_sense_buf(ahd, scb) + SIU_SENSE_OFFSET(siu),
329                        sense_len);
330 #ifdef AHD_DEBUG
331                 if ((ahd_debug & AHD_SHOW_SENSE) != 0) {
332                         uint8_t *sense_data = (uint8_t *)&ccb->csio.sense_data;
333                         u_int i;
334
335                         printf("Copied %d bytes of sense data offset %d:",
336                                sense_len, SIU_SENSE_OFFSET(siu));
337                         for (i = 0; i < sense_len; i++)
338                                 printf(" 0x%x", *sense_data++);
339                         printf("\n");
340                 }
341 #endif
342                 scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID;
343         }
344         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
345         ahd_free_scb(ahd, scb);
346         xpt_done(ccb);
347 }
348
349 static void
350 ahd_action(struct cam_sim *sim, union ccb *ccb)
351 {
352         struct  ahd_softc *ahd;
353 #ifdef AHD_TARGET_MODE
354         struct  ahd_tmode_lstate *lstate;
355 #endif
356         u_int   target_id;
357         u_int   our_id;
358
359         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahd_action\n"));
360         
361         ahd = (struct ahd_softc *)cam_sim_softc(sim);
362
363         target_id = ccb->ccb_h.target_id;
364         our_id = SIM_SCSI_ID(ahd, sim);
365         
366         switch (ccb->ccb_h.func_code) {
367         /* Common cases first */
368 #ifdef AHD_TARGET_MODE
369         case XPT_ACCEPT_TARGET_IO:      /* Accept Host Target Mode CDB */
370         case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/
371         {
372                 struct     ahd_tmode_tstate *tstate;
373                 cam_status status;
374
375                 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate,
376                                              &lstate, TRUE);
377
378                 if (status != CAM_REQ_CMP) {
379                         if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
380                                 /* Response from the black hole device */
381                                 tstate = NULL;
382                                 lstate = ahd->black_hole;
383                         } else {
384                                 ccb->ccb_h.status = status;
385                                 xpt_done(ccb);
386                                 break;
387                         }
388                 }
389                 if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
390
391                         SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
392                                           sim_links.sle);
393                         ccb->ccb_h.status = CAM_REQ_INPROG;
394                         if ((ahd->flags & AHD_TQINFIFO_BLOCKED) != 0)
395                                 ahd_run_tqinfifo(ahd, /*paused*/FALSE);
396                         break;
397                 }
398
399                 /*
400                  * The target_id represents the target we attempt to
401                  * select.  In target mode, this is the initiator of
402                  * the original command.
403                  */
404                 our_id = target_id;
405                 target_id = ccb->csio.init_id;
406                 /* FALLTHROUGH */
407         }
408 #endif
409         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
410         case XPT_RESET_DEV:     /* Bus Device Reset the specified SCSI device */
411         {
412                 struct  scb *scb;
413                 struct  hardware_scb *hscb;     
414                 struct  ahd_initiator_tinfo *tinfo;
415                 struct  ahd_tmode_tstate *tstate;
416                 u_int   col_idx;
417
418                 if ((ahd->flags & AHD_INITIATORROLE) == 0
419                  && (ccb->ccb_h.func_code == XPT_SCSI_IO
420                   || ccb->ccb_h.func_code == XPT_RESET_DEV)) {
421                         ccb->ccb_h.status = CAM_PROVIDE_FAIL;
422                         xpt_done(ccb);
423                         return;
424                 }
425
426                 /*
427                  * get an scb to use.
428                  */
429                 tinfo = ahd_fetch_transinfo(ahd, 'A', our_id,
430                                             target_id, &tstate);
431                 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0
432                  || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0
433                  || ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
434                         col_idx = AHD_NEVER_COL_IDX;
435                 } else {
436                         col_idx = AHD_BUILD_COL_IDX(target_id,
437                                                     ccb->ccb_h.target_lun);
438                 }
439                 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
440         
441                         xpt_freeze_simq(sim, /*count*/1);
442                         ahd->flags |= AHD_RESOURCE_SHORTAGE;
443                         ccb->ccb_h.status = CAM_REQUEUE_REQ;
444                         xpt_done(ccb);
445                         return;
446                 }
447                 
448                 hscb = scb->hscb;
449                 
450                 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE,
451                           ("start scb(%p)\n", scb));
452                 scb->io_ctx = ccb;
453                 /*
454                  * So we can find the SCB when an abort is requested
455                  */
456                 ccb->ccb_h.ccb_scb_ptr = scb;
457
458                 /*
459                  * Put all the arguments for the xfer in the scb
460                  */
461                 hscb->control = 0;
462                 hscb->scsiid = BUILD_SCSIID(ahd, sim, target_id, our_id);
463                 hscb->lun = ccb->ccb_h.target_lun;
464                 if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
465                         hscb->cdb_len = 0;
466                         scb->flags |= SCB_DEVICE_RESET;
467                         hscb->control |= MK_MESSAGE;
468                         hscb->task_management = SIU_TASKMGMT_LUN_RESET;
469                         ahd_execute_scb(scb, NULL, 0, 0);
470                 } else {
471 #ifdef AHD_TARGET_MODE
472                         if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
473                                 struct target_data *tdata;
474
475                                 tdata = &hscb->shared_data.tdata;
476                                 if (ahd->pending_device == lstate)
477                                         scb->flags |= SCB_TARGET_IMMEDIATE;
478                                 hscb->control |= TARGET_SCB;
479                                 tdata->target_phases = 0;
480                                 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
481                                         tdata->target_phases |= SPHASE_PENDING;
482                                         tdata->scsi_status =
483                                             ccb->csio.scsi_status;
484                                 }
485                                 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT)
486                                         tdata->target_phases |= NO_DISCONNECT;
487
488                                 tdata->initiator_tag =
489                                     ahd_htole16(ccb->csio.tag_id);
490                         }
491 #endif
492                         hscb->task_management = 0;
493                         if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID)
494                                 hscb->control |= ccb->csio.tag_action;
495                         
496                         ahd_setup_data(ahd, sim, &ccb->csio, scb);
497                 }
498                 break;
499         }
500 #ifdef AHD_TARGET_MODE
501         case XPT_NOTIFY_ACK:
502         case XPT_IMMED_NOTIFY:
503         {
504                 struct     ahd_tmode_tstate *tstate;
505                 struct     ahd_tmode_lstate *lstate;
506                 cam_status status;
507
508                 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate,
509                                              &lstate, TRUE);
510
511                 if (status != CAM_REQ_CMP) {
512                         ccb->ccb_h.status = status;
513                         xpt_done(ccb);
514                         break;
515                 }
516                 SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h,
517                                   sim_links.sle);
518                 ccb->ccb_h.status = CAM_REQ_INPROG;
519                 ahd_send_lstate_events(ahd, lstate);
520                 break;
521         }
522         case XPT_EN_LUN:                /* Enable LUN as a target */
523                 ahd_handle_en_lun(ahd, sim, ccb);
524                 xpt_done(ccb);
525                 break;
526 #endif
527         case XPT_ABORT:                 /* Abort the specified CCB */
528         {
529                 ahd_abort_ccb(ahd, sim, ccb);
530                 break;
531         }
532         case XPT_SET_TRAN_SETTINGS:
533         {
534                 ahd_set_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
535                                       SIM_CHANNEL(ahd, sim), &ccb->cts);
536                 xpt_done(ccb);
537                 break;
538         }
539         case XPT_GET_TRAN_SETTINGS:
540         /* Get default/user set transfer settings for the target */
541         {
542                 ahd_get_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
543                                       SIM_CHANNEL(ahd, sim), &ccb->cts);
544                 xpt_done(ccb);
545                 break;
546         }
547         case XPT_CALC_GEOMETRY:
548         {
549                 aic_calc_geometry(&ccb->ccg, ahd->flags & AHD_EXTENDED_TRANS_A);
550                 xpt_done(ccb);
551                 break;
552         }
553         case XPT_RESET_BUS:             /* Reset the specified SCSI bus */
554         {
555                 int  found;
556                 
557                 found = ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
558                                           /*initiate reset*/TRUE);
559                 if (bootverbose) {
560                         xpt_print_path(SIM_PATH(ahd, sim));
561                         printf("SCSI bus reset delivered. "
562                                "%d SCBs aborted.\n", found);
563                 }
564                 ccb->ccb_h.status = CAM_REQ_CMP;
565                 xpt_done(ccb);
566                 break;
567         }
568         case XPT_TERM_IO:               /* Terminate the I/O process */
569                 /* XXX Implement */
570                 ccb->ccb_h.status = CAM_REQ_INVALID;
571                 xpt_done(ccb);
572                 break;
573         case XPT_PATH_INQ:              /* Path routing inquiry */
574         {
575                 struct ccb_pathinq *cpi = &ccb->cpi;
576                 
577                 cpi->version_num = 1; /* XXX??? */
578                 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
579                 if ((ahd->features & AHD_WIDE) != 0)
580                         cpi->hba_inquiry |= PI_WIDE_16;
581                 if ((ahd->features & AHD_TARGETMODE) != 0) {
582                         cpi->target_sprt = PIT_PROCESSOR
583                                          | PIT_DISCONNECT
584                                          | PIT_TERM_IO;
585                 } else {
586                         cpi->target_sprt = 0;
587                 }
588                 cpi->hba_misc = 0;
589                 cpi->hba_eng_cnt = 0;
590                 cpi->max_target = (ahd->features & AHD_WIDE) ? 15 : 7;
591                 cpi->max_lun = AHD_NUM_LUNS_NONPKT - 1;
592                 cpi->initiator_id = ahd->our_id;
593                 if ((ahd->flags & AHD_RESET_BUS_A) == 0) {
594                         cpi->hba_misc |= PIM_NOBUSRESET;
595                 }
596                 cpi->bus_id = cam_sim_bus(sim);
597                 cpi->base_transfer_speed = 3300;
598                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
599                 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
600                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
601                 cpi->unit_number = cam_sim_unit(sim);
602                 cpi->protocol = PROTO_SCSI;
603                 cpi->protocol_version = SCSI_REV_2;
604                 cpi->transport = XPORT_SPI;
605                 cpi->transport_version = 4;
606                 cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_DT_ST
607                                                     | SID_SPI_IUS
608                                                     | SID_SPI_QAS;
609                 cpi->ccb_h.status = CAM_REQ_CMP;
610                 xpt_done(ccb);
611                 break;
612         }
613         default:
614                 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
615                 xpt_done(ccb);
616                 break;
617         }
618 }
619
620
621 static void
622 ahd_set_tran_settings(struct ahd_softc *ahd, int our_id, char channel,
623                       struct ccb_trans_settings *cts)
624 {
625         struct    ahd_devinfo devinfo;
626         struct    ccb_trans_settings_scsi *scsi;
627         struct    ccb_trans_settings_spi *spi;
628         struct    ahd_initiator_tinfo *tinfo;
629         struct    ahd_tmode_tstate *tstate;
630         uint16_t *discenable;
631         uint16_t *tagenable;
632         u_int     update_type;
633
634         scsi = &cts->proto_specific.scsi;
635         spi = &cts->xport_specific.spi;
636         ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim),
637                             cts->ccb_h.target_id,
638                             cts->ccb_h.target_lun,
639                             SIM_CHANNEL(ahd, sim),
640                             ROLE_UNKNOWN);
641         tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
642                                     devinfo.our_scsiid,
643                                     devinfo.target, &tstate);
644         update_type = 0;
645         if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
646                 update_type |= AHD_TRANS_GOAL;
647                 discenable = &tstate->discenable;
648                 tagenable = &tstate->tagenable;
649                 tinfo->curr.protocol_version = cts->protocol_version;
650                 tinfo->curr.transport_version = cts->transport_version;
651                 tinfo->goal.protocol_version = cts->protocol_version;
652                 tinfo->goal.transport_version = cts->transport_version;
653         } else if (cts->type == CTS_TYPE_USER_SETTINGS) {
654                 update_type |= AHD_TRANS_USER;
655                 discenable = &ahd->user_discenable;
656                 tagenable = &ahd->user_tagenable;
657                 tinfo->user.protocol_version = cts->protocol_version;
658                 tinfo->user.transport_version = cts->transport_version;
659         } else {
660                 cts->ccb_h.status = CAM_REQ_INVALID;
661                 return;
662         }
663         
664         if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
665                 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
666                         *discenable |= devinfo.target_mask;
667                 else
668                         *discenable &= ~devinfo.target_mask;
669         }
670         
671         if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
672                 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
673                         *tagenable |= devinfo.target_mask;
674                 else
675                         *tagenable &= ~devinfo.target_mask;
676         }       
677
678         if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
679                 ahd_validate_width(ahd, /*tinfo limit*/NULL,
680                                    &spi->bus_width, ROLE_UNKNOWN);
681                 ahd_set_width(ahd, &devinfo, spi->bus_width,
682                               update_type, /*paused*/FALSE);
683         }
684
685         if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) {
686                 if (update_type == AHD_TRANS_USER)
687                         spi->ppr_options = tinfo->user.ppr_options;
688                 else
689                         spi->ppr_options = tinfo->goal.ppr_options;
690         }
691
692         if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) {
693                 if (update_type == AHD_TRANS_USER)
694                         spi->sync_offset = tinfo->user.offset;
695                 else
696                         spi->sync_offset = tinfo->goal.offset;
697         }
698
699         if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) {
700                 if (update_type == AHD_TRANS_USER)
701                         spi->sync_period = tinfo->user.period;
702                 else
703                         spi->sync_period = tinfo->goal.period;
704         }
705
706         if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0)
707          || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) {
708                 u_int   maxsync;
709
710                 maxsync = AHD_SYNCRATE_MAX;
711
712                 if (spi->bus_width != MSG_EXT_WDTR_BUS_16_BIT)
713                         spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ;
714
715                 if ((*discenable & devinfo.target_mask) == 0)
716                         spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ;
717
718                 ahd_find_syncrate(ahd, &spi->sync_period,
719                                   &spi->ppr_options, maxsync);
720                 ahd_validate_offset(ahd, /*tinfo limit*/NULL,
721                                     spi->sync_period, &spi->sync_offset,
722                                     spi->bus_width, ROLE_UNKNOWN);
723
724                 /* We use a period of 0 to represent async */
725                 if (spi->sync_offset == 0) {
726                         spi->sync_period = 0;
727                         spi->ppr_options = 0;
728                 }
729
730                 ahd_set_syncrate(ahd, &devinfo, spi->sync_period,
731                                  spi->sync_offset, spi->ppr_options,
732                                  update_type, /*paused*/FALSE);
733         }
734         cts->ccb_h.status = CAM_REQ_CMP;
735 }
736
737 static void
738 ahd_get_tran_settings(struct ahd_softc *ahd, int our_id, char channel,
739                       struct ccb_trans_settings *cts)
740 {
741         struct  ahd_devinfo devinfo;
742         struct  ccb_trans_settings_scsi *scsi;
743         struct  ccb_trans_settings_spi *spi;
744         struct  ahd_initiator_tinfo *targ_info;
745         struct  ahd_tmode_tstate *tstate;
746         struct  ahd_transinfo *tinfo;
747
748         scsi = &cts->proto_specific.scsi;
749         spi = &cts->xport_specific.spi;
750         ahd_compile_devinfo(&devinfo, our_id,
751                             cts->ccb_h.target_id,
752                             cts->ccb_h.target_lun,
753                             channel, ROLE_UNKNOWN);
754         targ_info = ahd_fetch_transinfo(ahd, devinfo.channel,
755                                         devinfo.our_scsiid,
756                                         devinfo.target, &tstate);
757         
758         if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
759                 tinfo = &targ_info->curr;
760         else
761                 tinfo = &targ_info->user;
762         
763         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
764         spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
765         if (cts->type == CTS_TYPE_USER_SETTINGS) {
766                 if ((ahd->user_discenable & devinfo.target_mask) != 0)
767                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
768
769                 if ((ahd->user_tagenable & devinfo.target_mask) != 0)
770                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
771         } else {
772                 if ((tstate->discenable & devinfo.target_mask) != 0)
773                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
774
775                 if ((tstate->tagenable & devinfo.target_mask) != 0)
776                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
777         }
778         cts->protocol_version = tinfo->protocol_version;
779         cts->transport_version = tinfo->transport_version;
780
781         spi->sync_period = tinfo->period;
782         spi->sync_offset = tinfo->offset;
783         spi->bus_width = tinfo->width;
784         spi->ppr_options = tinfo->ppr_options;
785         
786         cts->protocol = PROTO_SCSI;
787         cts->transport = XPORT_SPI;
788         spi->valid = CTS_SPI_VALID_SYNC_RATE
789                    | CTS_SPI_VALID_SYNC_OFFSET
790                    | CTS_SPI_VALID_BUS_WIDTH
791                    | CTS_SPI_VALID_PPR_OPTIONS;
792
793         if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
794                 scsi->valid = CTS_SCSI_VALID_TQ;
795                 spi->valid |= CTS_SPI_VALID_DISC;
796         } else {
797                 scsi->valid = 0;
798         }
799
800         cts->ccb_h.status = CAM_REQ_CMP;
801 }
802
803 static void
804 ahd_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
805 {
806         struct ahd_softc *ahd;
807         struct cam_sim *sim;
808
809         sim = (struct cam_sim *)callback_arg;
810         ahd = (struct ahd_softc *)cam_sim_softc(sim);
811         switch (code) {
812         case AC_LOST_DEVICE:
813         {
814                 struct  ahd_devinfo devinfo;
815
816                 ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim),
817                                     xpt_path_target_id(path),
818                                     xpt_path_lun_id(path),
819                                     SIM_CHANNEL(ahd, sim),
820                                     ROLE_UNKNOWN);
821
822                 /*
823                  * Revert to async/narrow transfers
824                  * for the next device.
825                  */
826                 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
827                               AHD_TRANS_GOAL|AHD_TRANS_CUR, /*paused*/FALSE);
828                 ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
829                                  /*ppr_options*/0, AHD_TRANS_GOAL|AHD_TRANS_CUR,
830                                  /*paused*/FALSE);
831                 break;
832         }
833         default:
834                 break;
835         }
836 }
837
838 static void
839 ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
840                 int error)
841 {
842         struct  scb *scb;
843         union   ccb *ccb;
844         struct  ahd_softc *ahd;
845         struct  ahd_initiator_tinfo *tinfo;
846         struct  ahd_tmode_tstate *tstate;
847         u_int   mask;
848
849         scb = (struct scb *)arg;
850         ccb = scb->io_ctx;
851         ahd = scb->ahd_softc;
852
853         if (error != 0) {
854                 if (error == EFBIG)
855                         aic_set_transaction_status(scb, CAM_REQ_TOO_BIG);
856                 else
857                         aic_set_transaction_status(scb, CAM_REQ_CMP_ERR);
858                 if (nsegments != 0)
859                         bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap);
860                 ahd_free_scb(ahd, scb);
861                 xpt_done(ccb);
862                 return;
863         }
864         scb->sg_count = 0;
865         if (nsegments != 0) {
866                 void *sg;
867                 bus_dmasync_op_t op;
868                 u_int i;
869
870                 /* Copy the segments into our SG list */
871                 for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
872
873                         sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
874                                           dm_segs->ds_len,
875                                           /*last*/i == 1);
876                         dm_segs++;
877                 }
878                 
879                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
880                         op = BUS_DMASYNC_PREREAD;
881                 else
882                         op = BUS_DMASYNC_PREWRITE;
883
884                 bus_dmamap_sync(ahd->buffer_dmat, scb->dmamap, op);
885
886                 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
887                         struct target_data *tdata;
888
889                         tdata = &scb->hscb->shared_data.tdata;
890                         tdata->target_phases |= DPHASE_PENDING;
891                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
892                                 tdata->data_phase = P_DATAOUT;
893                         else
894                                 tdata->data_phase = P_DATAIN;
895                 }
896         }
897
898         /*
899          * Last time we need to check if this SCB needs to
900          * be aborted.
901          */
902         if (aic_get_transaction_status(scb) != CAM_REQ_INPROG) {
903                 if (nsegments != 0)
904                         bus_dmamap_unload(ahd->buffer_dmat,
905                                           scb->dmamap);
906                 ahd_free_scb(ahd, scb);
907                 xpt_done(ccb);
908                 return;
909         }
910
911         tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
912                                     SCSIID_OUR_ID(scb->hscb->scsiid),
913                                     SCSIID_TARGET(ahd, scb->hscb->scsiid),
914                                     &tstate);
915
916         mask = SCB_GET_TARGET_MASK(ahd, scb);
917
918         if ((tstate->discenable & mask) != 0
919          && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
920                 scb->hscb->control |= DISCENB;
921
922         if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
923                 scb->flags |= SCB_PACKETIZED;
924                 if (scb->hscb->task_management != 0)
925                         scb->hscb->control &= ~MK_MESSAGE;
926         }
927
928         if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0
929          && (tinfo->goal.width != 0
930           || tinfo->goal.period != 0
931           || tinfo->goal.ppr_options != 0)) {
932                 scb->flags |= SCB_NEGOTIATE;
933                 scb->hscb->control |= MK_MESSAGE;
934         } else if ((tstate->auto_negotiate & mask) != 0) {
935                 scb->flags |= SCB_AUTO_NEGOTIATE;
936                 scb->hscb->control |= MK_MESSAGE;
937         }
938
939         LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
940
941         ccb->ccb_h.status |= CAM_SIM_QUEUED;
942
943         aic_scb_timer_start(scb);
944
945         if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
946                 /* Define a mapping from our tag to the SCB. */
947                 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
948                 ahd_pause(ahd);
949                 ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
950                 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
951                 ahd_unpause(ahd);
952         } else {
953                 ahd_queue_scb(ahd, scb);
954         }
955
956 }
957
958 static void
959 ahd_poll(struct cam_sim *sim)
960 {
961         ahd_intr(cam_sim_softc(sim));
962 }
963
964 static void
965 ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
966                struct ccb_scsiio *csio, struct scb *scb)
967 {
968         struct hardware_scb *hscb;
969         struct ccb_hdr *ccb_h;
970         
971         hscb = scb->hscb;
972         ccb_h = &csio->ccb_h;
973         
974         csio->resid = 0;
975         csio->sense_resid = 0;
976         if (ccb_h->func_code == XPT_SCSI_IO) {
977                 hscb->cdb_len = csio->cdb_len;
978                 if ((ccb_h->flags & CAM_CDB_POINTER) != 0) {
979
980                         if (hscb->cdb_len > MAX_CDB_LEN
981                          && (ccb_h->flags & CAM_CDB_PHYS) == 0) {
982
983                                 /*
984                                  * Should CAM start to support CDB sizes
985                                  * greater than 16 bytes, we could use
986                                  * the sense buffer to store the CDB.
987                                  */
988                                 aic_set_transaction_status(scb,
989                                                            CAM_REQ_INVALID);
990                                 ahd_free_scb(ahd, scb);
991                                 xpt_done((union ccb *)csio);
992                                 return;
993                         }
994                         if ((ccb_h->flags & CAM_CDB_PHYS) != 0) {
995                                 hscb->shared_data.idata.cdb_from_host.cdbptr =
996                                    aic_htole64((uintptr_t)csio->cdb_io.cdb_ptr);
997                                 hscb->shared_data.idata.cdb_from_host.cdblen =
998                                    csio->cdb_len;
999                                 hscb->cdb_len |= SCB_CDB_LEN_PTR;
1000                         } else {
1001                                 memcpy(hscb->shared_data.idata.cdb, 
1002                                        csio->cdb_io.cdb_ptr,
1003                                        hscb->cdb_len);
1004                         }
1005                 } else {
1006                         if (hscb->cdb_len > MAX_CDB_LEN) {
1007
1008                                 aic_set_transaction_status(scb,
1009                                                            CAM_REQ_INVALID);
1010                                 ahd_free_scb(ahd, scb);
1011                                 xpt_done((union ccb *)csio);
1012                                 return;
1013                         }
1014                         memcpy(hscb->shared_data.idata.cdb,
1015                                csio->cdb_io.cdb_bytes, hscb->cdb_len);
1016                 }
1017         }
1018                 
1019         /* Only use S/G if there is a transfer */
1020         if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1021                 if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) {
1022                         /* We've been given a pointer to a single buffer */
1023                         if ((ccb_h->flags & CAM_DATA_PHYS) == 0) {
1024                                 int s;
1025                                 int error;
1026
1027                                 s = splsoftvm();
1028                                 error = bus_dmamap_load(ahd->buffer_dmat,
1029                                                         scb->dmamap,
1030                                                         csio->data_ptr,
1031                                                         csio->dxfer_len,
1032                                                         ahd_execute_scb,
1033                                                         scb, /*flags*/0);
1034                                 if (error == EINPROGRESS) {
1035                                         /*
1036                                          * So as to maintain ordering,
1037                                          * freeze the controller queue
1038                                          * until our mapping is
1039                                          * returned.
1040                                          */
1041                                         xpt_freeze_simq(sim,
1042                                                         /*count*/1);
1043                                         scb->io_ctx->ccb_h.status |=
1044                                             CAM_RELEASE_SIMQ;
1045                                 }
1046                                 splx(s);
1047                         } else {
1048                                 struct bus_dma_segment seg;
1049
1050                                 /* Pointer to physical buffer */
1051                                 if (csio->dxfer_len > AHD_MAXTRANSFER_SIZE)
1052                                         panic("ahd_setup_data - Transfer size "
1053                                               "larger than can device max");
1054
1055                                 seg.ds_addr =
1056                                     (bus_addr_t)(vm_offset_t)csio->data_ptr;
1057                                 seg.ds_len = csio->dxfer_len;
1058                                 ahd_execute_scb(scb, &seg, 1, 0);
1059                         }
1060                 } else {
1061                         struct bus_dma_segment *segs;
1062
1063                         if ((ccb_h->flags & CAM_DATA_PHYS) != 0)
1064                                 panic("ahd_setup_data - Physical segment "
1065                                       "pointers unsupported");
1066
1067                         if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0)
1068                                 panic("ahd_setup_data - Virtual segment "
1069                                       "addresses unsupported");
1070
1071                         /* Just use the segments provided */
1072                         segs = (struct bus_dma_segment *)csio->data_ptr;
1073                         ahd_execute_scb(scb, segs, csio->sglist_cnt, 0);
1074                 }
1075         } else {
1076                 ahd_execute_scb(scb, NULL, 0, 0);
1077         }
1078 }
1079
1080 static void
1081 ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
1082 {
1083         union ccb *abort_ccb;
1084
1085         abort_ccb = ccb->cab.abort_ccb;
1086         switch (abort_ccb->ccb_h.func_code) {
1087 #ifdef AHD_TARGET_MODE
1088         case XPT_ACCEPT_TARGET_IO:
1089         case XPT_IMMED_NOTIFY:
1090         case XPT_CONT_TARGET_IO:
1091         {
1092                 struct ahd_tmode_tstate *tstate;
1093                 struct ahd_tmode_lstate *lstate;
1094                 struct ccb_hdr_slist *list;
1095                 cam_status status;
1096
1097                 status = ahd_find_tmode_devs(ahd, sim, abort_ccb, &tstate,
1098                                              &lstate, TRUE);
1099
1100                 if (status != CAM_REQ_CMP) {
1101                         ccb->ccb_h.status = status;
1102                         break;
1103                 }
1104
1105                 if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO)
1106                         list = &lstate->accept_tios;
1107                 else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY)
1108                         list = &lstate->immed_notifies;
1109                 else
1110                         list = NULL;
1111
1112                 if (list != NULL) {
1113                         struct ccb_hdr *curelm;
1114                         int found;
1115
1116                         curelm = SLIST_FIRST(list);
1117                         found = 0;
1118                         if (curelm == &abort_ccb->ccb_h) {
1119                                 found = 1;
1120                                 SLIST_REMOVE_HEAD(list, sim_links.sle);
1121                         } else {
1122                                 while(curelm != NULL) {
1123                                         struct ccb_hdr *nextelm;
1124
1125                                         nextelm =
1126                                             SLIST_NEXT(curelm, sim_links.sle);
1127
1128                                         if (nextelm == &abort_ccb->ccb_h) {
1129                                                 found = 1;
1130                                                 SLIST_NEXT(curelm,
1131                                                            sim_links.sle) =
1132                                                     SLIST_NEXT(nextelm,
1133                                                                sim_links.sle);
1134                                                 break;
1135                                         }
1136                                         curelm = nextelm;
1137                                 }
1138                         }
1139
1140                         if (found) {
1141                                 abort_ccb->ccb_h.status = CAM_REQ_ABORTED;
1142                                 xpt_done(abort_ccb);
1143                                 ccb->ccb_h.status = CAM_REQ_CMP;
1144                         } else {
1145                                 xpt_print_path(abort_ccb->ccb_h.path);
1146                                 printf("Not found\n");
1147                                 ccb->ccb_h.status = CAM_PATH_INVALID;
1148                         }
1149                         break;
1150                 }
1151                 /* FALLTHROUGH */
1152         }
1153 #endif
1154         case XPT_SCSI_IO:
1155                 /* XXX Fully implement the hard ones */
1156                 ccb->ccb_h.status = CAM_UA_ABORT;
1157                 break;
1158         default:
1159                 ccb->ccb_h.status = CAM_REQ_INVALID;
1160                 break;
1161         }
1162         xpt_done(ccb);
1163 }
1164
1165 void
1166 ahd_send_async(struct ahd_softc *ahd, char channel, u_int target,
1167                 u_int lun, ac_code code, void *opt_arg)
1168 {
1169         struct  ccb_trans_settings cts;
1170         struct cam_path *path;
1171         void *arg;
1172         int error;
1173
1174         arg = NULL;
1175         error = ahd_create_path(ahd, channel, target, lun, &path);
1176
1177         if (error != CAM_REQ_CMP)
1178                 return;
1179
1180         switch (code) {
1181         case AC_TRANSFER_NEG:
1182         {
1183                 struct  ccb_trans_settings_scsi *scsi;
1184         
1185                 cts.type = CTS_TYPE_CURRENT_SETTINGS;
1186                 scsi = &cts.proto_specific.scsi;
1187                 cts.ccb_h.path = path;
1188                 cts.ccb_h.target_id = target;
1189                 cts.ccb_h.target_lun = lun;
1190                 ahd_get_tran_settings(ahd, ahd->our_id, channel, &cts);
1191                 arg = &cts;
1192                 scsi->valid &= ~CTS_SCSI_VALID_TQ;
1193                 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1194                 if (opt_arg == NULL)
1195                         break;
1196                 if (*((ahd_queue_alg *)opt_arg) == AHD_QUEUE_TAGGED)
1197                         scsi->flags |= ~CTS_SCSI_FLAGS_TAG_ENB;
1198                 scsi->valid |= CTS_SCSI_VALID_TQ;
1199                 break;
1200         }
1201         case AC_SENT_BDR:
1202         case AC_BUS_RESET:
1203                 break;
1204         default:
1205                 panic("ahd_send_async: Unexpected async event");
1206         }
1207         xpt_async(code, path, arg);
1208         xpt_free_path(path);
1209 }
1210
1211 void
1212 ahd_platform_set_tags(struct ahd_softc *ahd,
1213                       struct ahd_devinfo *devinfo, int enable)
1214 {
1215 }
1216
1217 int
1218 ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
1219 {
1220         ahd->platform_data = malloc(sizeof(struct ahd_platform_data), M_DEVBUF,
1221             M_NOWAIT | M_ZERO);
1222         if (ahd->platform_data == NULL)
1223                 return (ENOMEM);
1224         return (0);
1225 }
1226
1227 void
1228 ahd_platform_free(struct ahd_softc *ahd)
1229 {
1230         struct ahd_platform_data *pdata;
1231
1232         pdata = ahd->platform_data;
1233         if (pdata != NULL) {
1234                 if (pdata->regs[0] != NULL)
1235                         bus_release_resource(ahd->dev_softc,
1236                                              pdata->regs_res_type[0],
1237                                              pdata->regs_res_id[0],
1238                                              pdata->regs[0]);
1239
1240                 if (pdata->regs[1] != NULL)
1241                         bus_release_resource(ahd->dev_softc,
1242                                              pdata->regs_res_type[1],
1243                                              pdata->regs_res_id[1],
1244                                              pdata->regs[1]);
1245
1246                 if (pdata->irq != NULL)
1247                         bus_release_resource(ahd->dev_softc,
1248                                              pdata->irq_res_type,
1249                                              0, pdata->irq);
1250
1251                 if (pdata->sim != NULL) {
1252                         xpt_async(AC_LOST_DEVICE, pdata->path, NULL);
1253                         xpt_free_path(pdata->path);
1254                         xpt_bus_deregister(cam_sim_path(pdata->sim));
1255                         cam_sim_free(pdata->sim, /*free_devq*/TRUE);
1256                 }
1257                 if (pdata->eh != NULL)
1258                         EVENTHANDLER_DEREGISTER(shutdown_final, pdata->eh);
1259                 free(ahd->platform_data, M_DEVBUF);
1260         }
1261 }
1262
1263 int
1264 ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
1265 {
1266         /* We don't sort softcs under FreeBSD so report equal always */
1267         return (0);
1268 }
1269
1270 int
1271 ahd_detach(device_t dev)
1272 {
1273         struct ahd_softc *ahd;
1274
1275         device_printf(dev, "detaching device\n");
1276         ahd = device_get_softc(dev);
1277         ahd_lock(ahd);
1278         TAILQ_REMOVE(&ahd_tailq, ahd, links);
1279         ahd_intr_enable(ahd, FALSE);
1280         bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih);
1281         ahd_unlock(ahd);
1282         ahd_free(ahd);
1283         return (0);
1284 }
1285
1286 #if 0
1287 static void
1288 ahd_dump_targcmd(struct target_cmd *cmd)
1289 {
1290         uint8_t *byte;
1291         uint8_t *last_byte;
1292         int i;
1293
1294         byte = &cmd->initiator_channel;
1295         /* Debugging info for received commands */
1296         last_byte = &cmd[1].initiator_channel;
1297
1298         i = 0;
1299         while (byte < last_byte) {
1300                 if (i == 0)
1301                         printf("\t");
1302                 printf("%#x", *byte++);
1303                 i++;
1304                 if (i == 8) {
1305                         printf("\n");
1306                         i = 0;
1307                 } else {
1308                         printf(", ");
1309                 }
1310         }
1311 }
1312 #endif
1313
1314 static int
1315 ahd_modevent(module_t mod, int type, void *data)
1316 {
1317         /* XXX Deal with busy status on unload. */
1318         /* XXX Deal with unknown events */
1319         return 0;
1320 }
1321   
1322 static moduledata_t ahd_mod = {
1323         "ahd",
1324         ahd_modevent,
1325         NULL
1326 };
1327
1328 /********************************** DDB Hooks *********************************/
1329 #ifdef DDB
1330 static struct ahd_softc *ahd_ddb_softc;
1331 static int ahd_ddb_paused;
1332 static int ahd_ddb_paused_on_entry;
1333 DB_COMMAND(ahd_sunit, ahd_ddb_sunit)
1334 {
1335         struct ahd_softc *list_ahd;
1336
1337         ahd_ddb_softc = NULL;
1338         TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
1339                 if (list_ahd->unit == addr)
1340                         ahd_ddb_softc = list_ahd;
1341         }
1342         if (ahd_ddb_softc == NULL)
1343                 db_error("No matching softc found!\n");
1344 }
1345
1346 DB_COMMAND(ahd_pause, ahd_ddb_pause)
1347 {
1348         if (ahd_ddb_softc == NULL) {
1349                 db_error("Must set unit with ahd_sunit first!\n");
1350                 return;
1351         }
1352         if (ahd_ddb_paused == 0) {
1353                 ahd_ddb_paused++;
1354                 if (ahd_is_paused(ahd_ddb_softc)) {
1355                         ahd_ddb_paused_on_entry++;
1356                         return;
1357                 }
1358                 ahd_pause(ahd_ddb_softc);
1359         }
1360 }
1361
1362 DB_COMMAND(ahd_unpause, ahd_ddb_unpause)
1363 {
1364         if (ahd_ddb_softc == NULL) {
1365                 db_error("Must set unit with ahd_sunit first!\n");
1366                 return;
1367         }
1368         if (ahd_ddb_paused != 0) {
1369                 ahd_ddb_paused = 0;
1370                 if (ahd_ddb_paused_on_entry)
1371                         return;
1372                 ahd_unpause(ahd_ddb_softc);
1373         } else if (ahd_ddb_paused_on_entry != 0) {
1374                 /* Two unpauses to clear a paused on entry. */
1375                 ahd_ddb_paused_on_entry = 0;
1376                 ahd_unpause(ahd_ddb_softc);
1377         }
1378 }
1379
1380 DB_COMMAND(ahd_in, ahd_ddb_in)
1381 {
1382         int c;
1383         int size;
1384  
1385         if (ahd_ddb_softc == NULL) {
1386                 db_error("Must set unit with ahd_sunit first!\n");
1387                 return;
1388         }
1389         if (have_addr == 0)
1390                 return;
1391
1392         size = 1;
1393         while ((c = *modif++) != '\0') {
1394                 switch (c) {
1395                 case 'b':
1396                         size = 1;
1397                         break;
1398                 case 'w':
1399                         size = 2;
1400                         break;
1401                 case 'l':
1402                         size = 4;
1403                 break;
1404                 }
1405         }
1406
1407         if (count <= 0)
1408                 count = 1;
1409         while (--count >= 0) {
1410                 db_printf("%04lx (M)%x: \t", (u_long)addr,
1411                           ahd_inb(ahd_ddb_softc, MODE_PTR));
1412                 switch (size) {
1413                 case 1:
1414                         db_printf("%02x\n", ahd_inb(ahd_ddb_softc, addr));
1415                         break;
1416                 case 2:
1417                         db_printf("%04x\n", ahd_inw(ahd_ddb_softc, addr));
1418                         break;
1419                 case 4:
1420                         db_printf("%08x\n", ahd_inl(ahd_ddb_softc, addr));
1421                         break;
1422                 }
1423         }
1424 }
1425
1426 DB_FUNC(ahd_out, ahd_ddb_out, db_cmd_set, CS_MORE, NULL)
1427 {
1428         db_expr_t old_value;
1429         db_expr_t new_value;
1430         int       size;
1431  
1432         if (ahd_ddb_softc == NULL) {
1433                 db_error("Must set unit with ahd_sunit first!\n");
1434                 return;
1435         }
1436
1437         switch (modif[0]) {
1438         case '\0':
1439         case 'b':
1440                 size = 1;
1441                 break;
1442         case 'h':
1443                 size = 2;
1444                 break;
1445         case 'l':
1446                 size = 4;
1447                 break;
1448         default:
1449                 db_error("Unknown size\n");
1450                 return;
1451         }
1452  
1453         while (db_expression(&new_value)) {
1454                 switch (size) {
1455                 default:
1456                 case 1:
1457                         old_value = ahd_inb(ahd_ddb_softc, addr);
1458                         ahd_outb(ahd_ddb_softc, addr, new_value);
1459                         break;
1460                 case 2:
1461                         old_value = ahd_inw(ahd_ddb_softc, addr);
1462                         ahd_outw(ahd_ddb_softc, addr, new_value);
1463                         break;
1464                 case 4:
1465                         old_value = ahd_inl(ahd_ddb_softc, addr);
1466                         ahd_outl(ahd_ddb_softc, addr, new_value);
1467                         break;
1468                 }
1469                 db_printf("%04lx (M)%x: \t0x%lx\t=\t0x%lx",
1470                           (u_long)addr, ahd_inb(ahd_ddb_softc, MODE_PTR),
1471                           (u_long)old_value, (u_long)new_value);
1472                 addr += size;
1473         }
1474         db_skip_to_eol();
1475 }
1476
1477 DB_COMMAND(ahd_dump, ahd_ddb_dump)
1478 {
1479         if (ahd_ddb_softc == NULL) {
1480                 db_error("Must set unit with ahd_sunit first!\n");
1481                 return;
1482         }
1483         ahd_dump_card_state(ahd_ddb_softc);
1484 }
1485
1486 #endif
1487
1488
1489 DECLARE_MODULE(ahd, ahd_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
1490 MODULE_DEPEND(ahd, cam, 1, 1, 1);
1491 MODULE_VERSION(ahd, 1);