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