]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/aic7xxx/aic79xx_osm.c
This commit was generated by cvs2svn to compensate for changes in r105765,
[FreeBSD/FreeBSD.git] / sys / dev / aic7xxx / aic79xx_osm.c
1 /*
2  * Bus independent FreeBSD shim for the aic7xxx based adaptec SCSI controllers
3  *
4  * Copyright (c) 1994-2002 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#22 $
33  *
34  * $FreeBSD$
35  */
36
37 #include <dev/aic7xxx/aic79xx_osm.h>
38 #include <dev/aic7xxx/aic79xx_inline.h>
39
40 #include "opt_ddb.h"
41 #ifdef DDB
42 #include <ddb/ddb.h>
43 #endif
44
45 #ifndef AHD_TMODE_ENABLE
46 #define AHD_TMODE_ENABLE 0
47 #endif
48
49 #define ccb_scb_ptr spriv_ptr0
50
51 #if UNUSED
52 static void     ahd_dump_targcmd(struct target_cmd *cmd);
53 #endif
54 static int      ahd_modevent(module_t mod, int type, void *data);
55 static void     ahd_action(struct cam_sim *sim, union ccb *ccb);
56 static void     ahd_set_tran_settings(struct ahd_softc *ahd,
57                                       int our_id, char channel,
58                                       struct ccb_trans_settings *cts);
59 static void     ahd_get_tran_settings(struct ahd_softc *ahd,
60                                       int our_id, char channel,
61                                       struct ccb_trans_settings *cts);
62 static void     ahd_async(void *callback_arg, uint32_t code,
63                           struct cam_path *path, void *arg);
64 static void     ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
65                                 int nsegments, int error);
66 static void     ahd_poll(struct cam_sim *sim);
67 static void     ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
68                                struct ccb_scsiio *csio, struct scb *scb);
69 static void     ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim,
70                               union ccb *ccb);
71 static int      ahd_create_path(struct ahd_softc *ahd,
72                                 char channel, u_int target, u_int lun,
73                                 struct cam_path **path);
74
75 #if NOT_YET
76 static void     ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb);
77 #endif
78
79 static int
80 ahd_create_path(struct ahd_softc *ahd, char channel, u_int target,
81                 u_int lun, struct cam_path **path)
82 {
83         path_id_t path_id;
84
85         if (channel == 'B')
86                 path_id = cam_sim_path(ahd->platform_data->sim_b);
87         else 
88                 path_id = cam_sim_path(ahd->platform_data->sim);
89
90         return (xpt_create_path(path, /*periph*/NULL,
91                                 path_id, target, lun));
92 }
93
94 int
95 ahd_map_int(struct ahd_softc *ahd)
96 {
97         int error;
98
99         /* Hook up our interrupt handler */
100         error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq,
101                                INTR_TYPE_CAM, ahd_platform_intr, ahd,
102                                &ahd->platform_data->ih);
103         if (error != 0)
104                 device_printf(ahd->dev_softc, "bus_setup_intr() failed: %d\n",
105                               error);
106         return (error);
107 }
108
109 /*
110  * Attach all the sub-devices we can find
111  */
112 int
113 ahd_attach(struct ahd_softc *ahd)
114 {
115         char   ahd_info[256];
116         struct ccb_setasync csa;
117         struct cam_devq *devq;
118         struct cam_sim *sim;
119         struct cam_path *path;
120         long s;
121         int count;
122
123         count = 0;
124         sim = NULL;
125
126         ahd_controller_info(ahd, ahd_info);
127         printf("%s\n", ahd_info);
128         ahd_lock(ahd, &s);
129
130         /*
131          * Create the device queue for our SIM(s).
132          */
133         devq = cam_simq_alloc(AHD_MAX_QUEUE);
134         if (devq == NULL)
135                 goto fail;
136
137         /*
138          * Construct our SIM entry
139          */
140         sim = cam_sim_alloc(ahd_action, ahd_poll, "ahd", ahd,
141                             device_get_unit(ahd->dev_softc),
142                             1, /*XXX*/256, devq);
143         if (sim == NULL) {
144                 cam_simq_free(devq);
145                 goto fail;
146         }
147
148         if (xpt_bus_register(sim, /*bus_id*/0) != CAM_SUCCESS) {
149                 cam_sim_free(sim, /*free_devq*/TRUE);
150                 sim = NULL;
151                 goto fail;
152         }
153         
154         if (xpt_create_path(&path, /*periph*/NULL,
155                             cam_sim_path(sim), CAM_TARGET_WILDCARD,
156                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
157                 xpt_bus_deregister(cam_sim_path(sim));
158                 cam_sim_free(sim, /*free_devq*/TRUE);
159                 sim = NULL;
160                 goto fail;
161         }
162                 
163         xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
164         csa.ccb_h.func_code = XPT_SASYNC_CB;
165         csa.event_enable = AC_LOST_DEVICE;
166         csa.callback = ahd_async;
167         csa.callback_arg = sim;
168         xpt_action((union ccb *)&csa);
169         count++;
170
171 fail:
172         ahd->platform_data->sim = sim;
173         ahd->platform_data->path = path;
174         if (count != 0) {
175                 /* We have to wait until after any system dumps... */
176                 ahd->platform_data->eh =
177                     EVENTHANDLER_REGISTER(shutdown_final, ahd_shutdown,
178                                           ahd, SHUTDOWN_PRI_DEFAULT);
179                 ahd_intr_enable(ahd, TRUE);
180         }
181
182         ahd_unlock(ahd, &s);
183
184         return (count);
185 }
186
187 /*
188  * Catch an interrupt from the adapter
189  */
190 void
191 ahd_platform_intr(void *arg)
192 {
193         struct  ahd_softc *ahd;
194
195         ahd = (struct ahd_softc *)arg; 
196         ahd_intr(ahd);
197 }
198
199 /*
200  * We have an scb which has been processed by the
201  * adaptor, now we look to see how the operation
202  * went.
203  */
204 void
205 ahd_done(struct ahd_softc *ahd, struct scb *scb)
206 {
207         union ccb *ccb;
208
209         CAM_DEBUG(scb->io_ctx->ccb_h.path, CAM_DEBUG_TRACE,
210                   ("ahd_done - scb %d\n", SCB_GET_TAG(scb)));
211
212         ccb = scb->io_ctx;
213         LIST_REMOVE(scb, pending_links);
214
215         untimeout(ahd_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch);
216
217         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
218                 bus_dmasync_op_t op;
219
220                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
221                         op = BUS_DMASYNC_POSTREAD;
222                 else
223                         op = BUS_DMASYNC_POSTWRITE;
224                 bus_dmamap_sync(ahd->buffer_dmat, scb->dmamap, op);
225                 bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap);
226         }
227
228 #ifdef AHD_TARGET_MODE
229         if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
230                 struct cam_path *ccb_path;
231
232                 /*
233                  * If we have finally disconnected, clean up our
234                  * pending device state.
235                  * XXX - There may be error states that cause where
236                  *       we will remain connected.
237                  */
238                 ccb_path = ccb->ccb_h.path;
239                 if (ahd->pending_device != NULL
240                  && xpt_path_comp(ahd->pending_device->path, ccb_path) == 0) {
241
242                         if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
243                                 ahd->pending_device = NULL;
244                         } else {
245                                 xpt_print_path(ccb->ccb_h.path);
246                                 printf("Still disconnected\n");
247                                 ahd_freeze_ccb(ccb);
248                         }
249                 }
250
251                 if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG)
252                         ccb->ccb_h.status |= CAM_REQ_CMP;
253                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
254                 ahd_free_scb(ahd, scb);
255                 xpt_done(ccb);
256                 return;
257         }
258 #endif
259
260         /*
261          * If the recovery SCB completes, we have to be
262          * out of our timeout.
263          */
264         if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
265                 struct  scb *list_scb;
266
267                 /*
268                  * We were able to complete the command successfully,
269                  * so reinstate the timeouts for all other pending
270                  * commands.
271                  */
272                 LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) {
273                         union ccb *ccb;
274                         uint64_t time;
275
276                         ccb = list_scb->io_ctx;
277                         if (ccb->ccb_h.timeout == CAM_TIME_INFINITY)
278                                 continue;
279
280                         time = ccb->ccb_h.timeout;
281                         time *= hz;
282                         time /= 1000;
283                         ccb->ccb_h.timeout_ch = 
284                             timeout(ahd_timeout, list_scb, time);
285                 }
286
287                 if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
288                  || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
289                         ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
290                 ahd_print_path(ahd, scb);
291                 printf("no longer in timeout, status = %x\n",
292                        ccb->ccb_h.status);
293         }
294
295         /* Don't clobber any existing error state */
296         if (ahd_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                 int i;
320
321                 /*
322                  * Copy only the sense data into the provided buffer.
323                  */
324                 siu = (struct scsi_status_iu_header *)scb->sense_data;
325                 sense_len = MIN(scsi_4btoul(siu->sense_length),
326                                 sizeof(ccb->csio.sense_data));
327                 memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
328                 memcpy(&ccb->csio.sense_data,
329                        ahd_get_sense_buf(ahd, scb) + SIU_SENSE_OFFSET(siu),
330                        sense_len);
331                 printf("Copied %d bytes of sense data offset %d:", sense_len,
332                        SIU_SENSE_OFFSET(siu));
333                 for (i = 0; i < sense_len; i++)
334                         printf(" 0x%x", ((uint8_t *)&ccb->csio.sense_data)[i]);
335                 printf("\n");
336                 scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID;
337         }
338         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
339         ahd_free_scb(ahd, scb);
340         xpt_done(ccb);
341 }
342
343 static void
344 ahd_action(struct cam_sim *sim, union ccb *ccb)
345 {
346         struct  ahd_softc *ahd;
347 #ifdef AHD_TARGET_MODE
348         struct  ahd_tmode_lstate *lstate;
349 #endif
350         u_int   target_id;
351         u_int   our_id;
352         long    s;
353
354         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahd_action\n"));
355         
356         ahd = (struct ahd_softc *)cam_sim_softc(sim);
357
358         target_id = ccb->ccb_h.target_id;
359         our_id = SIM_SCSI_ID(ahd, sim);
360         
361         switch (ccb->ccb_h.func_code) {
362         /* Common cases first */
363 #ifdef AHD_TARGET_MODE
364         case XPT_ACCEPT_TARGET_IO:      /* Accept Host Target Mode CDB */
365         case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/
366         {
367                 struct     ahd_tmode_tstate *tstate;
368                 cam_status status;
369
370                 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate,
371                                              &lstate, TRUE);
372
373                 if (status != CAM_REQ_CMP) {
374                         if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
375                                 /* Response from the black hole device */
376                                 tstate = NULL;
377                                 lstate = ahd->black_hole;
378                         } else {
379                                 ccb->ccb_h.status = status;
380                                 xpt_done(ccb);
381                                 break;
382                         }
383                 }
384                 if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
385
386                         ahd_lock(ahd, &s);
387                         SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
388                                           sim_links.sle);
389                         ccb->ccb_h.status = CAM_REQ_INPROG;
390                         if ((ahd->flags & AHD_TQINFIFO_BLOCKED) != 0)
391                                 ahd_run_tqinfifo(ahd, /*paused*/FALSE);
392                         ahd_unlock(ahd, &s);
393                         break;
394                 }
395
396                 /*
397                  * The target_id represents the target we attempt to
398                  * select.  In target mode, this is the initiator of
399                  * the original command.
400                  */
401                 our_id = target_id;
402                 target_id = ccb->csio.init_id;
403                 /* FALLTHROUGH */
404         }
405 #endif
406         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
407         case XPT_RESET_DEV:     /* Bus Device Reset the specified SCSI device */
408         {
409                 struct  scb *scb;
410                 struct  hardware_scb *hscb;     
411                 struct  ahd_initiator_tinfo *tinfo;
412                 struct  ahd_tmode_tstate *tstate;
413                 u_int   col_idx;
414
415                 if ((ahd->flags & AHD_INITIATORROLE) == 0
416                  && (ccb->ccb_h.func_code == XPT_SCSI_IO
417                   || ccb->ccb_h.func_code == XPT_RESET_DEV)) {
418                         ccb->ccb_h.status = CAM_PROVIDE_FAIL;
419                         xpt_done(ccb);
420                         return;
421                 }
422
423                 /*
424                  * get an scb to use.
425                  */
426                 ahd_lock(ahd, &s);
427                 tinfo = ahd_fetch_transinfo(ahd, 'A', our_id,
428                                             target_id, &tstate);
429                 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0
430                  || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0
431                  || ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
432                         col_idx = AHD_NEVER_COL_IDX;
433                 } else {
434                         col_idx = AHD_BUILD_COL_IDX(target_id,
435                                                     ccb->ccb_h.target_lun);
436                 }
437                 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
438         
439                         xpt_freeze_simq(sim, /*count*/1);
440                         ahd->flags |= AHD_RESOURCE_SHORTAGE;
441                         ahd_unlock(ahd, &s);
442                         ccb->ccb_h.status = CAM_REQUEUE_REQ;
443                         xpt_done(ccb);
444                         return;
445                 }
446                 ahd_unlock(ahd, &s);
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                         ahd_execute_scb(scb, NULL, 0, 0);
469                 } else {
470 #ifdef AHD_TARGET_MODE
471                         if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
472                                 struct target_data *tdata;
473
474                                 tdata = &hscb->shared_data.tdata;
475                                 if (ahd->pending_device == lstate)
476                                         scb->flags |= SCB_TARGET_IMMEDIATE;
477                                 hscb->control |= TARGET_SCB;
478                                 tdata->target_phases = 0;
479                                 if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
480                                         tdata->target_phases |= SPHASE_PENDING;
481                                         tdata->scsi_status =
482                                             ccb->csio.scsi_status;
483                                 }
484                                 if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT)
485                                         tdata->target_phases |= NO_DISCONNECT;
486
487                                 tdata->initiator_tag =
488                                     ahd_htole16(ccb->csio.tag_id);
489                         }
490 #endif
491                         if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID)
492                                 hscb->control |= ccb->csio.tag_action;
493                         
494                         ahd_setup_data(ahd, sim, &ccb->csio, scb);
495                 }
496                 break;
497         }
498 #ifdef AHD_TARGET_MODE
499         case XPT_NOTIFY_ACK:
500         case XPT_IMMED_NOTIFY:
501         {
502                 struct     ahd_tmode_tstate *tstate;
503                 struct     ahd_tmode_lstate *lstate;
504                 cam_status status;
505
506                 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate,
507                                              &lstate, TRUE);
508
509                 if (status != CAM_REQ_CMP) {
510                         ccb->ccb_h.status = status;
511                         xpt_done(ccb);
512                         break;
513                 }
514                 SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h,
515                                   sim_links.sle);
516                 ccb->ccb_h.status = CAM_REQ_INPROG;
517                 ahd_send_lstate_events(ahd, lstate);
518                 break;
519         }
520         case XPT_EN_LUN:                /* Enable LUN as a target */
521                 ahd_handle_en_lun(ahd, sim, ccb);
522                 xpt_done(ccb);
523                 break;
524 #endif
525         case XPT_ABORT:                 /* Abort the specified CCB */
526         {
527                 ahd_abort_ccb(ahd, sim, ccb);
528                 break;
529         }
530         case XPT_SET_TRAN_SETTINGS:
531         {
532                 ahd_lock(ahd, &s);
533                 ahd_set_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
534                                       SIM_CHANNEL(ahd, sim), &ccb->cts);
535                 ahd_unlock(ahd, &s);
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_lock(ahd, &s);
543                 ahd_get_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
544                                       SIM_CHANNEL(ahd, sim), &ccb->cts);
545                 ahd_unlock(ahd, &s);
546                 xpt_done(ccb);
547                 break;
548         }
549         case XPT_CALC_GEOMETRY:
550         {
551                 struct    ccb_calc_geometry *ccg;
552                 uint32_t size_mb;
553                 uint32_t secs_per_cylinder;
554                 int       extended;
555
556                 ccg = &ccb->ccg;
557                 size_mb = ccg->volume_size
558                         / ((1024L * 1024L) / ccg->block_size);
559                 extended = ahd->flags & AHD_EXTENDED_TRANS_A;
560                 
561                 if (size_mb > 1024 && extended) {
562                         ccg->heads = 255;
563                         ccg->secs_per_track = 63;
564                 } else {
565                         ccg->heads = 64;
566                         ccg->secs_per_track = 32;
567                 }
568                 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
569                 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
570                 ccb->ccb_h.status = CAM_REQ_CMP;
571                 xpt_done(ccb);
572                 break;
573         }
574         case XPT_RESET_BUS:             /* Reset the specified SCSI bus */
575         {
576                 int  found;
577                 
578                 ahd_lock(ahd, &s);
579                 found = ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
580                                           /*initiate reset*/TRUE);
581                 ahd_unlock(ahd, &s);
582                 if (bootverbose) {
583                         xpt_print_path(SIM_PATH(ahd, sim));
584                         printf("SCSI bus reset delivered. "
585                                "%d SCBs aborted.\n", found);
586                 }
587                 ccb->ccb_h.status = CAM_REQ_CMP;
588                 xpt_done(ccb);
589                 break;
590         }
591         case XPT_TERM_IO:               /* Terminate the I/O process */
592                 /* XXX Implement */
593                 ccb->ccb_h.status = CAM_REQ_INVALID;
594                 xpt_done(ccb);
595                 break;
596         case XPT_PATH_INQ:              /* Path routing inquiry */
597         {
598                 struct ccb_pathinq *cpi = &ccb->cpi;
599                 
600                 cpi->version_num = 1; /* XXX??? */
601                 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
602                 if ((ahd->features & AHD_WIDE) != 0)
603                         cpi->hba_inquiry |= PI_WIDE_16;
604                 if ((ahd->features & AHD_TARGETMODE) != 0) {
605                         cpi->target_sprt = PIT_PROCESSOR
606                                          | PIT_DISCONNECT
607                                          | PIT_TERM_IO;
608                 } else {
609                         cpi->target_sprt = 0;
610                 }
611                 cpi->hba_misc = 0;
612                 cpi->hba_eng_cnt = 0;
613                 cpi->max_target = (ahd->features & AHD_WIDE) ? 15 : 7;
614                 cpi->max_lun = AHD_NUM_LUNS - 1;
615                 cpi->initiator_id = ahd->our_id;
616                 if ((ahd->flags & AHD_RESET_BUS_A) == 0) {
617                         cpi->hba_misc |= PIM_NOBUSRESET;
618                 }
619                 cpi->bus_id = cam_sim_bus(sim);
620                 cpi->base_transfer_speed = 3300;
621                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
622                 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
623                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
624                 cpi->unit_number = cam_sim_unit(sim);
625 #ifdef AHD_NEW_TRAN_SETTINGS
626                 cpi->protocol = PROTO_SCSI;
627                 cpi->protocol_version = SCSI_REV_2;
628                 cpi->transport = XPORT_SPI;
629                 cpi->transport_version = 2;
630                 cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_ST;
631                 cpi->transport_version = 4;
632                 cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_DT_ST;
633 #endif
634                 cpi->ccb_h.status = CAM_REQ_CMP;
635                 xpt_done(ccb);
636                 break;
637         }
638         default:
639                 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
640                 xpt_done(ccb);
641                 break;
642         }
643 }
644
645
646 static void
647 ahd_set_tran_settings(struct ahd_softc *ahd, int our_id, char channel,
648                       struct ccb_trans_settings *cts)
649 {
650 #ifdef AHD_NEW_TRAN_SETTINGS
651         struct    ahd_devinfo devinfo;
652         struct    ccb_trans_settings_scsi *scsi;
653         struct    ccb_trans_settings_spi *spi;
654         struct    ahd_initiator_tinfo *tinfo;
655         struct    ahd_tmode_tstate *tstate;
656         uint16_t *discenable;
657         uint16_t *tagenable;
658         u_int     update_type;
659
660         scsi = &cts->proto_specific.scsi;
661         spi = &cts->xport_specific.spi;
662         ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim),
663                             cts->ccb_h.target_id,
664                             cts->ccb_h.target_lun,
665                             SIM_CHANNEL(ahd, sim),
666                             ROLE_UNKNOWN);
667         tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
668                                     devinfo.our_scsiid,
669                                     devinfo.target, &tstate);
670         update_type = 0;
671         if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
672                 update_type |= AHD_TRANS_GOAL;
673                 discenable = &tstate->discenable;
674                 tagenable = &tstate->tagenable;
675                 tinfo->curr.protocol_version = cts->protocol_version;
676                 tinfo->curr.transport_version = cts->transport_version;
677                 tinfo->goal.protocol_version = cts->protocol_version;
678                 tinfo->goal.transport_version = cts->transport_version;
679         } else if (cts->type == CTS_TYPE_USER_SETTINGS) {
680                 update_type |= AHD_TRANS_USER;
681                 discenable = &ahd->user_discenable;
682                 tagenable = &ahd->user_tagenable;
683                 tinfo->user.protocol_version = cts->protocol_version;
684                 tinfo->user.transport_version = cts->transport_version;
685         } else {
686                 cts->ccb_h.status = CAM_REQ_INVALID;
687                 return;
688         }
689         
690         if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
691                 if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
692                         *discenable |= devinfo.target_mask;
693                 else
694                         *discenable &= ~devinfo.target_mask;
695         }
696         
697         if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
698                 if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
699                         *tagenable |= devinfo.target_mask;
700                 else
701                         *tagenable &= ~devinfo.target_mask;
702         }       
703
704         if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
705                 ahd_validate_width(ahd, /*tinfo limit*/NULL,
706                                    &spi->bus_width, ROLE_UNKNOWN);
707                 ahd_set_width(ahd, &devinfo, spi->bus_width,
708                               update_type, /*paused*/FALSE);
709         }
710
711         if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) {
712                 if (update_type == AHD_TRANS_USER)
713                         spi->ppr_options = tinfo->user.ppr_options;
714                 else
715                         spi->ppr_options = tinfo->goal.ppr_options;
716         }
717
718         if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) {
719                 if (update_type == AHD_TRANS_USER)
720                         spi->sync_offset = tinfo->user.offset;
721                 else
722                         spi->sync_offset = tinfo->goal.offset;
723         }
724
725         if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) {
726                 if (update_type == AHD_TRANS_USER)
727                         spi->sync_period = tinfo->user.period;
728                 else
729                         spi->sync_period = tinfo->goal.period;
730         }
731
732         if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0)
733          || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) {
734                 u_int   maxsync;
735
736                 maxsync = AHD_SYNCRATE_MAX;
737
738                 if (spi->bus_width != MSG_EXT_WDTR_BUS_16_BIT)
739                         spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ;
740
741                 if ((*discenable & devinfo.target_mask) == 0)
742                         spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ;
743
744                 ahd_find_syncrate(ahd, &spi->sync_period,
745                                   &spi->ppr_options, maxsync);
746                 ahd_validate_offset(ahd, /*tinfo limit*/NULL,
747                                     spi->sync_period, &spi->sync_offset,
748                                     spi->bus_width, ROLE_UNKNOWN);
749
750                 /* We use a period of 0 to represent async */
751                 if (spi->sync_offset == 0) {
752                         spi->sync_period = 0;
753                         spi->ppr_options = 0;
754                 }
755
756                 ahd_set_syncrate(ahd, &devinfo, spi->sync_period,
757                                  spi->sync_offset, spi->ppr_options,
758                                  update_type, /*paused*/FALSE);
759         }
760         cts->ccb_h.status = CAM_REQ_CMP;
761 #else
762         struct    ahd_devinfo devinfo;
763         struct    ahd_initiator_tinfo *tinfo;
764         struct    ahd_tmode_tstate *tstate;
765         uint16_t *discenable;
766         uint16_t *tagenable;
767         u_int     update_type;
768
769         ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim),
770                             cts->ccb_h.target_id,
771                             cts->ccb_h.target_lun,
772                             SIM_CHANNEL(ahd, sim),
773                             ROLE_UNKNOWN);
774         tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
775                                     devinfo.our_scsiid,
776                                     devinfo.target, &tstate);
777         update_type = 0;
778         if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) {
779                 update_type |= AHD_TRANS_GOAL;
780                 discenable = &tstate->discenable;
781                 tagenable = &tstate->tagenable;
782         } else if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
783                 update_type |= AHD_TRANS_USER;
784                 discenable = &ahd->user_discenable;
785                 tagenable = &ahd->user_tagenable;
786         } else {
787                 cts->ccb_h.status = CAM_REQ_INVALID;
788                 return;
789         }
790         
791         if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) {
792                 if ((cts->flags & CCB_TRANS_DISC_ENB) != 0)
793                         *discenable |= devinfo.target_mask;
794                 else
795                         *discenable &= ~devinfo.target_mask;
796         }
797         
798         if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) {
799                 if ((cts->flags & CCB_TRANS_TAG_ENB) != 0)
800                         *tagenable |= devinfo.target_mask;
801                 else
802                         *tagenable &= ~devinfo.target_mask;
803         }       
804
805         if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0) {
806                 ahd_validate_width(ahd, /*tinfo limit*/NULL,
807                                    &cts->bus_width, ROLE_UNKNOWN);
808                 ahd_set_width(ahd, &devinfo, cts->bus_width,
809                               update_type, /*paused*/FALSE);
810         }
811
812         if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0) {
813                 if (update_type == AHD_TRANS_USER)
814                         cts->sync_offset = tinfo->user.offset;
815                 else
816                         cts->sync_offset = tinfo->goal.offset;
817         }
818
819         if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0) {
820                 if (update_type == AHD_TRANS_USER)
821                         cts->sync_period = tinfo->user.period;
822                 else
823                         cts->sync_period = tinfo->goal.period;
824         }
825
826         if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)
827          || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
828          || ((cts->valid & CCB_TRANS_TQ_VALID) != 0)
829          || ((cts->valid & CCB_TRANS_DISC_VALID) != 0)) {
830                 u_int ppr_options;
831                 u_int maxsync;
832
833                 maxsync = AHD_SYNCRATE_MAX;
834                 ppr_options = 0;
835                 if (cts->sync_period <= AHD_SYNCRATE_DT
836                  && cts->bus_width == MSG_EXT_WDTR_BUS_16_BIT) {
837                         ppr_options = tinfo->user.ppr_options
838                                     | MSG_EXT_PPR_DT_REQ;
839                 }
840
841                 if ((*tagenable & devinfo.target_mask) == 0
842                  || (*discenable & devinfo.target_mask) == 0)
843                         ppr_options &= ~MSG_EXT_PPR_IU_REQ;
844
845                 ahd_find_syncrate(ahd, &cts->sync_period,
846                                   &ppr_options, maxsync);
847                 ahd_validate_offset(ahd, /*tinfo limit*/NULL,
848                                     cts->sync_period, &cts->sync_offset,
849                                     MSG_EXT_WDTR_BUS_8_BIT,
850                                     ROLE_UNKNOWN);
851
852                 /* We use a period of 0 to represent async */
853                 if (cts->sync_offset == 0) {
854                         cts->sync_period = 0;
855                         ppr_options = 0;
856                 }
857
858                 if (ppr_options != 0
859                  && tinfo->user.transport_version >= 3) {
860                         tinfo->goal.transport_version =
861                             tinfo->user.transport_version;
862                         tinfo->curr.transport_version =
863                             tinfo->user.transport_version;
864                 }
865                 
866                 ahd_set_syncrate(ahd, &devinfo, cts->sync_period,
867                                  cts->sync_offset, ppr_options,
868                                  update_type, /*paused*/FALSE);
869         }
870         cts->ccb_h.status = CAM_REQ_CMP;
871 #endif
872 }
873
874 static void
875 ahd_get_tran_settings(struct ahd_softc *ahd, int our_id, char channel,
876                       struct ccb_trans_settings *cts)
877 {
878 #ifdef AHD_NEW_TRAN_SETTINGS
879         struct  ahd_devinfo devinfo;
880         struct  ccb_trans_settings_scsi *scsi;
881         struct  ccb_trans_settings_spi *spi;
882         struct  ahd_initiator_tinfo *targ_info;
883         struct  ahd_tmode_tstate *tstate;
884         struct  ahd_transinfo *tinfo;
885
886         scsi = &cts->proto_specific.scsi;
887         spi = &cts->xport_specific.spi;
888         ahd_compile_devinfo(&devinfo, our_id,
889                             cts->ccb_h.target_id,
890                             cts->ccb_h.target_lun,
891                             channel, ROLE_UNKNOWN);
892         targ_info = ahd_fetch_transinfo(ahd, devinfo.channel,
893                                         devinfo.our_scsiid,
894                                         devinfo.target, &tstate);
895         
896         if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
897                 tinfo = &targ_info->curr;
898         else
899                 tinfo = &targ_info->user;
900         
901         scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
902         spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
903         if (cts->type == CTS_TYPE_USER_SETTINGS) {
904                 if ((ahd->user_discenable & devinfo.target_mask) != 0)
905                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
906
907                 if ((ahd->user_tagenable & devinfo.target_mask) != 0)
908                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
909         } else {
910                 if ((tstate->discenable & devinfo.target_mask) != 0)
911                         spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
912
913                 if ((tstate->tagenable & devinfo.target_mask) != 0)
914                         scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
915         }
916         cts->protocol_version = tinfo->protocol_version;
917         cts->transport_version = tinfo->transport_version;
918
919         spi->sync_period = tinfo->period;
920         spi->sync_offset = tinfo->offset;
921         spi->bus_width = tinfo->width;
922         spi->ppr_options = tinfo->ppr_options;
923         
924         cts->protocol = PROTO_SCSI;
925         cts->transport = XPORT_SPI;
926         spi->valid = CTS_SPI_VALID_SYNC_RATE
927                    | CTS_SPI_VALID_SYNC_OFFSET
928                    | CTS_SPI_VALID_BUS_WIDTH
929                    | CTS_SPI_VALID_PPR_OPTIONS;
930
931         if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
932                 scsi->valid = CTS_SCSI_VALID_TQ;
933                 spi->valid |= CTS_SPI_VALID_DISC;
934         } else {
935                 scsi->valid = 0;
936         }
937
938         cts->ccb_h.status = CAM_REQ_CMP;
939 #else
940         struct  ahd_devinfo devinfo;
941         struct  ahd_initiator_tinfo *targ_info;
942         struct  ahd_tmode_tstate *tstate;
943         struct  ahd_transinfo *tinfo;
944
945         ahd_compile_devinfo(&devinfo, our_id,
946                             cts->ccb_h.target_id,
947                             cts->ccb_h.target_lun,
948                             channel, ROLE_UNKNOWN);
949         targ_info = ahd_fetch_transinfo(ahd, devinfo.channel,
950                                         devinfo.our_scsiid,
951                                         devinfo.target, &tstate);
952         
953         if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0)
954                 tinfo = &targ_info->curr;
955         else
956                 tinfo = &targ_info->user;
957         
958         cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
959         if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) == 0) {
960                 if ((ahd->user_discenable & devinfo.target_mask) != 0)
961                         cts->flags |= CCB_TRANS_DISC_ENB;
962
963                 if ((ahd->user_tagenable & devinfo.target_mask) != 0)
964                         cts->flags |= CCB_TRANS_TAG_ENB;
965         } else {
966                 if ((tstate->discenable & devinfo.target_mask) != 0)
967                         cts->flags |= CCB_TRANS_DISC_ENB;
968
969                 if ((tstate->tagenable & devinfo.target_mask) != 0)
970                         cts->flags |= CCB_TRANS_TAG_ENB;
971         }
972         cts->sync_period = tinfo->period;
973         cts->sync_offset = tinfo->offset;
974         cts->bus_width = tinfo->width;
975         
976         cts->valid = CCB_TRANS_SYNC_RATE_VALID
977                    | CCB_TRANS_SYNC_OFFSET_VALID
978                    | CCB_TRANS_BUS_WIDTH_VALID;
979
980         if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD)
981                 cts->valid |= CCB_TRANS_DISC_VALID|CCB_TRANS_TQ_VALID;
982
983         cts->ccb_h.status = CAM_REQ_CMP;
984 #endif
985 }
986
987 static void
988 ahd_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
989 {
990         struct ahd_softc *ahd;
991         struct cam_sim *sim;
992
993         sim = (struct cam_sim *)callback_arg;
994         ahd = (struct ahd_softc *)cam_sim_softc(sim);
995         switch (code) {
996         case AC_LOST_DEVICE:
997         {
998                 struct  ahd_devinfo devinfo;
999                 long    s;
1000
1001                 ahd_compile_devinfo(&devinfo, SIM_SCSI_ID(ahd, sim),
1002                                     xpt_path_target_id(path),
1003                                     xpt_path_lun_id(path),
1004                                     SIM_CHANNEL(ahd, sim),
1005                                     ROLE_UNKNOWN);
1006
1007                 /*
1008                  * Revert to async/narrow transfers
1009                  * for the next device.
1010                  */
1011                 ahd_lock(ahd, &s);
1012                 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
1013                               AHD_TRANS_GOAL|AHD_TRANS_CUR, /*paused*/FALSE);
1014                 ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
1015                                  /*ppr_options*/0, AHD_TRANS_GOAL|AHD_TRANS_CUR,
1016                                  /*paused*/FALSE);
1017                 ahd_unlock(ahd, &s);
1018                 break;
1019         }
1020         default:
1021                 break;
1022         }
1023 }
1024
1025 static void
1026 ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
1027                 int error)
1028 {
1029         struct  scb *scb;
1030         union   ccb *ccb;
1031         struct  ahd_softc *ahd;
1032         struct  ahd_initiator_tinfo *tinfo;
1033         struct  ahd_tmode_tstate *tstate;
1034         u_int   mask;
1035         u_long  s;
1036
1037         scb = (struct scb *)arg;
1038         ccb = scb->io_ctx;
1039         ahd = scb->ahd_softc;
1040
1041         if (error != 0) {
1042                 if (error == EFBIG)
1043                         ahd_set_transaction_status(scb, CAM_REQ_TOO_BIG);
1044                 else
1045                         ahd_set_transaction_status(scb, CAM_REQ_CMP_ERR);
1046                 if (nsegments != 0)
1047                         bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap);
1048                 ahd_lock(ahd, &s);
1049                 ahd_free_scb(ahd, scb);
1050                 ahd_unlock(ahd, &s);
1051                 xpt_done(ccb);
1052                 return;
1053         }
1054         scb->sg_count = 0;
1055         if (nsegments != 0) {
1056                 void *sg;
1057                 bus_dmasync_op_t op;
1058                 u_int i;
1059
1060                 /* Copy the segments into our SG list */
1061                 for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
1062
1063                         sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
1064                                           dm_segs->ds_len,
1065                                           /*last*/i == 1);
1066                         dm_segs++;
1067                 }
1068                 
1069                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
1070                         op = BUS_DMASYNC_PREREAD;
1071                 else
1072                         op = BUS_DMASYNC_PREWRITE;
1073
1074                 bus_dmamap_sync(ahd->buffer_dmat, scb->dmamap, op);
1075
1076                 if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
1077                         struct target_data *tdata;
1078
1079                         tdata = &scb->hscb->shared_data.tdata;
1080                         tdata->target_phases |= DPHASE_PENDING;
1081                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
1082                                 tdata->data_phase = P_DATAOUT;
1083                         else
1084                                 tdata->data_phase = P_DATAIN;
1085                 }
1086         }
1087
1088         ahd_lock(ahd, &s);
1089
1090         /*
1091          * Last time we need to check if this SCB needs to
1092          * be aborted.
1093          */
1094         if (ahd_get_transaction_status(scb) != CAM_REQ_INPROG) {
1095                 if (nsegments != 0)
1096                         bus_dmamap_unload(ahd->buffer_dmat,
1097                                           scb->dmamap);
1098                 ahd_free_scb(ahd, scb);
1099                 ahd_unlock(ahd, &s);
1100                 xpt_done(ccb);
1101                 return;
1102         }
1103
1104         tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
1105                                     SCSIID_OUR_ID(scb->hscb->scsiid),
1106                                     SCSIID_TARGET(ahd, scb->hscb->scsiid),
1107                                     &tstate);
1108
1109         mask = SCB_GET_TARGET_MASK(ahd, scb);
1110
1111         if ((tstate->discenable & mask) != 0
1112          && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
1113                 scb->hscb->control |= DISCENB;
1114
1115         if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
1116                 scb->flags |= SCB_PACKETIZED;
1117
1118         if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0
1119          && (tinfo->goal.width != 0
1120           || tinfo->goal.period != 0
1121           || tinfo->goal.ppr_options != 0)) {
1122                 scb->flags |= SCB_NEGOTIATE;
1123                 scb->hscb->control |= MK_MESSAGE;
1124         } else if ((tstate->auto_negotiate & mask) != 0) {
1125                 scb->flags |= SCB_AUTO_NEGOTIATE;
1126                 scb->hscb->control |= MK_MESSAGE;
1127         }
1128
1129         LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
1130
1131         ccb->ccb_h.status |= CAM_SIM_QUEUED;
1132
1133         if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
1134                 uint64_t time;
1135
1136                 if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT)
1137                         ccb->ccb_h.timeout = 5 * 1000;
1138
1139                 time = ccb->ccb_h.timeout;
1140                 time *= hz;
1141                 time /= 1000;
1142                 ccb->ccb_h.timeout_ch =
1143                     timeout(ahd_timeout, (caddr_t)scb, time);
1144         }
1145
1146         if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
1147                 /* Define a mapping from our tag to the SCB. */
1148                 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
1149                 ahd_pause(ahd);
1150                 ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
1151                 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
1152                 ahd_unpause(ahd);
1153         } else {
1154                 ahd_queue_scb(ahd, scb);
1155         }
1156
1157         ahd_unlock(ahd, &s);
1158 }
1159
1160 static void
1161 ahd_poll(struct cam_sim *sim)
1162 {
1163         ahd_intr(cam_sim_softc(sim));
1164 }
1165
1166 static void
1167 ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
1168                struct ccb_scsiio *csio, struct scb *scb)
1169 {
1170         struct hardware_scb *hscb;
1171         struct ccb_hdr *ccb_h;
1172         
1173         hscb = scb->hscb;
1174         ccb_h = &csio->ccb_h;
1175         
1176         csio->resid = 0;
1177         csio->sense_resid = 0;
1178         if (ccb_h->func_code == XPT_SCSI_IO) {
1179                 hscb->cdb_len = csio->cdb_len;
1180                 if ((ccb_h->flags & CAM_CDB_POINTER) != 0) {
1181
1182                         if (hscb->cdb_len > MAX_CDB_LEN
1183                          && (ccb_h->flags & CAM_CDB_PHYS) == 0) {
1184                                 u_long s;
1185
1186                                 ahd_set_transaction_status(scb,
1187                                                            CAM_REQ_INVALID);
1188                                 ahd_lock(ahd, &s);
1189                                 ahd_free_scb(ahd, scb);
1190                                 ahd_unlock(ahd, &s);
1191                                 xpt_done((union ccb *)csio);
1192                                 return;
1193                         }
1194                         if ((ccb_h->flags & CAM_CDB_PHYS) != 0) {
1195                                 hscb->shared_data.idata.cdbptr =
1196                                    ahd_htole64((uintptr_t)csio->cdb_io.cdb_ptr);
1197                         } else {
1198                                 memcpy(hscb->shared_data.idata.cdb, 
1199                                        csio->cdb_io.cdb_ptr,
1200                                        hscb->cdb_len);
1201                         }
1202                 } else {
1203                         if (hscb->cdb_len > MAX_CDB_LEN) {
1204                                 u_long s;
1205
1206                                 ahd_set_transaction_status(scb,
1207                                                            CAM_REQ_INVALID);
1208                                 ahd_lock(ahd, &s);
1209                                 ahd_free_scb(ahd, scb);
1210                                 ahd_unlock(ahd, &s);
1211                                 xpt_done((union ccb *)csio);
1212                                 return;
1213                         }
1214                         memcpy(hscb->shared_data.idata.cdb,
1215                                csio->cdb_io.cdb_bytes, hscb->cdb_len);
1216                 }
1217         }
1218                 
1219         /* Only use S/G if there is a transfer */
1220         if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1221                 if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) {
1222                         /* We've been given a pointer to a single buffer */
1223                         if ((ccb_h->flags & CAM_DATA_PHYS) == 0) {
1224                                 int s;
1225                                 int error;
1226
1227                                 s = splsoftvm();
1228                                 error = bus_dmamap_load(ahd->buffer_dmat,
1229                                                         scb->dmamap,
1230                                                         csio->data_ptr,
1231                                                         csio->dxfer_len,
1232                                                         ahd_execute_scb,
1233                                                         scb, /*flags*/0);
1234                                 if (error == EINPROGRESS) {
1235                                         /*
1236                                          * So as to maintain ordering,
1237                                          * freeze the controller queue
1238                                          * until our mapping is
1239                                          * returned.
1240                                          */
1241                                         xpt_freeze_simq(sim,
1242                                                         /*count*/1);
1243                                         scb->io_ctx->ccb_h.status |=
1244                                             CAM_RELEASE_SIMQ;
1245                                 }
1246                                 splx(s);
1247                         } else {
1248                                 struct bus_dma_segment seg;
1249
1250                                 /* Pointer to physical buffer */
1251                                 if (csio->dxfer_len > AHD_MAXTRANSFER_SIZE)
1252                                         panic("ahd_setup_data - Transfer size "
1253                                               "larger than can device max");
1254
1255                                 seg.ds_addr = (bus_addr_t)csio->data_ptr;
1256                                 seg.ds_len = csio->dxfer_len;
1257                                 ahd_execute_scb(scb, &seg, 1, 0);
1258                         }
1259                 } else {
1260                         struct bus_dma_segment *segs;
1261
1262                         if ((ccb_h->flags & CAM_DATA_PHYS) != 0)
1263                                 panic("ahd_setup_data - Physical segment "
1264                                       "pointers unsupported");
1265
1266                         if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0)
1267                                 panic("ahd_setup_data - Virtual segment "
1268                                       "addresses unsupported");
1269
1270                         /* Just use the segments provided */
1271                         segs = (struct bus_dma_segment *)csio->data_ptr;
1272                         ahd_execute_scb(scb, segs, csio->sglist_cnt, 0);
1273                 }
1274         } else {
1275                 ahd_execute_scb(scb, NULL, 0, 0);
1276         }
1277 }
1278
1279 #if NOT_YET
1280 static void
1281 ahd_set_recoveryscb(struct ahd_softc *ahd, struct scb *scb) {
1282
1283         if ((scb->flags & SCB_RECOVERY_SCB) == 0) {
1284                 struct scb *list_scb;
1285
1286                 scb->flags |= SCB_RECOVERY_SCB;
1287
1288                 /*
1289                  * Take all queued, but not sent SCBs out of the equation.
1290                  * Also ensure that no new CCBs are queued to us while we
1291                  * try to fix this problem.
1292                  */
1293                 if ((scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
1294                         xpt_freeze_simq(SCB_GET_SIM(ahd, scb), /*count*/1);
1295                         scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ;
1296                 }
1297
1298                 /*
1299                  * Go through all of our pending SCBs and remove
1300                  * any scheduled timeouts for them.  We will reschedule
1301                  * them after we've successfully fixed this problem.
1302                  */
1303                 LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) {
1304                         union ccb *ccb;
1305
1306                         ccb = list_scb->io_ctx;
1307                         untimeout(ahd_timeout, list_scb, ccb->ccb_h.timeout_ch);
1308                 }
1309         }
1310 }
1311 #endif
1312
1313 void
1314 ahd_timeout(void *arg)
1315 {
1316         struct  scb       *scb;
1317         struct  ahd_softc *ahd;
1318         ahd_mode_state     saved_modes;
1319         long               s;
1320         int                target;
1321         int                lun;
1322         char               channel;
1323
1324 #if NOT_YET
1325         int                i;
1326         int                found;
1327         u_int              last_phase;
1328 #endif
1329
1330         scb = (struct scb *)arg; 
1331         ahd = (struct ahd_softc *)scb->ahd_softc;
1332
1333         ahd_lock(ahd, &s);
1334
1335         ahd_pause_and_flushwork(ahd);
1336
1337         saved_modes = ahd_save_modes(ahd);
1338 #if 0
1339         ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
1340         ahd_outb(ahd, SCSISIGO, ACKO);
1341         printf("set ACK\n");
1342         ahd_outb(ahd, SCSISIGO, 0);
1343         printf("clearing Ack\n");
1344         ahd_restore_modes(ahd, saved_modes);
1345 #endif
1346         if ((scb->flags & SCB_ACTIVE) == 0) {
1347                 /* Previous timeout took care of me already */
1348                 printf("%s: Timedout SCB already complete. "
1349                        "Interrupts may not be functioning.\n", ahd_name(ahd));
1350                 ahd_unpause(ahd);
1351                 ahd_unlock(ahd, &s);
1352                 return;
1353         }
1354
1355         target = SCB_GET_TARGET(ahd, scb);
1356         channel = SCB_GET_CHANNEL(ahd, scb);
1357         lun = SCB_GET_LUN(scb);
1358
1359         ahd_print_path(ahd, scb);
1360         printf("SCB 0x%x - timed out\n", SCB_GET_TAG(scb));
1361         ahd_dump_card_state(ahd);
1362         ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
1363                           /*initiate reset*/TRUE);
1364         ahd_unlock(ahd, &s);
1365         return;
1366 #if NOT_YET
1367         last_phase = ahd_inb(ahd, LASTPHASE);
1368         if (scb->sg_count > 0) {
1369                 for (i = 0; i < scb->sg_count; i++) {
1370                         printf("sg[%d] - Addr 0x%x : Length %d\n",
1371                                i,
1372                                ((struct ahd_dma_seg *)scb->sg_list)[i].addr,
1373                                ((struct ahd_dma_seg *)scb->sg_list)[i].len
1374                                 & AHD_SG_LEN_MASK);
1375                 }
1376         }
1377         if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
1378                 /*
1379                  * Been down this road before.
1380                  * Do a full bus reset.
1381                  */
1382 bus_reset:
1383                 ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
1384                 found = ahd_reset_channel(ahd, channel, /*Initiate Reset*/TRUE);
1385                 printf("%s: Issued Channel %c Bus Reset. "
1386                        "%d SCBs aborted\n", ahd_name(ahd), channel, found);
1387         } else {
1388                 /*
1389                  * If we are a target, transition to bus free and report
1390                  * the timeout.
1391                  * 
1392                  * The target/initiator that is holding up the bus may not
1393                  * be the same as the one that triggered this timeout
1394                  * (different commands have different timeout lengths).
1395                  * If the bus is idle and we are actiing as the initiator
1396                  * for this request, queue a BDR message to the timed out
1397                  * target.  Otherwise, if the timed out transaction is
1398                  * active:
1399                  *   Initiator transaction:
1400                  *      Stuff the message buffer with a BDR message and assert
1401                  *      ATN in the hopes that the target will let go of the bus
1402                  *      and go to the mesgout phase.  If this fails, we'll
1403                  *      get another timeout 2 seconds later which will attempt
1404                  *      a bus reset.
1405                  *
1406                  *   Target transaction:
1407                  *      Transition to BUS FREE and report the error.
1408                  *      It's good to be the target!
1409                  */
1410                 u_int active_scb_index;
1411                 u_int saved_scbptr;
1412
1413                 saved_scbptr = ahd_get_scbptr(ahd);
1414                 active_scb_index = saved_scbptr;
1415
1416                 if (last_phase != P_BUSFREE 
1417                   && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0
1418                   && (active_scb_index < ahd->scb_data.numscbs)) {
1419                         struct scb *active_scb;
1420
1421                         /*
1422                          * If the active SCB is not us, assume that
1423                          * the active SCB has a longer timeout than
1424                          * the timedout SCB, and wait for the active
1425                          * SCB to timeout.
1426                          */ 
1427                         active_scb = ahd_lookup_scb(ahd, active_scb_index);
1428                         if (active_scb != scb) {
1429                                 struct   ccb_hdr *ccbh;
1430                                 uint64_t newtimeout;
1431
1432                                 ahd_print_path(ahd, scb);
1433                                 printf("Other SCB Timeout%s",
1434                                        (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
1435                                        ? " again\n" : "\n");
1436                                 scb->flags |= SCB_OTHERTCL_TIMEOUT;
1437                                 newtimeout =
1438                                     MAX(active_scb->io_ctx->ccb_h.timeout,
1439                                         scb->io_ctx->ccb_h.timeout);
1440                                 newtimeout *= hz;
1441                                 newtimeout /= 1000;
1442                                 ccbh = &scb->io_ctx->ccb_h;
1443                                 scb->io_ctx->ccb_h.timeout_ch =
1444                                     timeout(ahd_timeout, scb, newtimeout);
1445                                 ahd_unpause(ahd);
1446                                 ahd_unlock(ahd, &s);
1447                                 return;
1448                         } 
1449
1450                         /* It's us */
1451                         if ((scb->hscb->control & TARGET_SCB) != 0) {
1452
1453                                 /*
1454                                  * Send back any queued up transactions
1455                                  * and properly record the error condition.
1456                                  */
1457                                 ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
1458                                                SCB_GET_CHANNEL(ahd, scb),
1459                                                SCB_GET_LUN(scb),
1460                                                SCB_GET_TAG(scb),
1461                                                ROLE_TARGET,
1462                                                CAM_CMD_TIMEOUT);
1463
1464                                 /* Will clear us from the bus */
1465                                 ahd_restart(ahd);
1466                                 ahd_unlock(ahd, &s);
1467                                 return;
1468                         }
1469
1470                         ahd_set_recoveryscb(ahd, active_scb);
1471                         ahd_outb(ahd, MSG_OUT, HOST_MSG);
1472                         ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
1473                         ahd_print_path(ahd, active_scb);
1474                         printf("BDR message in message buffer\n");
1475                         active_scb->flags |= SCB_DEVICE_RESET;
1476                         active_scb->io_ctx->ccb_h.timeout_ch =
1477                             timeout(ahd_timeout, (caddr_t)active_scb, 2 * hz);
1478                         ahd_unpause(ahd);
1479                 } else {
1480                         int      disconnected;
1481
1482                         /* XXX Shouldn't panic.  Just punt instead? */
1483                         if ((scb->hscb->control & TARGET_SCB) != 0)
1484                                 panic("Timed-out target SCB but bus idle");
1485
1486                         if (last_phase != P_BUSFREE
1487                          && (ahd_inb(ahd, SSTAT0) & TARGET) != 0) {
1488                                 /* XXX What happened to the SCB? */
1489                                 /* Hung target selection.  Goto busfree */
1490                                 printf("%s: Hung target selection\n",
1491                                        ahd_name(ahd));
1492                                 ahd_restart(ahd);
1493                                 ahd_unlock(ahd, &s);
1494                                 return;
1495                         }
1496
1497                         if (ahd_search_qinfifo(ahd, target, channel, lun,
1498                                                SCB_GET_TAG(scb), ROLE_INITIATOR,
1499                                                /*status*/0, SEARCH_COUNT) > 0) {
1500                                 disconnected = FALSE;
1501                         } else {
1502                                 disconnected = TRUE;
1503                         }
1504
1505                         if (disconnected) {
1506
1507                                 ahd_set_recoveryscb(ahd, scb);
1508                                 /*
1509                                  * Actually re-queue this SCB in an attempt
1510                                  * to select the device before it reconnects.
1511                                  * In either case (selection or reselection),
1512                                  * we will now issue a target reset to the
1513                                  * timed-out device.
1514                                  *
1515                                  * Set the MK_MESSAGE control bit indicating
1516                                  * that we desire to send a message.  We
1517                                  * also set the disconnected flag since
1518                                  * in the paging case there is no guarantee
1519                                  * that our SCB control byte matches the
1520                                  * version on the card.  We don't want the
1521                                  * sequencer to abort the command thinking
1522                                  * an unsolicited reselection occurred.
1523                                  */
1524                                 scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
1525                                 scb->flags |= SCB_DEVICE_RESET;
1526
1527                                 /*
1528                                  * The sequencer will never re-reference the
1529                                  * in-core SCB.  To make sure we are notified
1530                                  * during reslection, set the MK_MESSAGE flag
1531                                  * in the card's copy of the SCB.
1532                                  */
1533                                 ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
1534                                 ahd_outb(ahd, SCB_CONTROL,
1535                                          ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
1536
1537                                 /*
1538                                  * Clear out any entries in the QINFIFO first
1539                                  * so we are the next SCB for this target
1540                                  * to run.
1541                                  */
1542                                 ahd_search_qinfifo(ahd,
1543                                                    SCB_GET_TARGET(ahd, scb),
1544                                                    channel, SCB_GET_LUN(scb),
1545                                                    SCB_LIST_NULL,
1546                                                    ROLE_INITIATOR,
1547                                                    CAM_REQUEUE_REQ,
1548                                                    SEARCH_COMPLETE);
1549                                 ahd_print_path(ahd, scb);
1550                                 printf("Queuing a BDR SCB\n");
1551                                 ahd_qinfifo_requeue_tail(ahd, scb);
1552                                 ahd_set_scbptr(ahd, saved_scbptr);
1553                                 scb->io_ctx->ccb_h.timeout_ch =
1554                                     timeout(ahd_timeout, (caddr_t)scb, 2 * hz);
1555                                 ahd_unpause(ahd);
1556                         } else {
1557                                 /* Go "immediatly" to the bus reset */
1558                                 /* This shouldn't happen */
1559                                 ahd_set_recoveryscb(ahd, scb);
1560                                 ahd_print_path(ahd, scb);
1561                                 printf("SCB %d: Immediate reset.  "
1562                                         "Flags = 0x%x\n", SCB_GET_TAG(scb),
1563                                         scb->flags);
1564                                 goto bus_reset;
1565                         }
1566                 }
1567         }
1568         ahd_unlock(ahd, &s);
1569 #endif
1570 }
1571
1572 static void
1573 ahd_abort_ccb(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
1574 {
1575         union ccb *abort_ccb;
1576
1577         abort_ccb = ccb->cab.abort_ccb;
1578         switch (abort_ccb->ccb_h.func_code) {
1579 #ifdef AHD_TARGET_MODE
1580         case XPT_ACCEPT_TARGET_IO:
1581         case XPT_IMMED_NOTIFY:
1582         case XPT_CONT_TARGET_IO:
1583         {
1584                 struct ahd_tmode_tstate *tstate;
1585                 struct ahd_tmode_lstate *lstate;
1586                 struct ccb_hdr_slist *list;
1587                 cam_status status;
1588
1589                 status = ahd_find_tmode_devs(ahd, sim, abort_ccb, &tstate,
1590                                              &lstate, TRUE);
1591
1592                 if (status != CAM_REQ_CMP) {
1593                         ccb->ccb_h.status = status;
1594                         break;
1595                 }
1596
1597                 if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO)
1598                         list = &lstate->accept_tios;
1599                 else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY)
1600                         list = &lstate->immed_notifies;
1601                 else
1602                         list = NULL;
1603
1604                 if (list != NULL) {
1605                         struct ccb_hdr *curelm;
1606                         int found;
1607
1608                         curelm = SLIST_FIRST(list);
1609                         found = 0;
1610                         if (curelm == &abort_ccb->ccb_h) {
1611                                 found = 1;
1612                                 SLIST_REMOVE_HEAD(list, sim_links.sle);
1613                         } else {
1614                                 while(curelm != NULL) {
1615                                         struct ccb_hdr *nextelm;
1616
1617                                         nextelm =
1618                                             SLIST_NEXT(curelm, sim_links.sle);
1619
1620                                         if (nextelm == &abort_ccb->ccb_h) {
1621                                                 found = 1;
1622                                                 SLIST_NEXT(curelm,
1623                                                            sim_links.sle) =
1624                                                     SLIST_NEXT(nextelm,
1625                                                                sim_links.sle);
1626                                                 break;
1627                                         }
1628                                         curelm = nextelm;
1629                                 }
1630                         }
1631
1632                         if (found) {
1633                                 abort_ccb->ccb_h.status = CAM_REQ_ABORTED;
1634                                 xpt_done(abort_ccb);
1635                                 ccb->ccb_h.status = CAM_REQ_CMP;
1636                         } else {
1637                                 xpt_print_path(abort_ccb->ccb_h.path);
1638                                 printf("Not found\n");
1639                                 ccb->ccb_h.status = CAM_PATH_INVALID;
1640                         }
1641                         break;
1642                 }
1643                 /* FALLTHROUGH */
1644         }
1645 #endif
1646         case XPT_SCSI_IO:
1647                 /* XXX Fully implement the hard ones */
1648                 ccb->ccb_h.status = CAM_UA_ABORT;
1649                 break;
1650         default:
1651                 ccb->ccb_h.status = CAM_REQ_INVALID;
1652                 break;
1653         }
1654         xpt_done(ccb);
1655 }
1656
1657 void
1658 ahd_send_async(struct ahd_softc *ahd, char channel, u_int target,
1659                 u_int lun, ac_code code, void *opt_arg)
1660 {
1661         struct  ccb_trans_settings cts;
1662         struct cam_path *path;
1663         void *arg;
1664         int error;
1665
1666         arg = NULL;
1667         error = ahd_create_path(ahd, channel, target, lun, &path);
1668
1669         if (error != CAM_REQ_CMP)
1670                 return;
1671
1672         switch (code) {
1673         case AC_TRANSFER_NEG:
1674         {
1675 #ifdef AHD_NEW_TRAN_SETTINGS
1676                 struct  ccb_trans_settings_scsi *scsi;
1677         
1678                 cts.type = CTS_TYPE_CURRENT_SETTINGS;
1679                 scsi = &cts.proto_specific.scsi;
1680 #else
1681                 cts.flags = CCB_TRANS_CURRENT_SETTINGS;
1682 #endif
1683                 cts.ccb_h.path = path;
1684                 cts.ccb_h.target_id = target;
1685                 cts.ccb_h.target_lun = lun;
1686                 ahd_get_tran_settings(ahd, ahd->our_id, channel, &cts);
1687                 arg = &cts;
1688 #ifdef AHD_NEW_TRAN_SETTINGS
1689                 scsi->valid &= ~CTS_SCSI_VALID_TQ;
1690                 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1691 #else
1692                 cts.valid &= ~CCB_TRANS_TQ_VALID;
1693                 cts.flags &= ~CCB_TRANS_TAG_ENB;
1694 #endif
1695                 if (opt_arg == NULL)
1696                         break;
1697                 if (*((ahd_queue_alg *)opt_arg) == AHD_QUEUE_TAGGED)
1698 #ifdef AHD_NEW_TRAN_SETTINGS
1699                         scsi->flags |= ~CTS_SCSI_FLAGS_TAG_ENB;
1700                 scsi->valid |= CTS_SCSI_VALID_TQ;
1701 #else
1702                         cts.flags |= CCB_TRANS_TAG_ENB;
1703                 cts.valid |= CCB_TRANS_TQ_VALID;
1704 #endif
1705                 break;
1706         }
1707         case AC_SENT_BDR:
1708         case AC_BUS_RESET:
1709                 break;
1710         default:
1711                 panic("ahd_send_async: Unexpected async event");
1712         }
1713         xpt_async(code, path, arg);
1714         xpt_free_path(path);
1715 }
1716
1717 void
1718 ahd_platform_set_tags(struct ahd_softc *ahd,
1719                       struct ahd_devinfo *devinfo, int enable)
1720 {
1721 }
1722
1723 int
1724 ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
1725 {
1726         ahd->platform_data = malloc(sizeof(struct ahd_platform_data), M_DEVBUF,
1727             M_NOWAIT | M_ZERO);
1728         if (ahd->platform_data == NULL)
1729                 return (ENOMEM);
1730         return (0);
1731 }
1732
1733 void
1734 ahd_platform_free(struct ahd_softc *ahd)
1735 {
1736         struct ahd_platform_data *pdata;
1737
1738         pdata = ahd->platform_data;
1739         if (pdata != NULL) {
1740                 if (pdata->regs[0] != NULL)
1741                         bus_release_resource(ahd->dev_softc,
1742                                              pdata->regs_res_type[0],
1743                                              pdata->regs_res_id[0],
1744                                              pdata->regs[0]);
1745
1746                 if (pdata->regs[1] != NULL)
1747                         bus_release_resource(ahd->dev_softc,
1748                                              pdata->regs_res_type[1],
1749                                              pdata->regs_res_id[1],
1750                                              pdata->regs[1]);
1751
1752                 if (pdata->irq != NULL)
1753                         bus_release_resource(ahd->dev_softc,
1754                                              pdata->irq_res_type,
1755                                              0, pdata->irq);
1756
1757                 if (pdata->sim_b != NULL) {
1758                         xpt_async(AC_LOST_DEVICE, pdata->path_b, NULL);
1759                         xpt_free_path(pdata->path_b);
1760                         xpt_bus_deregister(cam_sim_path(pdata->sim_b));
1761                         cam_sim_free(pdata->sim_b, /*free_devq*/TRUE);
1762                 }
1763                 if (pdata->sim != NULL) {
1764                         xpt_async(AC_LOST_DEVICE, pdata->path, NULL);
1765                         xpt_free_path(pdata->path);
1766                         xpt_bus_deregister(cam_sim_path(pdata->sim));
1767                         cam_sim_free(pdata->sim, /*free_devq*/TRUE);
1768                 }
1769                 if (pdata->eh != NULL)
1770                         EVENTHANDLER_DEREGISTER(shutdown_final, pdata->eh);
1771                 free(ahd->platform_data, M_DEVBUF);
1772         }
1773 }
1774
1775 int
1776 ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
1777 {
1778         /* We don't sort softcs under FreeBSD so report equal always */
1779         return (0);
1780 }
1781
1782 int
1783 ahd_detach(device_t dev)
1784 {
1785         struct ahd_softc *ahd;
1786         u_long l;
1787         u_long s;
1788
1789         ahd_list_lock(&l);
1790         device_printf(dev, "detaching device\n");
1791         ahd = device_get_softc(dev);
1792         ahd = ahd_find_softc(ahd);
1793         if (ahd == NULL) {
1794                 device_printf(dev, "aic7xxx already detached\n");
1795                 ahd_list_unlock(&l);
1796                 return (ENOENT);
1797         }
1798         ahd_lock(ahd, &s);
1799         ahd_intr_enable(ahd, FALSE);
1800         bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih);
1801         ahd_unlock(ahd, &s);
1802         ahd_free(ahd);
1803         ahd_list_unlock(&l);
1804         return (0);
1805 }
1806
1807 #if UNUSED
1808 static void
1809 ahd_dump_targcmd(struct target_cmd *cmd)
1810 {
1811         uint8_t *byte;
1812         uint8_t *last_byte;
1813         int i;
1814
1815         byte = &cmd->initiator_channel;
1816         /* Debugging info for received commands */
1817         last_byte = &cmd[1].initiator_channel;
1818
1819         i = 0;
1820         while (byte < last_byte) {
1821                 if (i == 0)
1822                         printf("\t");
1823                 printf("%#x", *byte++);
1824                 i++;
1825                 if (i == 8) {
1826                         printf("\n");
1827                         i = 0;
1828                 } else {
1829                         printf(", ");
1830                 }
1831         }
1832 }
1833 #endif
1834
1835 static int
1836 ahd_modevent(module_t mod, int type, void *data)
1837 {
1838         /* XXX Deal with busy status on unload. */
1839         return 0;
1840 }
1841   
1842 static moduledata_t ahd_mod = {
1843         "ahd",
1844         ahd_modevent,
1845         NULL
1846 };
1847
1848 /********************************** DDB Hooks *********************************/
1849 #ifdef DDB
1850 static struct ahd_softc *ahd_ddb_softc;
1851 static int ahd_ddb_paused;
1852 static int ahd_ddb_paused_on_entry;
1853 DB_COMMAND(ahd_set_unit, ahd_ddb_set_unit)
1854 {
1855         struct ahd_softc *list_ahd;
1856
1857         ahd_ddb_softc = NULL;
1858         TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
1859                 if (list_ahd->unit == addr)
1860                         ahd_ddb_softc = list_ahd;
1861         }
1862         if (ahd_ddb_softc == NULL)
1863                 db_error("No matching softc found!\n");
1864 }
1865
1866 DB_COMMAND(ahd_pause, ahd_ddb_pause)
1867 {
1868         if (ahd_ddb_softc == NULL) {
1869                 db_error("Must set unit with ahd_set_unit first!\n");
1870                 return;
1871         }
1872         if (ahd_ddb_paused == 0) {
1873                 ahd_ddb_paused++;
1874                 if (ahd_is_paused(ahd_ddb_softc)) {
1875                         ahd_ddb_paused_on_entry++;
1876                         return;
1877                 }
1878                 ahd_pause(ahd_ddb_softc);
1879         }
1880 }
1881
1882 DB_COMMAND(ahd_unpause, ahd_ddb_unpause)
1883 {
1884         if (ahd_ddb_softc == NULL) {
1885                 db_error("Must set unit with ahd_set_unit first!\n");
1886                 return;
1887         }
1888         if (ahd_ddb_paused != 0) {
1889                 ahd_ddb_paused = 0;
1890                 if (ahd_ddb_paused_on_entry)
1891                         return;
1892                 ahd_unpause(ahd_ddb_softc);
1893         } else if (ahd_ddb_paused_on_entry != 0) {
1894                 /* Two unpauses to clear a paused on entry. */
1895                 ahd_ddb_paused_on_entry = 0;
1896                 ahd_unpause(ahd_ddb_softc);
1897         }
1898 }
1899
1900 DB_COMMAND(ahd_in, ahd_ddb_in)
1901 {
1902         int c;
1903         int size;
1904  
1905         if (ahd_ddb_softc == NULL) {
1906                 db_error("Must set unit with ahd_set_unit first!\n");
1907                 return;
1908         }
1909         if (have_addr == 0)
1910                 return;
1911
1912         size = 1;
1913         while ((c = *modif++) != '\0') {
1914                 switch (c) {
1915                 case 'b':
1916                         size = 1;
1917                         break;
1918                 case 'w':
1919                         size = 2;
1920                         break;
1921                 case 'l':
1922                         size = 4;
1923                 break;
1924                 }
1925         }
1926
1927         if (count <= 0)
1928                 count = 1;
1929         while (--count >= 0) {
1930                 db_printf("%04x (M)%x: \t", addr,
1931                           ahd_inb(ahd_ddb_softc, MODE_PTR));
1932                 switch (size) {
1933                 case 1:
1934                         db_printf("%02x\n", ahd_inb(ahd_ddb_softc, addr));
1935                         break;
1936                 case 2:
1937                         db_printf("%04x\n", ahd_inw(ahd_ddb_softc, addr));
1938                         break;
1939                 case 4:
1940                         db_printf("%08x\n", ahd_inl(ahd_ddb_softc, addr));
1941                         break;
1942                 }
1943         }
1944 }
1945
1946 DB_SET(ahd_out, ahd_ddb_out, db_cmd_set, CS_MORE, NULL)
1947 {
1948         db_expr_t old_value;
1949         db_expr_t new_value;
1950         int       size;
1951  
1952         if (ahd_ddb_softc == NULL) {
1953                 db_error("Must set unit with ahd_set_unit first!\n");
1954                 return;
1955         }
1956
1957         switch (modif[0]) {
1958         case '\0':
1959         case 'b':
1960                 size = 1;
1961                 break;
1962         case 'h':
1963                 size = 2;
1964                 break;
1965         case 'l':
1966                 size = 4;
1967                 break;
1968         default:
1969                 db_error("Unknown size\n");
1970                 return;
1971         }
1972  
1973         while (db_expression(&new_value)) {
1974                 switch (size) {
1975                 default:
1976                 case 1:
1977                         old_value = ahd_inb(ahd_ddb_softc, addr);
1978                         ahd_outb(ahd_ddb_softc, addr, new_value);
1979                         break;
1980                 case 2:
1981                         old_value = ahd_inw(ahd_ddb_softc, addr);
1982                         ahd_outw(ahd_ddb_softc, addr, new_value);
1983                         break;
1984                 case 4:
1985                         old_value = ahd_inl(ahd_ddb_softc, addr);
1986                         ahd_outl(ahd_ddb_softc, addr, new_value);
1987                         break;
1988                 }
1989                 db_printf("%04x (M)%x: \t0x%x\t=\t0x%x",
1990                           addr, ahd_inb(ahd_ddb_softc, MODE_PTR),
1991                           old_value, new_value);
1992                 addr += size;
1993         }
1994         db_skip_to_eol();
1995 }
1996
1997 #endif
1998
1999
2000 DECLARE_MODULE(ahd, ahd_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
2001 MODULE_DEPEND(ahd, cam, 1, 1, 1);
2002 MODULE_VERSION(ahd, 1);