The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/aha/aha.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Generic register and struct definitions for the Adaptech 154x/164x
    3  * SCSI host adapters. Product specific probe and attach routines can
    4  * be found in:
    5  *      aha 1540/1542B/1542C/1542CF/1542CP      aha_isa.c
    6  *
    7  * Copyright (c) 1998 M. Warner Losh.
    8  * All Rights Reserved.
    9  *
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions, and the following disclaimer,
   16  *    without modification, immediately at the beginning of the file.
   17  * 2. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   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  * Derived from bt.c written by:
   33  *
   34  * Copyright (c) 1998 Justin T. Gibbs.
   35  * All rights reserved.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions, and the following disclaimer,
   42  *    without modification, immediately at the beginning of the file.
   43  * 2. The name of the author may not be used to endorse or promote products
   44  *    derived from this software without specific prior written permission.
   45  *
   46  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   49  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   50  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   56  * SUCH DAMAGE.
   57  *
   58  * $FreeBSD$
   59  */
   60 
   61 #include "pnp.h"
   62 
   63 #include <sys/param.h>
   64 #include <sys/systm.h> 
   65 #include <sys/malloc.h>
   66 #include <sys/buf.h>
   67 #include <sys/kernel.h>
   68 #include <sys/sysctl.h>
   69  
   70 #include <machine/bus_pio.h>
   71 #include <machine/bus.h>
   72 #include <machine/clock.h>
   73 
   74 #include <cam/cam.h>
   75 #include <cam/cam_ccb.h>
   76 #include <cam/cam_sim.h>
   77 #include <cam/cam_xpt_sim.h>
   78 #include <cam/cam_debug.h>
   79 
   80 #include <cam/scsi/scsi_message.h>
   81 
   82 #include <vm/vm.h>
   83 #include <vm/pmap.h>
   84 
   85 #if NPNP > 0
   86 #include <i386/isa/isa_device.h>
   87 #include <i386/isa/pnp.h>               /* XXX pnp isn't x86 only */
   88 #endif
   89  
   90 #include <dev/aha/ahareg.h>
   91 
   92 struct aha_softc *aha_softcs[NAHATOT];
   93 
   94 #define MIN(a, b) ((a) < (b) ? (a) : (b))
   95 #define PRVERB(x) if (bootverbose) printf x
   96 
   97 /* Macro to determine that a rev is potentially a new valid one
   98  * so that the driver doesn't keep breaking on new revs as it
   99  * did for the CF and CP.
  100  */
  101 #define PROBABLY_NEW_BOARD(REV) (REV > 0x43 && REV < 0x56)
  102 
  103 #ifndef MAX
  104 #define MAX(a, b) ((a) > (b) ? (a) : (b))
  105 #endif
  106 
  107 /* MailBox Management functions */
  108 static __inline void    ahanextinbox(struct aha_softc *aha);
  109 static __inline void    ahanextoutbox(struct aha_softc *aha);
  110 
  111 static __inline void
  112 ahanextinbox(struct aha_softc *aha)
  113 {
  114         if (aha->cur_inbox == aha->last_inbox)
  115                 aha->cur_inbox = aha->in_boxes;
  116         else
  117                 aha->cur_inbox++;
  118 }
  119 
  120 static __inline void
  121 ahanextoutbox(struct aha_softc *aha)
  122 {
  123         if (aha->cur_outbox == aha->last_outbox)
  124                 aha->cur_outbox = aha->out_boxes;
  125         else
  126                 aha->cur_outbox++;
  127 }
  128 
  129 #define ahautoa24(u,s3)                 \
  130         (s3)[0] = ((u) >> 16) & 0xff;   \
  131         (s3)[1] = ((u) >> 8) & 0xff;    \
  132         (s3)[2] = (u) & 0xff;
  133 
  134 #define aha_a24tou(s3) \
  135         (((s3)[0] << 16) | ((s3)[1] << 8) | (s3)[2])
  136 
  137 /* CCB Mangement functions */
  138 static __inline u_int32_t               ahaccbvtop(struct aha_softc *aha,
  139                                                   struct aha_ccb *accb);
  140 static __inline struct aha_ccb*         ahaccbptov(struct aha_softc *aha,
  141                                                   u_int32_t ccb_addr);
  142 
  143 static __inline u_int32_t
  144 ahaccbvtop(struct aha_softc *aha, struct aha_ccb *accb)
  145 {
  146         return (aha->aha_ccb_physbase
  147               + (u_int32_t)((caddr_t)accb - (caddr_t)aha->aha_ccb_array));
  148 }
  149 static __inline struct aha_ccb *
  150 ahaccbptov(struct aha_softc *aha, u_int32_t ccb_addr)
  151 {
  152         return (aha->aha_ccb_array +
  153               + ((struct aha_ccb*)ccb_addr-(struct aha_ccb*)aha->aha_ccb_physbase));
  154 }
  155 
  156 static struct aha_ccb*  ahagetccb(struct aha_softc *aha);
  157 static __inline void    ahafreeccb(struct aha_softc *aha, struct aha_ccb *accb);
  158 static void             ahaallocccbs(struct aha_softc *aha);
  159 static bus_dmamap_callback_t ahaexecuteccb;
  160 static void             ahadone(struct aha_softc *aha, struct aha_ccb *accb,
  161                                aha_mbi_comp_code_t comp_code);
  162 
  163 /* Host adapter command functions */
  164 static int      ahareset(struct aha_softc* aha, int hard_reset);
  165 
  166 /* Initialization functions */
  167 static int                      ahainitmboxes(struct aha_softc *aha);
  168 static bus_dmamap_callback_t    ahamapmboxes;
  169 static bus_dmamap_callback_t    ahamapccbs;
  170 static bus_dmamap_callback_t    ahamapsgs;
  171 
  172 /* Transfer Negotiation Functions */
  173 static void ahafetchtransinfo(struct aha_softc *aha,
  174                              struct ccb_trans_settings *cts);
  175 
  176 /* CAM SIM entry points */
  177 #define ccb_accb_ptr spriv_ptr0
  178 #define ccb_aha_ptr spriv_ptr1
  179 static void     ahaaction(struct cam_sim *sim, union ccb *ccb);
  180 static void     ahapoll(struct cam_sim *sim);
  181 
  182 /* Our timeout handler */
  183 timeout_t ahatimeout;
  184 
  185 u_long aha_unit = 0;
  186 
  187 /*
  188  * Do our own re-probe protection until a configuration
  189  * manager can do it for us.  This ensures that we don't
  190  * reprobe a card already found by the EISA or PCI probes.
  191  */
  192 struct aha_isa_port aha_isa_ports[] =
  193 {
  194         { 0x130, 0, 4 },
  195         { 0x134, 0, 5 },
  196         { 0x230, 0, 2 },
  197         { 0x234, 0, 3 },
  198         { 0x330, 0, 0 },
  199         { 0x334, 0, 1 }
  200 };
  201 
  202 /*
  203  * I/O ports listed in the order enumerated by the
  204  * card for certain op codes.
  205  */
  206 u_int16_t aha_board_ports[] =
  207 {
  208         0x330,
  209         0x334,
  210         0x230,
  211         0x234,
  212         0x130,
  213         0x134
  214 };
  215 
  216 /* Exported functions */
  217 struct aha_softc *
  218 aha_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh)
  219 {
  220         struct  aha_softc *aha;  
  221 
  222         if (unit != AHA_TEMP_UNIT) {
  223                 if (unit >= NAHATOT) {
  224                         printf("aha: unit number (%d) too high\n", unit);
  225                         return NULL;
  226                 }
  227 
  228                 /*
  229                  * Allocate a storage area for us
  230                  */
  231                 if (aha_softcs[unit]) {    
  232                         printf("aha%d: memory already allocated\n", unit);
  233                         return NULL;    
  234                 }
  235         }
  236 
  237         aha = malloc(sizeof(struct aha_softc), M_DEVBUF, M_NOWAIT);
  238         if (!aha) {
  239                 printf("aha%d: cannot malloc!\n", unit);
  240                 return NULL;    
  241         }
  242         bzero(aha, sizeof(struct aha_softc));
  243         SLIST_INIT(&aha->free_aha_ccbs);
  244         LIST_INIT(&aha->pending_ccbs);
  245         SLIST_INIT(&aha->sg_maps);
  246         aha->unit = unit;
  247         aha->tag = tag;
  248         aha->bsh = bsh;
  249         aha->ccb_sg_opcode = INITIATOR_SG_CCB_WRESID;
  250         aha->ccb_ccb_opcode = INITIATOR_CCB_WRESID;
  251 
  252         if (aha->unit != AHA_TEMP_UNIT) {
  253                 aha_softcs[unit] = aha;
  254         }
  255         return (aha);
  256 }
  257 
  258 void
  259 aha_free(struct aha_softc *aha)
  260 {
  261         switch (aha->init_level) {
  262         default:
  263         case 8:
  264         {
  265                 struct sg_map_node *sg_map;
  266 
  267                 while ((sg_map = SLIST_FIRST(&aha->sg_maps))!= NULL) {
  268                         SLIST_REMOVE_HEAD(&aha->sg_maps, links);
  269                         bus_dmamap_unload(aha->sg_dmat,
  270                                           sg_map->sg_dmamap);
  271                         bus_dmamem_free(aha->sg_dmat, sg_map->sg_vaddr,
  272                                         sg_map->sg_dmamap);
  273                         free(sg_map, M_DEVBUF);
  274                 }
  275                 bus_dma_tag_destroy(aha->sg_dmat);
  276         }
  277         case 7:
  278                 bus_dmamap_unload(aha->ccb_dmat, aha->ccb_dmamap);
  279         case 6:
  280                 bus_dmamap_destroy(aha->ccb_dmat, aha->ccb_dmamap);
  281                 bus_dmamem_free(aha->ccb_dmat, aha->aha_ccb_array,
  282                                 aha->ccb_dmamap);
  283         case 5:
  284                 bus_dma_tag_destroy(aha->ccb_dmat);
  285         case 4:
  286                 bus_dmamap_unload(aha->mailbox_dmat, aha->mailbox_dmamap);
  287         case 3:
  288                 bus_dmamem_free(aha->mailbox_dmat, aha->in_boxes,
  289                                 aha->mailbox_dmamap);
  290                 bus_dmamap_destroy(aha->mailbox_dmat, aha->mailbox_dmamap);
  291         case 2:
  292                 bus_dma_tag_destroy(aha->buffer_dmat);
  293         case 1:
  294                 bus_dma_tag_destroy(aha->mailbox_dmat);
  295         case 0:
  296         }
  297         if (aha->unit != AHA_TEMP_UNIT) {
  298                 aha_softcs[aha->unit] = NULL;
  299         }
  300         free(aha, M_DEVBUF);
  301 }
  302 
  303 /*
  304  * Probe the adapter and verify that the card is an Adaptec.
  305  */
  306 int
  307 aha_probe(struct aha_softc* aha)
  308 {
  309         u_int    status;
  310         u_int    intstat;
  311         int      error;
  312         board_id_data_t board_id;
  313 
  314         /*
  315          * See if the three I/O ports look reasonable.
  316          * Touch the minimal number of registers in the
  317          * failure case.
  318          */
  319         status = aha_inb(aha, STATUS_REG);
  320         if ((status == 0)
  321          || (status & (DIAG_ACTIVE|CMD_REG_BUSY|
  322                        STATUS_REG_RSVD)) != 0) {
  323                 PRVERB(("%s: status reg test failed %x\n", aha_name(aha),
  324                         status));
  325                 return (ENXIO);
  326         }
  327 
  328         intstat = aha_inb(aha, INTSTAT_REG);
  329         if ((intstat & INTSTAT_REG_RSVD) != 0) {
  330                 PRVERB(("%s: Failed Intstat Reg Test\n", aha_name(aha)));
  331                 return (ENXIO);
  332         }
  333 
  334         /*
  335          * Looking good so far.  Final test is to reset the
  336          * adapter and fetch the board ID and ensure we aren't
  337          * looking at a BusLogic.
  338          */
  339         if ((error = ahareset(aha, /*hard_reset*/TRUE)) != 0) {
  340                 if (bootverbose)
  341                         printf("%s: Failed Reset\n", aha_name(aha));
  342                 return (ENXIO);
  343         }
  344 
  345         /*
  346          * Get the board ID.  We use this to see if we're dealing with
  347          * a buslogic card or a aha card (or clone).
  348          */
  349         error = aha_cmd(aha, AOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0,
  350                        (u_int8_t*)&board_id, sizeof(board_id),
  351                        DEFAULT_CMD_TIMEOUT);
  352         if (error != 0) {
  353                 PRVERB(("%s: INQUIRE failed %x\n", aha_name(aha), error));
  354                 return (ENXIO);
  355         }
  356         aha->fw_major = board_id.firmware_rev_major;
  357         aha->fw_minor = board_id.firmware_rev_minor;
  358         aha->boardid = board_id.board_type;
  359 
  360         /*
  361          * The Buslogic cards have an id of either 0x41 or 0x42.  So
  362          * if those come up in the probe, we test the geometry register
  363          * of the board.  Adaptec boards that are this old will not have
  364          * this register, and return 0xff, while buslogic cards will return
  365          * something different.  Other aha cards return 0x00 or 0x7f, so
  366          * use them as well.  No buslogic cards seem to return these
  367          * values.
  368          *
  369          * It appears that for reasons unknow, for the for the
  370          * aha-1542B cards, we need to wait a little bit before trying
  371          * to read the geometry register.  I picked 10ms since we have
  372          * reports that a for loop to 1000 did the trick, and this
  373          * errs on the side of conservatism.  Besides, no one will
  374          * notice a 10mS delay here, even the 1542B card users :-)
  375          *
  376          * Some compatible cards return 0 here.
  377          *
  378          * XXX I'm not sure how this will impact other cloned cards 
  379          *
  380          * This really should be replaced with the esetup command, since
  381          * that appears to be more reliable.
  382          */
  383         if (aha->boardid <= 0x42) {
  384                 /* Wait 10ms before reading */
  385                 DELAY(10000);
  386                 status = aha_inb(aha, GEOMETRY_REG);
  387                 if (status != 0xff && status != 0x00 && status != 0x7f) {
  388                         PRVERB(("%s: Geometry Register test failed\n",
  389                                 aha_name(aha)));
  390                         return (ENXIO);
  391                 }
  392         }
  393         
  394         return (0);
  395 }
  396 
  397 /*
  398  * Pull the boards setup information and record it in our softc.
  399  */
  400 int
  401 aha_fetch_adapter_info(struct aha_softc *aha)
  402 {
  403         setup_data_t    setup_info;
  404         config_data_t config_data;
  405         u_int8_t length_param;
  406         int      error;
  407         struct  aha_extbios extbios;
  408         
  409         switch (aha->boardid) {
  410         case BOARD_1540_16HEAD_BIOS:
  411                 snprintf(aha->model, sizeof(aha->model), "1540 16 head BIOS");
  412                 break;
  413         case BOARD_1540_64HEAD_BIOS:
  414                 snprintf(aha->model, sizeof(aha->model), "1540 64 head BIOS");
  415                 break;
  416         case BOARD_1542:
  417                 snprintf(aha->model, sizeof(aha->model), "1540/1542 64 head BIOS");
  418                 break;
  419         case BOARD_1640:
  420                 snprintf(aha->model, sizeof(aha->model), "1640");
  421                 break;
  422         case BOARD_1740:
  423                 snprintf(aha->model, sizeof(aha->model), "1740A/1742A/1744");
  424                 break;
  425         case BOARD_1542C:
  426                 snprintf(aha->model, sizeof(aha->model), "1542C");
  427                 break;
  428         case BOARD_1542CF:
  429                 snprintf(aha->model, sizeof(aha->model), "1542CF");
  430                 break;
  431         case BOARD_1542CP:
  432                 snprintf(aha->model, sizeof(aha->model), "1542CP");
  433                 break;
  434         default:
  435                 snprintf(aha->model, sizeof(aha->model), "Unknown");
  436                 break;
  437         }
  438         /*
  439          * If we are a new type of 1542 board (anything newer than a 1542C)
  440          * then disable the extended bios so that the
  441          * mailbox interface is unlocked.
  442          * This is also true for the 1542B Version 3.20. First Adaptec
  443          * board that supports >1Gb drives.
  444          * No need to check the extended bios flags as some of the
  445          * extensions that cause us problems are not flagged in that byte.
  446          */
  447         if (PROBABLY_NEW_BOARD(aha->boardid) ||
  448                 (aha->boardid == 0x41
  449                 && aha->fw_major == 0x31 && 
  450                 aha->fw_minor >= 0x34)) {
  451                 error = aha_cmd(aha, AOP_RETURN_EXT_BIOS_INFO, NULL,
  452                         /*paramlen*/0, (u_char *)&extbios, sizeof(extbios),
  453                         DEFAULT_CMD_TIMEOUT);
  454                 error = aha_cmd(aha, AOP_MBOX_IF_ENABLE, (u_int8_t *)&extbios,
  455                         /*paramlen*/2, NULL, 0, DEFAULT_CMD_TIMEOUT);
  456         }
  457         if (aha->boardid < 0x41)
  458                 printf("%s: Warning: aha-1542A won't likely work.\n",
  459                         aha_name(aha));
  460 
  461         aha->max_sg = 17;               /* Need >= 17 to do 64k I/O */
  462         aha->diff_bus = 0;
  463         aha->extended_lun = 0;
  464         aha->extended_trans = 0;
  465         aha->max_ccbs = 16;
  466         /* Determine Sync/Wide/Disc settings */
  467         length_param = sizeof(setup_info);
  468         error = aha_cmd(aha, AOP_INQUIRE_SETUP_INFO, &length_param,
  469                        /*paramlen*/1, (u_int8_t*)&setup_info,
  470                        sizeof(setup_info), DEFAULT_CMD_TIMEOUT);
  471         if (error != 0) {
  472                 printf("%s: aha_fetch_adapter_info - Failed "
  473                        "Get Setup Info\n", aha_name(aha));
  474                 return (error);
  475         }
  476         if (setup_info.initiate_sync != 0) {
  477                 aha->sync_permitted = ALL_TARGETS;
  478         }
  479         aha->disc_permitted = ALL_TARGETS;
  480 
  481         /* We need as many mailboxes as we can have ccbs */
  482         aha->num_boxes = aha->max_ccbs;
  483 
  484         /* Determine our SCSI ID */
  485         
  486         error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
  487                        (u_int8_t*)&config_data, sizeof(config_data),
  488                        DEFAULT_CMD_TIMEOUT);
  489         if (error != 0) {
  490                 printf("%s: aha_fetch_adapter_info - Failed Get Config\n",
  491                        aha_name(aha));
  492                 return (error);
  493         }
  494         aha->scsi_id = config_data.scsi_id;
  495         return (0);
  496 }
  497 
  498 /*
  499  * Start the board, ready for normal operation
  500  */
  501 int
  502 aha_init(struct aha_softc* aha)
  503 {
  504         /* Announce the Adapter */
  505         printf("%s: AHA-%s FW Rev. %c.%c (ID=%x) ", aha_name(aha),
  506                aha->model, aha->fw_major, aha->fw_minor, aha->boardid);
  507 
  508         if (aha->diff_bus != 0)
  509                 printf("Diff ");
  510 
  511         printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", aha->scsi_id,
  512                aha->max_ccbs);
  513 
  514         /*
  515          * Create our DMA tags.  These tags define the kinds of device
  516          * accessable memory allocations and memory mappings we will 
  517          * need to perform during normal operation.
  518          *
  519          * Unless we need to further restrict the allocation, we rely
  520          * on the restrictions of the parent dmat, hence the common
  521          * use of MAXADDR and MAXSIZE.
  522          */
  523 
  524         /* DMA tag for mapping buffers into device visible space. */
  525         if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/1, /*boundary*/0,
  526                                /*lowaddr*/BUS_SPACE_MAXADDR,
  527                                /*highaddr*/BUS_SPACE_MAXADDR,
  528                                /*filter*/NULL, /*filterarg*/NULL,
  529                                /*maxsize*/MAXBSIZE, /*nsegments*/AHA_NSEG,
  530                                /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
  531                                /*flags*/BUS_DMA_ALLOCNOW,
  532                                &aha->buffer_dmat) != 0) {
  533                 goto error_exit;
  534         }
  535 
  536         aha->init_level++;
  537         /* DMA tag for our mailboxes */
  538         if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/1, /*boundary*/0,
  539                                /*lowaddr*/BUS_SPACE_MAXADDR,
  540                                /*highaddr*/BUS_SPACE_MAXADDR,
  541                                /*filter*/NULL, /*filterarg*/NULL,
  542                                aha->num_boxes * (sizeof(aha_mbox_in_t)
  543                                                + sizeof(aha_mbox_out_t)),
  544                                /*nsegments*/1,
  545                                /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
  546                                /*flags*/0, &aha->mailbox_dmat) != 0) {
  547                 goto error_exit;
  548         }
  549 
  550         aha->init_level++;
  551 
  552         /* Allocation for our mailboxes */
  553         if (bus_dmamem_alloc(aha->mailbox_dmat, (void **)&aha->out_boxes,
  554                              BUS_DMA_NOWAIT, &aha->mailbox_dmamap) != 0) {
  555                 goto error_exit;
  556         }
  557 
  558         aha->init_level++;
  559 
  560         /* And permanently map them */
  561         bus_dmamap_load(aha->mailbox_dmat, aha->mailbox_dmamap,
  562                         aha->out_boxes,
  563                         aha->num_boxes * (sizeof(aha_mbox_in_t)
  564                                        + sizeof(aha_mbox_out_t)),
  565                         ahamapmboxes, aha, /*flags*/0);
  566 
  567         aha->init_level++;
  568 
  569         aha->in_boxes = (aha_mbox_in_t *)&aha->out_boxes[aha->num_boxes];
  570 
  571         ahainitmboxes(aha);
  572 
  573         /* DMA tag for our ccb structures */
  574         if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/1, /*boundary*/0,
  575                                /*lowaddr*/BUS_SPACE_MAXADDR,
  576                                /*highaddr*/BUS_SPACE_MAXADDR,
  577                                /*filter*/NULL, /*filterarg*/NULL,
  578                                aha->max_ccbs * sizeof(struct aha_ccb),
  579                                /*nsegments*/1,
  580                                /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
  581                                /*flags*/0, &aha->ccb_dmat) != 0) {
  582                 goto error_exit;
  583         }
  584 
  585         aha->init_level++;
  586 
  587         /* Allocation for our ccbs */
  588         if (bus_dmamem_alloc(aha->ccb_dmat, (void **)&aha->aha_ccb_array,
  589                              BUS_DMA_NOWAIT, &aha->ccb_dmamap) != 0) {
  590                 goto error_exit;
  591         }
  592 
  593         aha->init_level++;
  594 
  595         /* And permanently map them */
  596         bus_dmamap_load(aha->ccb_dmat, aha->ccb_dmamap,
  597                         aha->aha_ccb_array,
  598                         aha->max_ccbs * sizeof(struct aha_ccb),
  599                         ahamapccbs, aha, /*flags*/0);
  600 
  601         aha->init_level++;
  602 
  603         /* DMA tag for our S/G structures.  We allocate in page sized chunks */
  604         if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/1, /*boundary*/0,
  605                                /*lowaddr*/BUS_SPACE_MAXADDR,
  606                                /*highaddr*/BUS_SPACE_MAXADDR,
  607                                /*filter*/NULL, /*filterarg*/NULL,
  608                                PAGE_SIZE, /*nsegments*/1,
  609                                /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT,
  610                                /*flags*/0, &aha->sg_dmat) != 0) {
  611                 goto error_exit;
  612         }
  613 
  614         aha->init_level++;
  615 
  616         /* Perform initial CCB allocation */
  617         bzero(aha->aha_ccb_array, aha->max_ccbs * sizeof(struct aha_ccb));
  618         ahaallocccbs(aha);
  619 
  620         if (aha->num_ccbs == 0) {
  621                 printf("%s: aha_init - Unable to allocate initial ccbs\n",
  622                        aha_name(aha));
  623                 goto error_exit;
  624         }
  625 
  626         /*
  627          * Note that we are going and return (to probe)
  628          */
  629         return 0;
  630 
  631 error_exit:
  632 
  633         return (ENXIO);
  634 }
  635 
  636 int
  637 aha_attach(struct aha_softc *aha)
  638 {
  639         int tagged_dev_openings;
  640         struct cam_devq *devq;
  641 
  642         /*
  643          * We don't do tagged queueing, since the aha cards don't
  644          * support it.
  645          */
  646         tagged_dev_openings = 0;
  647 
  648         /*
  649          * Create the device queue for our SIM.
  650          */
  651         devq = cam_simq_alloc(aha->max_ccbs - 1);
  652         if (devq == NULL)
  653                 return (ENOMEM);
  654 
  655         /*
  656          * Construct our SIM entry
  657          */
  658         aha->sim = cam_sim_alloc(ahaaction, ahapoll, "aha", aha, aha->unit,
  659                                 2, tagged_dev_openings, devq);
  660         if (aha->sim == NULL) {
  661                 cam_simq_free(devq);
  662                 return (ENOMEM);
  663         }
  664         
  665         if (xpt_bus_register(aha->sim, 0) != CAM_SUCCESS) {
  666                 cam_sim_free(aha->sim, /*free_devq*/TRUE);
  667                 return (ENXIO);
  668         }
  669         
  670         if (xpt_create_path(&aha->path, /*periph*/NULL,
  671                             cam_sim_path(aha->sim), CAM_TARGET_WILDCARD,
  672                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  673                 xpt_bus_deregister(cam_sim_path(aha->sim));
  674                 cam_sim_free(aha->sim, /*free_devq*/TRUE);
  675                 return (ENXIO);
  676         }
  677                 
  678         return (0);
  679 }
  680 
  681 char *
  682 aha_name(struct aha_softc *aha)
  683 {
  684         static char name[10];
  685 
  686         snprintf(name, sizeof(name), "aha%d", aha->unit);
  687         return (name);
  688 }
  689 
  690 int
  691 aha_check_probed_iop(u_int ioport)
  692 {
  693         u_int i;
  694 
  695         for (i=0; i < AHA_NUM_ISAPORTS; i++) {
  696                 if (aha_isa_ports[i].addr == ioport) {
  697                         if (aha_isa_ports[i].probed != 0)
  698                                 return (1);
  699                         else {
  700                                 return (0);
  701                         }
  702                 }
  703         }
  704         return (1);
  705 }
  706 
  707 void
  708 aha_mark_probed_bio(isa_compat_io_t port)
  709 {
  710         if (port < BIO_DISABLED)
  711                 aha_mark_probed_iop(aha_board_ports[port]);
  712 }
  713 
  714 void
  715 aha_mark_probed_iop(u_int ioport)
  716 {
  717         u_int i;
  718 
  719         for (i = 0; i < AHA_NUM_ISAPORTS; i++) {
  720                 if (ioport == aha_isa_ports[i].addr) {
  721                         aha_isa_ports[i].probed = 1;
  722                         break;
  723                 }
  724         }
  725 }
  726 
  727 void
  728 aha_find_probe_range(int ioport, int *port_index, int *max_port_index)
  729 {
  730         if (ioport > 0) {
  731                 int i;
  732 
  733                 for (i = 0;i < AHA_NUM_ISAPORTS; i++)
  734                         if (ioport <= aha_isa_ports[i].addr)
  735                                 break;
  736                 if ((i >= AHA_NUM_ISAPORTS)
  737                  || (ioport != aha_isa_ports[i].addr)) {
  738                         printf("\n"
  739 "aha_isa_probe: Invalid baseport of 0x%x specified.\n"
  740 "aha_isa_probe: Nearest valid baseport is 0x%x.\n"
  741 "aha_isa_probe: Failing probe.\n",
  742                                ioport,
  743                                (i < AHA_NUM_ISAPORTS)
  744                                     ? aha_isa_ports[i].addr
  745                                     : aha_isa_ports[AHA_NUM_ISAPORTS - 1].addr);
  746                         *port_index = *max_port_index = -1;
  747                         return;
  748                 }
  749                 *port_index = *max_port_index = aha_isa_ports[i].bio;
  750         } else {
  751                 *port_index = 0;
  752                 *max_port_index = AHA_NUM_ISAPORTS - 1;
  753         }
  754 }
  755 
  756 int
  757 aha_iop_from_bio(isa_compat_io_t bio_index)
  758 {
  759         if (bio_index >= 0 && bio_index < AHA_NUM_ISAPORTS)
  760                 return (aha_board_ports[bio_index]);
  761         return (-1);
  762 }
  763 
  764 static void
  765 ahaallocccbs(struct aha_softc *aha)
  766 {
  767         struct aha_ccb *next_ccb;
  768         struct sg_map_node *sg_map;
  769         bus_addr_t physaddr;
  770         aha_sg_t *segs;
  771         int newcount;
  772         int i;
  773 
  774         next_ccb = &aha->aha_ccb_array[aha->num_ccbs];
  775 
  776         sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
  777 
  778         if (sg_map == NULL)
  779                 return;
  780 
  781         /* Allocate S/G space for the next batch of CCBS */
  782         if (bus_dmamem_alloc(aha->sg_dmat, (void **)&sg_map->sg_vaddr,
  783                              BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {
  784                 free(sg_map, M_DEVBUF);
  785                 return;
  786         }
  787 
  788         SLIST_INSERT_HEAD(&aha->sg_maps, sg_map, links);
  789 
  790         bus_dmamap_load(aha->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr,
  791                         PAGE_SIZE, ahamapsgs, aha, /*flags*/0);
  792         
  793         segs = sg_map->sg_vaddr;
  794         physaddr = sg_map->sg_physaddr;
  795 
  796         newcount = (PAGE_SIZE / (AHA_NSEG * sizeof(aha_sg_t)));
  797         for (i = 0; aha->num_ccbs < aha->max_ccbs && i < newcount; i++) {
  798                 int error;
  799 
  800                 next_ccb->sg_list = segs;
  801                 next_ccb->sg_list_phys = physaddr;
  802                 next_ccb->flags = ACCB_FREE;
  803                 error = bus_dmamap_create(aha->buffer_dmat, /*flags*/0,
  804                                           &next_ccb->dmamap);
  805                 if (error != 0)
  806                         break;
  807                 SLIST_INSERT_HEAD(&aha->free_aha_ccbs, next_ccb, links);
  808                 segs += AHA_NSEG;
  809                 physaddr += (AHA_NSEG * sizeof(aha_sg_t));
  810                 next_ccb++;
  811                 aha->num_ccbs++;
  812         }
  813 
  814         /* Reserve a CCB for error recovery */
  815         if (aha->recovery_accb == NULL) {
  816                 aha->recovery_accb = SLIST_FIRST(&aha->free_aha_ccbs);
  817                 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
  818         }
  819 }
  820 
  821 static __inline void
  822 ahafreeccb(struct aha_softc *aha, struct aha_ccb *accb)
  823 {
  824         int s;
  825 
  826         s = splcam();
  827         if ((accb->flags & ACCB_ACTIVE) != 0)
  828                 LIST_REMOVE(&accb->ccb->ccb_h, sim_links.le);
  829         if (aha->resource_shortage != 0
  830          && (accb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
  831                 accb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
  832                 aha->resource_shortage = FALSE;
  833         }
  834         accb->flags = ACCB_FREE;
  835         SLIST_INSERT_HEAD(&aha->free_aha_ccbs, accb, links);
  836         aha->active_ccbs--;
  837         splx(s);
  838 }
  839 
  840 static struct aha_ccb*
  841 ahagetccb(struct aha_softc *aha)
  842 {
  843         struct  aha_ccb* accb;
  844         int     s;
  845 
  846         s = splcam();
  847         if ((accb = SLIST_FIRST(&aha->free_aha_ccbs)) != NULL) {
  848                 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
  849                 aha->active_ccbs++;
  850         } else if (aha->num_ccbs < aha->max_ccbs) {
  851                 ahaallocccbs(aha);
  852                 accb = SLIST_FIRST(&aha->free_aha_ccbs);
  853                 if (accb == NULL)
  854                         printf("%s: Can't malloc ACCB\n", aha_name(aha));
  855                 else {
  856                         SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links);
  857                         aha->active_ccbs++;
  858                 }
  859         }
  860         splx(s);
  861 
  862         return (accb);
  863 }
  864 
  865 static void
  866 ahaaction(struct cam_sim *sim, union ccb *ccb)
  867 {
  868         struct  aha_softc *aha;
  869 
  870         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahaaction\n"));
  871         
  872         aha = (struct aha_softc *)cam_sim_softc(sim);
  873         
  874         switch (ccb->ccb_h.func_code) {
  875         /* Common cases first */
  876         case XPT_SCSI_IO:       /* Execute the requested I/O operation */
  877         case XPT_RESET_DEV:     /* Bus Device Reset the specified SCSI device */
  878         {
  879                 struct  aha_ccb *accb;
  880                 struct  aha_hccb *hccb;
  881 
  882                 /*
  883                  * get a accb to use.
  884                  */
  885                 if ((accb = ahagetccb(aha)) == NULL) {
  886                         int s;
  887 
  888                         s = splcam();
  889                         aha->resource_shortage = TRUE;
  890                         splx(s);
  891                         xpt_freeze_simq(aha->sim, /*count*/1);
  892                         ccb->ccb_h.status = CAM_REQUEUE_REQ;
  893                         xpt_done(ccb);
  894                         return;
  895                 }
  896                 
  897                 hccb = &accb->hccb;
  898 
  899                 /*
  900                  * So we can find the ACCB when an abort is requested
  901                  */
  902                 accb->ccb = ccb;
  903                 ccb->ccb_h.ccb_accb_ptr = accb;
  904                 ccb->ccb_h.ccb_aha_ptr = aha;
  905 
  906                 /*
  907                  * Put all the arguments for the xfer in the accb
  908                  */
  909                 hccb->target = ccb->ccb_h.target_id;
  910                 hccb->lun = ccb->ccb_h.target_lun;
  911                 hccb->ahastat = 0;
  912                 hccb->sdstat = 0;
  913 
  914                 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
  915                         struct ccb_scsiio *csio;
  916                         struct ccb_hdr *ccbh;
  917 
  918                         csio = &ccb->csio;
  919                         ccbh = &csio->ccb_h;
  920                         hccb->opcode = aha->ccb_ccb_opcode;
  921                         hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0;
  922                         hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0;
  923                         hccb->cmd_len = csio->cdb_len;
  924                         if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) {
  925                                 ccb->ccb_h.status = CAM_REQ_INVALID;
  926                                 ahafreeccb(aha, accb);
  927                                 xpt_done(ccb);
  928                                 return;
  929                         }
  930                         hccb->sense_len = csio->sense_len;
  931                         if ((ccbh->flags & CAM_CDB_POINTER) != 0) {
  932                                 if ((ccbh->flags & CAM_CDB_PHYS) == 0) {
  933                                         bcopy(csio->cdb_io.cdb_ptr,
  934                                               hccb->scsi_cdb, hccb->cmd_len);
  935                                 } else {
  936                                         /* I guess I could map it in... */
  937                                         ccbh->status = CAM_REQ_INVALID;
  938                                         ahafreeccb(aha, accb);
  939                                         xpt_done(ccb);
  940                                         return;
  941                                 }
  942                         } else {
  943                                 bcopy(csio->cdb_io.cdb_bytes,
  944                                       hccb->scsi_cdb, hccb->cmd_len);
  945                         }
  946                         /*
  947                          * If we have any data to send with this command,
  948                          * map it into bus space.
  949                          */
  950                         /* Only use S/G if there is a transfer */
  951                         if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  952                                 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {
  953                                         /*
  954                                          * We've been given a pointer
  955                                          * to a single buffer.
  956                                          */
  957                                         if ((ccbh->flags & CAM_DATA_PHYS)==0) {
  958                                                 int s;
  959                                                 int error;
  960 
  961                                                 s = splsoftvm();
  962                                                 error = bus_dmamap_load(
  963                                                     aha->buffer_dmat,
  964                                                     accb->dmamap,
  965                                                     csio->data_ptr,
  966                                                     csio->dxfer_len,
  967                                                     ahaexecuteccb,
  968                                                     accb,
  969                                                     /*flags*/0);
  970                                                 if (error == EINPROGRESS) {
  971                                                         /*
  972                                                          * So as to maintain
  973                                                          * ordering, freeze the
  974                                                          * controller queue
  975                                                          * until our mapping is
  976                                                          * returned.
  977                                                          */
  978                                                         xpt_freeze_simq(aha->sim,
  979                                                                         1);
  980                                                         csio->ccb_h.status |=
  981                                                             CAM_RELEASE_SIMQ;
  982                                                 }
  983                                                 splx(s);
  984                                         } else {
  985                                                 struct bus_dma_segment seg; 
  986 
  987                                                 /* Pointer to physical buffer */
  988                                                 seg.ds_addr =
  989                                                     (bus_addr_t)csio->data_ptr;
  990                                                 seg.ds_len = csio->dxfer_len;
  991                                                 ahaexecuteccb(accb, &seg, 1, 0);
  992                                         }
  993                                 } else {
  994                                         struct bus_dma_segment *segs;
  995 
  996                                         if ((ccbh->flags & CAM_DATA_PHYS) != 0)
  997                                                 panic("ahaaction - Physical "
  998                                                       "segment pointers "
  999                                                       "unsupported");
 1000 
 1001                                         if ((ccbh->flags&CAM_SG_LIST_PHYS)==0)
 1002                                                 panic("ahaaction - Virtual "
 1003                                                       "segment addresses "
 1004                                                       "unsupported");
 1005 
 1006                                         /* Just use the segments provided */
 1007                                         segs = (struct bus_dma_segment *)
 1008                                             csio->data_ptr;
 1009                                         ahaexecuteccb(accb, segs,
 1010                                                      csio->sglist_cnt, 0);
 1011                                 }
 1012                         } else {
 1013                                 ahaexecuteccb(accb, NULL, 0, 0);
 1014                         }
 1015                 } else {
 1016                         hccb->opcode = INITIATOR_BUS_DEV_RESET;
 1017                         /* No data transfer */
 1018                         hccb->datain = TRUE;
 1019                         hccb->dataout = TRUE;
 1020                         hccb->cmd_len = 0;
 1021                         hccb->sense_len = 0;
 1022                         ahaexecuteccb(accb, NULL, 0, 0);
 1023                 }
 1024                 break;
 1025         }
 1026         case XPT_EN_LUN:                /* Enable LUN as a target */
 1027         case XPT_TARGET_IO:             /* Execute target I/O request */
 1028         case XPT_ACCEPT_TARGET_IO:      /* Accept Host Target Mode CDB */
 1029         case XPT_CONT_TARGET_IO:        /* Continue Host Target I/O Connection*/
 1030         case XPT_ABORT:                 /* Abort the specified CCB */
 1031                 /* XXX Implement */
 1032                 ccb->ccb_h.status = CAM_REQ_INVALID;
 1033                 xpt_done(ccb);
 1034                 break;
 1035         case XPT_SET_TRAN_SETTINGS:
 1036         {
 1037                 /* XXX Implement */
 1038                 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
 1039                 xpt_done(ccb);
 1040                 break;
 1041         }
 1042         case XPT_GET_TRAN_SETTINGS:
 1043         /* Get default/user set transfer settings for the target */
 1044         {
 1045                 struct  ccb_trans_settings *cts;
 1046                 u_int   target_mask;
 1047 
 1048                 cts = &ccb->cts;
 1049                 target_mask = 0x01 << ccb->ccb_h.target_id;
 1050                 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
 1051                         cts->flags = 0;
 1052                         if ((aha->disc_permitted & target_mask) != 0)
 1053                                 cts->flags |= CCB_TRANS_DISC_ENB;
 1054                         cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
 1055                         if ((aha->sync_permitted & target_mask) != 0) {
 1056                                 if (aha->boardid >= BOARD_1542CF)
 1057                                         cts->sync_period = 25;
 1058                                 else
 1059                                         cts->sync_period = 50;
 1060                         } else
 1061                                 cts->sync_period = 0;
 1062 
 1063                         if (cts->sync_period != 0)
 1064                                 cts->sync_offset = 15;
 1065 
 1066                         cts->valid = CCB_TRANS_SYNC_RATE_VALID
 1067                                    | CCB_TRANS_SYNC_OFFSET_VALID
 1068                                    | CCB_TRANS_BUS_WIDTH_VALID
 1069                                    | CCB_TRANS_DISC_VALID
 1070                                    | CCB_TRANS_TQ_VALID;
 1071                 } else {
 1072                         ahafetchtransinfo(aha, cts);
 1073                 }
 1074 
 1075                 ccb->ccb_h.status = CAM_REQ_CMP;
 1076                 xpt_done(ccb);
 1077                 break;
 1078         }
 1079         case XPT_CALC_GEOMETRY:
 1080         {
 1081                 struct    ccb_calc_geometry *ccg;
 1082                 u_int32_t size_mb;
 1083                 u_int32_t secs_per_cylinder;
 1084 
 1085                 ccg = &ccb->ccg;
 1086                 size_mb = ccg->volume_size
 1087                         / ((1024L * 1024L) / ccg->block_size);
 1088                 
 1089                 if (size_mb >= 1024 && (aha->extended_trans != 0)) {
 1090                         if (size_mb >= 2048) {
 1091                                 ccg->heads = 255;
 1092                                 ccg->secs_per_track = 63;
 1093                         } else {
 1094                                 ccg->heads = 128;
 1095                                 ccg->secs_per_track = 32;
 1096                         }
 1097                 } else {
 1098                         ccg->heads = 64;
 1099                         ccg->secs_per_track = 32;
 1100                 }
 1101                 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
 1102                 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
 1103                 ccb->ccb_h.status = CAM_REQ_CMP;
 1104                 xpt_done(ccb);
 1105                 break;
 1106         }
 1107         case XPT_RESET_BUS:             /* Reset the specified SCSI bus */
 1108         {
 1109                 ahareset(aha, /*hardreset*/TRUE);
 1110                 ccb->ccb_h.status = CAM_REQ_CMP;
 1111                 xpt_done(ccb);
 1112                 break;
 1113         }
 1114         case XPT_TERM_IO:               /* Terminate the I/O process */
 1115                 /* XXX Implement */
 1116                 ccb->ccb_h.status = CAM_REQ_INVALID;
 1117                 xpt_done(ccb);
 1118                 break;
 1119         case XPT_PATH_INQ:              /* Path routing inquiry */
 1120         {
 1121                 struct ccb_pathinq *cpi = &ccb->cpi;
 1122                 
 1123                 cpi->version_num = 1; /* XXX??? */
 1124                 cpi->hba_inquiry = PI_SDTR_ABLE;
 1125                 cpi->target_sprt = 0;
 1126                 cpi->hba_misc = 0;
 1127                 cpi->hba_eng_cnt = 0;
 1128                 cpi->max_target = 7;
 1129                 cpi->max_lun = 7;
 1130                 cpi->initiator_id = aha->scsi_id;
 1131                 cpi->bus_id = cam_sim_bus(sim);
 1132                 cpi->base_transfer_speed = 3300;
 1133                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
 1134                 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
 1135                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
 1136                 cpi->unit_number = cam_sim_unit(sim);
 1137                 cpi->ccb_h.status = CAM_REQ_CMP;
 1138                 xpt_done(ccb);
 1139                 break;
 1140         }
 1141         default:
 1142                 ccb->ccb_h.status = CAM_REQ_INVALID;
 1143                 xpt_done(ccb);
 1144                 break;
 1145         }
 1146 }
 1147 
 1148 static void
 1149 ahaexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 1150 {
 1151         struct   aha_ccb *accb;
 1152         union    ccb *ccb;
 1153         struct   aha_softc *aha;
 1154         int      s;
 1155         u_int32_t paddr;
 1156 
 1157         accb = (struct aha_ccb *)arg;
 1158         ccb = accb->ccb;
 1159         aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr;
 1160 
 1161         if (error != 0) {
 1162                 if (error != EFBIG)
 1163                         printf("%s: Unexepected error 0x%x returned from "
 1164                                "bus_dmamap_load\n", aha_name(aha), error);
 1165                 if (ccb->ccb_h.status == CAM_REQ_INPROG) {
 1166                         xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
 1167                         ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
 1168                 }
 1169                 ahafreeccb(aha, accb);
 1170                 xpt_done(ccb);
 1171                 return;
 1172         }
 1173                 
 1174         if (nseg != 0) {
 1175                 aha_sg_t *sg;
 1176                 bus_dma_segment_t *end_seg;
 1177                 bus_dmasync_op_t op;
 1178 
 1179                 end_seg = dm_segs + nseg;
 1180 
 1181                 /* Copy the segments into our SG list */
 1182                 sg = accb->sg_list;
 1183                 while (dm_segs < end_seg) {
 1184                         ahautoa24(dm_segs->ds_len, sg->len);
 1185                         ahautoa24(dm_segs->ds_addr, sg->addr);
 1186                         sg++;
 1187                         dm_segs++;
 1188                 }
 1189 
 1190                 if (nseg > 1) {
 1191                         accb->hccb.opcode = aha->ccb_sg_opcode;
 1192                         ahautoa24((sizeof(aha_sg_t) * nseg),
 1193                                   accb->hccb.data_len);
 1194                         ahautoa24(accb->sg_list_phys, accb->hccb.data_addr);
 1195                 } else {
 1196                         bcopy(accb->sg_list->len, accb->hccb.data_len, 3);
 1197                         bcopy(accb->sg_list->addr, accb->hccb.data_addr, 3);
 1198                 }
 1199 
 1200                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
 1201                         op = BUS_DMASYNC_PREREAD;
 1202                 else
 1203                         op = BUS_DMASYNC_PREWRITE;
 1204 
 1205                 bus_dmamap_sync(aha->buffer_dmat, accb->dmamap, op);
 1206 
 1207         } else {
 1208                 accb->hccb.opcode = INITIATOR_CCB;
 1209                 ahautoa24(0, accb->hccb.data_len);
 1210                 ahautoa24(0, accb->hccb.data_addr);
 1211         }
 1212 
 1213         s = splcam();
 1214 
 1215         /*
 1216          * Last time we need to check if this CCB needs to
 1217          * be aborted.
 1218          */
 1219         if (ccb->ccb_h.status != CAM_REQ_INPROG) {
 1220                 if (nseg != 0)
 1221                         bus_dmamap_unload(aha->buffer_dmat, accb->dmamap);
 1222                 ahafreeccb(aha, accb);
 1223                 xpt_done(ccb);
 1224                 splx(s);
 1225                 return;
 1226         }
 1227                 
 1228         accb->flags = ACCB_ACTIVE;
 1229         ccb->ccb_h.status |= CAM_SIM_QUEUED;
 1230         LIST_INSERT_HEAD(&aha->pending_ccbs, &ccb->ccb_h, sim_links.le);
 1231 
 1232         ccb->ccb_h.timeout_ch =
 1233             timeout(ahatimeout, (caddr_t)accb,
 1234                     (ccb->ccb_h.timeout * hz) / 1000);
 1235 
 1236         /* Tell the adapter about this command */
 1237         if (aha->cur_outbox->action_code != AMBO_FREE) {
 1238                 /*
 1239                  * We should never encounter a busy mailbox.
 1240                  * If we do, warn the user, and treat it as
 1241                  * a resource shortage.  If the controller is
 1242                  * hung, one of the pending transactions will
 1243                  * timeout causing us to start recovery operations.
 1244                  */
 1245                 printf("%s: Encountered busy mailbox with %d out of %d "
 1246                        "commands active!!!", aha_name(aha), aha->active_ccbs,
 1247                        aha->max_ccbs);
 1248                 untimeout(ahatimeout, accb, ccb->ccb_h.timeout_ch);
 1249                 if (nseg != 0)
 1250                         bus_dmamap_unload(aha->buffer_dmat, accb->dmamap);
 1251                 ahafreeccb(aha, accb);
 1252                 aha->resource_shortage = TRUE;
 1253                 xpt_freeze_simq(aha->sim, /*count*/1);
 1254                 ccb->ccb_h.status = CAM_REQUEUE_REQ;
 1255                 xpt_done(ccb);
 1256                 return;
 1257         }
 1258         paddr = ahaccbvtop(aha, accb);
 1259         ahautoa24(paddr, aha->cur_outbox->ccb_addr);
 1260         aha->cur_outbox->action_code = AMBO_START;      
 1261         aha_outb(aha, COMMAND_REG, AOP_START_MBOX);
 1262 
 1263         ahanextoutbox(aha);
 1264         splx(s);
 1265 }
 1266 
 1267 void
 1268 aha_intr(void *arg)
 1269 {
 1270         struct  aha_softc *aha;
 1271         u_int   intstat;
 1272 
 1273         aha = (struct aha_softc *)arg;
 1274         while (((intstat = aha_inb(aha, INTSTAT_REG)) & INTR_PENDING) != 0) {
 1275                 if ((intstat & CMD_COMPLETE) != 0) {
 1276                         aha->latched_status = aha_inb(aha, STATUS_REG);
 1277                         aha->command_cmp = TRUE;
 1278                 }
 1279 
 1280                 aha_outb(aha, CONTROL_REG, RESET_INTR);
 1281 
 1282                 if ((intstat & IMB_LOADED) != 0) {
 1283                         while (aha->cur_inbox->comp_code != AMBI_FREE) {
 1284                                 u_int32_t       paddr;
 1285                                 paddr = aha_a24tou(aha->cur_inbox->ccb_addr);
 1286                                 ahadone(aha,
 1287                                        ahaccbptov(aha, paddr),
 1288                                        aha->cur_inbox->comp_code);
 1289                                 aha->cur_inbox->comp_code = AMBI_FREE;
 1290                                 ahanextinbox(aha);
 1291                         }
 1292                 }
 1293 
 1294                 if ((intstat & SCSI_BUS_RESET) != 0) {
 1295                         ahareset(aha, /*hardreset*/FALSE);
 1296                 }
 1297         }
 1298 }
 1299 
 1300 static void
 1301 ahadone(struct aha_softc *aha, struct aha_ccb *accb, aha_mbi_comp_code_t comp_code)
 1302 {
 1303         union  ccb        *ccb;
 1304         struct ccb_scsiio *csio;
 1305 
 1306         ccb = accb->ccb;
 1307         csio = &accb->ccb->csio;
 1308 
 1309         if ((accb->flags & ACCB_ACTIVE) == 0) {
 1310                 printf("%s: ahadone - Attempt to free non-active ACCB %p\n",
 1311                        aha_name(aha), (void *)accb);
 1312                 return;
 1313         }
 1314 
 1315         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
 1316                 bus_dmasync_op_t op;
 1317 
 1318                 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
 1319                         op = BUS_DMASYNC_POSTREAD;
 1320                 else
 1321                         op = BUS_DMASYNC_POSTWRITE;
 1322                 bus_dmamap_sync(aha->buffer_dmat, accb->dmamap, op);
 1323                 bus_dmamap_unload(aha->buffer_dmat, accb->dmamap);
 1324         }
 1325 
 1326         if (accb == aha->recovery_accb) {
 1327                 /*
 1328                  * The recovery ACCB does not have a CCB associated
 1329                  * with it, so short circuit the normal error handling.
 1330                  * We now traverse our list of pending CCBs and process
 1331                  * any that were terminated by the recovery CCBs action.
 1332                  * We also reinstate timeouts for all remaining, pending,
 1333                  * CCBs.
 1334                  */
 1335                 struct cam_path *path;
 1336                 struct ccb_hdr *ccb_h;
 1337                 cam_status error;
 1338 
 1339                 /* Notify all clients that a BDR occured */
 1340                 error = xpt_create_path(&path, /*periph*/NULL,
 1341                                         cam_sim_path(aha->sim),
 1342                                         accb->hccb.target,
 1343                                         CAM_LUN_WILDCARD);
 1344                 
 1345                 if (error == CAM_REQ_CMP)
 1346                         xpt_async(AC_SENT_BDR, path, NULL);
 1347 
 1348                 ccb_h = LIST_FIRST(&aha->pending_ccbs);
 1349                 while (ccb_h != NULL) {
 1350                         struct aha_ccb *pending_accb;
 1351 
 1352                         pending_accb = (struct aha_ccb *)ccb_h->ccb_accb_ptr;
 1353                         if (pending_accb->hccb.target == accb->hccb.target) {
 1354                                 pending_accb->hccb.ahastat = AHASTAT_HA_BDR;
 1355                                 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
 1356                                 ahadone(aha, pending_accb, AMBI_ERROR);
 1357                         } else {
 1358                                 ccb_h->timeout_ch =
 1359                                     timeout(ahatimeout, (caddr_t)pending_accb,
 1360                                             (ccb_h->timeout * hz) / 1000);
 1361                                 ccb_h = LIST_NEXT(ccb_h, sim_links.le);
 1362                         }
 1363                 }
 1364                 printf("%s: No longer in timeout\n", aha_name(aha));
 1365                 return;
 1366         }
 1367 
 1368         untimeout(ahatimeout, accb, ccb->ccb_h.timeout_ch);
 1369 
 1370         switch (comp_code) {
 1371         case AMBI_FREE:
 1372                 printf("%s: ahadone - CCB completed with free status!\n",
 1373                        aha_name(aha));
 1374                 break;
 1375         case AMBI_NOT_FOUND:
 1376                 printf("%s: ahadone - CCB Abort failed to find CCB\n",
 1377                        aha_name(aha));
 1378                 break;
 1379         case AMBI_ABORT:
 1380         case AMBI_ERROR:
 1381                 /* An error occured */
 1382                 if (accb->hccb.opcode < INITIATOR_CCB_WRESID)
 1383                         csio->resid = 0;
 1384                 else
 1385                         csio->resid = aha_a24tou(accb->hccb.data_len);
 1386                 switch(accb->hccb.ahastat) {
 1387                 case AHASTAT_DATARUN_ERROR:
 1388                 {
 1389                         if (csio->resid <= 0) {
 1390                                 csio->ccb_h.status = CAM_DATA_RUN_ERR;
 1391                                 break;
 1392                         }
 1393                         /* FALLTHROUGH */
 1394                 }
 1395                 case AHASTAT_NOERROR:
 1396                         csio->scsi_status = accb->hccb.sdstat;
 1397                         csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
 1398                         switch(csio->scsi_status) {
 1399                         case SCSI_STATUS_CHECK_COND:
 1400                         case SCSI_STATUS_CMD_TERMINATED:
 1401                                 csio->ccb_h.status |= CAM_AUTOSNS_VALID;
 1402                                 /*
 1403                                  * The aha writes the sense data at different
 1404                                  * offsets based on the scsi cmd len
 1405                                  */
 1406                                 bcopy((caddr_t) &accb->hccb.scsi_cdb +
 1407                                         accb->hccb.cmd_len, 
 1408                                         (caddr_t) &csio->sense_data,
 1409                                         accb->hccb.sense_len);
 1410                                 break;
 1411                         default:
 1412                                 break;
 1413                         case SCSI_STATUS_OK:
 1414                                 csio->ccb_h.status = CAM_REQ_CMP;
 1415                                 break;
 1416                         }
 1417                         break;
 1418                 case AHASTAT_SELTIMEOUT:
 1419                         csio->ccb_h.status = CAM_SEL_TIMEOUT;
 1420                         break;
 1421                 case AHASTAT_UNEXPECTED_BUSFREE:
 1422                         csio->ccb_h.status = CAM_UNEXP_BUSFREE;
 1423                         break;
 1424                 case AHASTAT_INVALID_PHASE:
 1425                         csio->ccb_h.status = CAM_SEQUENCE_FAIL;
 1426                         break;
 1427                 case AHASTAT_INVALID_ACTION_CODE:
 1428                         panic("%s: Inavlid Action code", aha_name(aha));
 1429                         break;
 1430                 case AHASTAT_INVALID_OPCODE:
 1431                         if (accb->hccb.opcode < INITIATOR_CCB_WRESID)
 1432                                 panic("%s: Invalid CCB Opcode %x hccb = %p",
 1433                                         aha_name(aha), accb->hccb.opcode,
 1434                                         &accb->hccb);
 1435                         printf("%s: AHA-1540A detected, compensating\n",
 1436                                 aha_name(aha));
 1437                         aha->ccb_sg_opcode = INITIATOR_SG_CCB;
 1438                         aha->ccb_ccb_opcode = INITIATOR_CCB;
 1439                         xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
 1440                         csio->ccb_h.status = CAM_REQUEUE_REQ;
 1441                         break;
 1442                 case AHASTAT_LINKED_CCB_LUN_MISMATCH:
 1443                         /* We don't even support linked commands... */
 1444                         panic("%s: Linked CCB Lun Mismatch", aha_name(aha));
 1445                         break;
 1446                 case AHASTAT_INVALID_CCB_OR_SG_PARAM:
 1447                         panic("%s: Invalid CCB or SG list", aha_name(aha));
 1448                         break;
 1449                 case AHASTAT_HA_SCSI_BUS_RESET:
 1450                         if ((csio->ccb_h.status & CAM_STATUS_MASK)
 1451                             != CAM_CMD_TIMEOUT)
 1452                                 csio->ccb_h.status = CAM_SCSI_BUS_RESET;
 1453                         break;
 1454                 case AHASTAT_HA_BDR:
 1455                         if ((accb->flags & ACCB_DEVICE_RESET) == 0)
 1456                                 csio->ccb_h.status = CAM_BDR_SENT;
 1457                         else
 1458                                 csio->ccb_h.status = CAM_CMD_TIMEOUT;
 1459                         break;
 1460                 }
 1461                 if (csio->ccb_h.status != CAM_REQ_CMP) {
 1462                         xpt_freeze_devq(csio->ccb_h.path, /*count*/1);
 1463                         csio->ccb_h.status |= CAM_DEV_QFRZN;
 1464                 }
 1465                 if ((accb->flags & ACCB_RELEASE_SIMQ) != 0)
 1466                         ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
 1467                 ahafreeccb(aha, accb);
 1468                 xpt_done(ccb);
 1469                 break;
 1470         case AMBI_OK:
 1471                 /* All completed without incident */
 1472                 /* XXX DO WE NEED TO COPY SENSE BYTES HERE???? XXX */
 1473                 /* I don't think so since it works???? */
 1474                 ccb->ccb_h.status |= CAM_REQ_CMP;
 1475                 if ((accb->flags & ACCB_RELEASE_SIMQ) != 0)
 1476                         ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
 1477                 ahafreeccb(aha, accb);
 1478                 xpt_done(ccb);
 1479                 break;
 1480         }
 1481 }
 1482 
 1483 static int
 1484 ahareset(struct aha_softc* aha, int hard_reset)
 1485 {
 1486         struct   ccb_hdr *ccb_h;
 1487         u_int    status;
 1488         u_int    timeout;
 1489         u_int8_t reset_type;
 1490 
 1491         if (hard_reset != 0)
 1492                 reset_type = HARD_RESET;
 1493         else
 1494                 reset_type = SOFT_RESET;
 1495         aha_outb(aha, CONTROL_REG, reset_type);
 1496 
 1497         /* Wait 5sec. for Diagnostic start */
 1498         timeout = 5 * 10000;
 1499         while (--timeout) {
 1500                 status = aha_inb(aha, STATUS_REG);
 1501                 if ((status & DIAG_ACTIVE) != 0)
 1502                         break;
 1503                 DELAY(100);
 1504         }
 1505         if (timeout == 0) {
 1506                 PRVERB(("%s: ahareset - Diagnostic Active failed to "
 1507                         "assert. status = 0x%x\n", aha_name(aha),
 1508                         status));
 1509                 return (ETIMEDOUT);
 1510         }
 1511 
 1512         /* Wait 10sec. for Diagnostic end */
 1513         timeout = 10 * 10000;
 1514         while (--timeout) {
 1515                 status = aha_inb(aha, STATUS_REG);
 1516                 if ((status & DIAG_ACTIVE) == 0)
 1517                         break;
 1518                 DELAY(100);
 1519         }
 1520         if (timeout == 0) {
 1521                 panic("%s: ahareset - Diagnostic Active failed to drop. "
 1522                        "status = 0x%x\n", aha_name(aha), status);
 1523                 return (ETIMEDOUT);
 1524         }
 1525 
 1526         /* Wait for the host adapter to become ready or report a failure */
 1527         timeout = 10000;
 1528         while (--timeout) {
 1529                 status = aha_inb(aha, STATUS_REG);
 1530                 if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0)
 1531                         break;
 1532                 DELAY(100);
 1533         }
 1534         if (timeout == 0) {
 1535                 printf("%s: ahareset - Host adapter failed to come ready. "
 1536                        "status = 0x%x\n", aha_name(aha), status);
 1537                 return (ETIMEDOUT);
 1538         }
 1539 
 1540         /* If the diagnostics failed, tell the user */
 1541         if ((status & DIAG_FAIL) != 0
 1542          || (status & HA_READY) == 0) {
 1543                 printf("%s: ahareset - Adapter failed diagnostics\n",
 1544                        aha_name(aha));
 1545 
 1546                 if ((status & DATAIN_REG_READY) != 0)
 1547                         printf("%s: ahareset - Host Adapter Error "
 1548                                "code = 0x%x\n", aha_name(aha),
 1549                                aha_inb(aha, DATAIN_REG));
 1550                 return (ENXIO);
 1551         }
 1552 
 1553         /* If we've allocated mailboxes, initialize them */
 1554         if (aha->init_level > 4)
 1555                 ahainitmboxes(aha);
 1556 
 1557         /* If we've attached to the XPT, tell it about the event */
 1558         if (aha->path != NULL)
 1559                 xpt_async(AC_BUS_RESET, aha->path, NULL);
 1560 
 1561         /*
 1562          * Perform completion processing for all outstanding CCBs.
 1563          */
 1564         while ((ccb_h = LIST_FIRST(&aha->pending_ccbs)) != NULL) {
 1565                 struct aha_ccb *pending_accb;
 1566 
 1567                 pending_accb = (struct aha_ccb *)ccb_h->ccb_accb_ptr;
 1568                 pending_accb->hccb.ahastat = AHASTAT_HA_SCSI_BUS_RESET;
 1569                 ahadone(aha, pending_accb, AMBI_ERROR);
 1570         }
 1571 
 1572         return (0);
 1573 }
 1574 
 1575 /*
 1576  * Send a command to the adapter.
 1577  */
 1578 int
 1579 aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params, 
 1580         u_int param_len, u_int8_t *reply_data, u_int reply_len, 
 1581         u_int cmd_timeout)
 1582 {
 1583         u_int   timeout;
 1584         u_int   status;
 1585         u_int   saved_status;
 1586         u_int   intstat;
 1587         u_int   reply_buf_size;
 1588         int     s;
 1589         int     cmd_complete;
 1590         int     error;
 1591 
 1592         /* No data returned to start */
 1593         reply_buf_size = reply_len;
 1594         reply_len = 0;
 1595         intstat = 0;
 1596         cmd_complete = 0;
 1597         saved_status = 0;
 1598         error = 0;
 1599 
 1600         /*
 1601          * All commands except for the "start mailbox" and the "enable
 1602          * outgoing mailbox read interrupt" commands cannot be issued
 1603          * while there are pending transactions.  Freeze our SIMQ
 1604          * and wait for all completions to occur if necessary.
 1605          */
 1606         timeout = 100000;
 1607         s = splcam();
 1608         while (LIST_FIRST(&aha->pending_ccbs) != NULL && --timeout) {
 1609                 /* Fire the interrupt handler in case interrupts are blocked */
 1610                 aha_intr(aha);
 1611                 splx(s);
 1612                 DELAY(100);
 1613                 s = splcam();
 1614         }
 1615         splx(s);
 1616 
 1617         if (timeout == 0) {
 1618                 printf("%s: aha_cmd: Timeout waiting for adapter idle\n",
 1619                        aha_name(aha));
 1620                 return (ETIMEDOUT);
 1621         }
 1622         aha->command_cmp = 0;
 1623         /*
 1624          * Wait up to 10 sec. for the adapter to become
 1625          * ready to accept commands.
 1626          */
 1627         timeout = 100000;
 1628         while (--timeout) {
 1629 
 1630                 status = aha_inb(aha, STATUS_REG);
 1631                 if ((status & HA_READY) != 0
 1632                  && (status & CMD_REG_BUSY) == 0)
 1633                         break;
 1634                 /*
 1635                  * Throw away any pending data which may be
 1636                  * left over from earlier commands that we
 1637                  * timedout on.
 1638                  */
 1639                 if ((status & DATAIN_REG_READY) != 0)
 1640                         (void)aha_inb(aha, DATAIN_REG);
 1641                 DELAY(100);
 1642         }
 1643         if (timeout == 0) {
 1644                 printf("%s: aha_cmd: Timeout waiting for adapter ready, "
 1645                        "status = 0x%x\n", aha_name(aha), status);
 1646                 return (ETIMEDOUT);
 1647         }
 1648 
 1649         /*
 1650          * Send the opcode followed by any necessary parameter bytes.
 1651          */
 1652         aha_outb(aha, COMMAND_REG, opcode);
 1653 
 1654         /*
 1655          * Wait for up to 1sec to get the parameter list sent
 1656          */
 1657         timeout = 10000;
 1658         while (param_len && --timeout) {
 1659                 DELAY(100);
 1660                 s = splcam();
 1661                 status = aha_inb(aha, STATUS_REG);
 1662                 intstat = aha_inb(aha, INTSTAT_REG);
 1663                 splx(s);
 1664 
 1665                 if ((intstat & (INTR_PENDING|CMD_COMPLETE))
 1666                  == (INTR_PENDING|CMD_COMPLETE)) {
 1667                         saved_status = status;
 1668                         cmd_complete = 1;
 1669                         break;
 1670                 }
 1671 
 1672                 if (aha->command_cmp != 0) {
 1673                         saved_status = aha->latched_status;
 1674                         cmd_complete = 1;
 1675                         break;
 1676                 }
 1677                 if ((status & DATAIN_REG_READY) != 0)
 1678                         break;
 1679                 if ((status & CMD_REG_BUSY) == 0) {
 1680                         aha_outb(aha, COMMAND_REG, *params++);
 1681                         param_len--;
 1682                         timeout = 10000;
 1683                 }
 1684         }
 1685         if (timeout == 0) {
 1686                 printf("%s: aha_cmd: Timeout sending parameters, "
 1687                        "status = 0x%x\n", aha_name(aha), status);
 1688                 error = ETIMEDOUT;
 1689         }
 1690 
 1691         /*
 1692          * For all other commands, we wait for any output data
 1693          * and the final comand completion interrupt.
 1694          */
 1695         while (cmd_complete == 0 && --cmd_timeout) {
 1696 
 1697                 s = splcam();
 1698                 status = aha_inb(aha, STATUS_REG);
 1699                 intstat = aha_inb(aha, INTSTAT_REG);
 1700                 splx(s);
 1701 
 1702                 if (aha->command_cmp != 0) {
 1703                         cmd_complete = 1;
 1704                         saved_status = aha->latched_status;
 1705                 } else if ((intstat & (INTR_PENDING|CMD_COMPLETE))
 1706                         == (INTR_PENDING|CMD_COMPLETE)) {
 1707                         /*
 1708                          * Our poll (in case interrupts are blocked)
 1709                          * saw the CMD_COMPLETE interrupt.
 1710                          */
 1711                         cmd_complete = 1;
 1712                         saved_status = status;
 1713                 } else if ((status & DATAIN_REG_READY) != 0) {
 1714                         u_int8_t data;
 1715 
 1716                         data = aha_inb(aha, DATAIN_REG);
 1717                         if (reply_len < reply_buf_size) {
 1718                                 *reply_data++ = data;
 1719                         } else {
 1720                                 printf("%s: aha_cmd - Discarded reply data "
 1721                                        "byte for opcode 0x%x\n", aha_name(aha),
 1722                                        opcode);
 1723                         }
 1724                         /*
 1725                          * Reset timeout to ensure at least a second
 1726                          * between response bytes.
 1727                          */
 1728                         cmd_timeout = MAX(cmd_timeout, 10000);
 1729                         reply_len++;
 1730                 }
 1731                 DELAY(100);
 1732         }
 1733         if (cmd_timeout == 0) {
 1734                 printf("%s: aha_cmd: Timeout waiting for reply data and "
 1735                        "command complete.\n%s: status = 0x%x, intstat = 0x%x, "
 1736                        "reply_len = %d\n", aha_name(aha), aha_name(aha), status,
 1737                        intstat, reply_len);
 1738                 return (ETIMEDOUT);
 1739         }
 1740 
 1741         /*
 1742          * Clear any pending interrupts.  Block interrupts so our
 1743          * interrupt handler is not re-entered.
 1744          */
 1745         s = splcam();
 1746         aha_intr(aha);
 1747         splx(s);
 1748         
 1749         if (error != 0)
 1750                 return (error);
 1751 
 1752         /*
 1753          * If the command was rejected by the controller, tell the caller.
 1754          */
 1755         if ((saved_status & CMD_INVALID) != 0) {
 1756                 PRVERB(("%s: Invalid Command 0x%x\n", aha_name(aha), opcode));
 1757                 /*
 1758                  * Some early adapters may not recover properly from
 1759                  * an invalid command.  If it appears that the controller
 1760                  * has wedged (i.e. status was not cleared by our interrupt
 1761                  * reset above), perform a soft reset.
 1762                  */
 1763                 DELAY(1000);
 1764                 status = aha_inb(aha, STATUS_REG);
 1765                 if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY|
 1766                               CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0
 1767                  || (status & (HA_READY|INIT_REQUIRED))
 1768                   != (HA_READY|INIT_REQUIRED)) {
 1769                         ahareset(aha, /*hard_reset*/FALSE);
 1770                 }
 1771                 return (EINVAL);
 1772         }
 1773 
 1774         if (param_len > 0) {
 1775                 /* The controller did not accept the full argument list */
 1776                 return (E2BIG);
 1777         }
 1778 
 1779         if (reply_len != reply_buf_size) {
 1780                 /* Too much or too little data received */
 1781                 return (EMSGSIZE);
 1782         }
 1783 
 1784         /* We were successful */
 1785         return (0);
 1786 }
 1787 
 1788 static int
 1789 ahainitmboxes(struct aha_softc *aha) 
 1790 {
 1791         int error;
 1792         init_24b_mbox_params_t init_mbox;
 1793 
 1794         bzero(aha->in_boxes, sizeof(aha_mbox_in_t) * aha->num_boxes);
 1795         bzero(aha->out_boxes, sizeof(aha_mbox_out_t) * aha->num_boxes);
 1796         aha->cur_inbox = aha->in_boxes;
 1797         aha->last_inbox = aha->in_boxes + aha->num_boxes - 1;
 1798         aha->cur_outbox = aha->out_boxes;
 1799         aha->last_outbox = aha->out_boxes + aha->num_boxes - 1;
 1800 
 1801         /* Tell the adapter about them */
 1802         init_mbox.num_mboxes = aha->num_boxes;
 1803         ahautoa24(aha->mailbox_physbase, init_mbox.base_addr);
 1804         error = aha_cmd(aha, AOP_INITIALIZE_MBOX, (u_int8_t *)&init_mbox,
 1805                        /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL,
 1806                        /*reply_len*/0, DEFAULT_CMD_TIMEOUT);
 1807 
 1808         if (error != 0)
 1809                 printf("ahainitmboxes: Initialization command failed\n");
 1810         return (error);
 1811 }
 1812 
 1813 /*
 1814  * Update the XPT's idea of the negotiated transfer
 1815  * parameters for a particular target.
 1816  */
 1817 static void
 1818 ahafetchtransinfo(struct aha_softc *aha, struct ccb_trans_settings* cts)
 1819 {
 1820         setup_data_t    setup_info;
 1821         u_int           target;
 1822         u_int           targ_offset;
 1823         u_int           sync_period;
 1824         int             error;
 1825         u_int8_t        param;
 1826         targ_syncinfo_t sync_info;
 1827 
 1828         target = cts->ccb_h.target_id;
 1829         targ_offset = (target & 0x7);
 1830 
 1831         /*
 1832          * Inquire Setup Information.  This command retreives
 1833          * the sync info for older models.
 1834          */
 1835         param = sizeof(setup_info);
 1836         error = aha_cmd(aha, AOP_INQUIRE_SETUP_INFO, &param, /*paramlen*/1,
 1837                        (u_int8_t*)&setup_info, sizeof(setup_info),
 1838                        DEFAULT_CMD_TIMEOUT);
 1839 
 1840         if (error != 0) {
 1841                 printf("%s: ahafetchtransinfo - Inquire Setup Info Failed %d\n",
 1842                        aha_name(aha), error);
 1843                 return;
 1844         }
 1845 
 1846         sync_info = setup_info.syncinfo[targ_offset];
 1847 
 1848         if (sync_info.sync == 0)
 1849                 cts->sync_offset = 0;
 1850         else
 1851                 cts->sync_offset = sync_info.offset;
 1852 
 1853         cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
 1854 
 1855         if (aha->boardid >= BOARD_1542CF)
 1856                 sync_period = 1000;
 1857         else
 1858                 sync_period = 2000;
 1859         sync_period += 500 * sync_info.period;
 1860 
 1861         /* Convert ns value to standard SCSI sync rate */
 1862         if (cts->sync_offset != 0)
 1863                 cts->sync_period = scsi_calc_syncparam(sync_period);
 1864         else
 1865                 cts->sync_period = 0;
 1866         
 1867         cts->valid = CCB_TRANS_SYNC_RATE_VALID
 1868                    | CCB_TRANS_SYNC_OFFSET_VALID
 1869                    | CCB_TRANS_BUS_WIDTH_VALID;
 1870         xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts);
 1871 }
 1872 
 1873 static void
 1874 ahamapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 1875 {
 1876         struct aha_softc* aha;
 1877 
 1878         aha = (struct aha_softc*)arg;
 1879         aha->mailbox_physbase = segs->ds_addr;
 1880 }
 1881 
 1882 static void
 1883 ahamapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 1884 {
 1885         struct aha_softc* aha;
 1886 
 1887         aha = (struct aha_softc*)arg;
 1888         aha->aha_ccb_physbase = segs->ds_addr;
 1889 }
 1890 
 1891 static void
 1892 ahamapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 1893 {
 1894 
 1895         struct aha_softc* aha;
 1896 
 1897         aha = (struct aha_softc*)arg;
 1898         SLIST_FIRST(&aha->sg_maps)->sg_physaddr = segs->ds_addr;
 1899 }
 1900 
 1901 static void
 1902 ahapoll(struct cam_sim *sim)
 1903 {
 1904         aha_intr(cam_sim_softc(sim));
 1905 }
 1906 
 1907 void
 1908 ahatimeout(void *arg)
 1909 {
 1910         struct aha_ccb  *accb;
 1911         union  ccb      *ccb;
 1912         struct aha_softc *aha;
 1913         int              s;
 1914         u_int32_t       paddr;
 1915 
 1916         accb = (struct aha_ccb *)arg;
 1917         ccb = accb->ccb;
 1918         aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr;
 1919         xpt_print_path(ccb->ccb_h.path);
 1920         printf("CCB %p - timed out\n", (void *)accb);
 1921 
 1922         s = splcam();
 1923 
 1924         if ((accb->flags & ACCB_ACTIVE) == 0) {
 1925                 xpt_print_path(ccb->ccb_h.path);
 1926                 printf("CCB %p - timed out CCB already completed\n",
 1927                        (void *)accb);
 1928                 splx(s);
 1929                 return;
 1930         }
 1931 
 1932         /*
 1933          * In order to simplify the recovery process, we ask the XPT
 1934          * layer to halt the queue of new transactions and we traverse
 1935          * the list of pending CCBs and remove their timeouts. This
 1936          * means that the driver attempts to clear only one error
 1937          * condition at a time.  In general, timeouts that occur
 1938          * close together are related anyway, so there is no benefit
 1939          * in attempting to handle errors in parrallel.  Timeouts will
 1940          * be reinstated when the recovery process ends.
 1941          */
 1942         if ((accb->flags & ACCB_DEVICE_RESET) == 0) {
 1943                 struct ccb_hdr *ccb_h;
 1944 
 1945                 if ((accb->flags & ACCB_RELEASE_SIMQ) == 0) {
 1946                         xpt_freeze_simq(aha->sim, /*count*/1);
 1947                         accb->flags |= ACCB_RELEASE_SIMQ;
 1948                 }
 1949 
 1950                 ccb_h = LIST_FIRST(&aha->pending_ccbs);
 1951                 while (ccb_h != NULL) {
 1952                         struct aha_ccb *pending_accb;
 1953 
 1954                         pending_accb = (struct aha_ccb *)ccb_h->ccb_accb_ptr;
 1955                         untimeout(ahatimeout, pending_accb, ccb_h->timeout_ch);
 1956                         ccb_h = LIST_NEXT(ccb_h, sim_links.le);
 1957                 }
 1958         }
 1959 
 1960         if ((accb->flags & ACCB_DEVICE_RESET) != 0
 1961          || aha->cur_outbox->action_code != AMBO_FREE) {
 1962                 /*
 1963                  * Try a full host adapter/SCSI bus reset.
 1964                  * We do this only if we have already attempted
 1965                  * to clear the condition with a BDR, or we cannot
 1966                  * attempt a BDR for lack of mailbox resources.
 1967                  */
 1968                 ccb->ccb_h.status = CAM_CMD_TIMEOUT;
 1969                 ahareset(aha, /*hardreset*/TRUE);
 1970                 printf("%s: No longer in timeout\n", aha_name(aha));
 1971         } else {
 1972                 /*    
 1973                  * Send a Bus Device Reset message:
 1974                  * The target that is holding up the bus may not
 1975                  * be the same as the one that triggered this timeout
 1976                  * (different commands have different timeout lengths),
 1977                  * but we have no way of determining this from our
 1978                  * timeout handler.  Our strategy here is to queue a
 1979                  * BDR message to the target of the timed out command.
 1980                  * If this fails, we'll get another timeout 2 seconds
 1981                  * later which will attempt a bus reset.
 1982                  */
 1983                 accb->flags |= ACCB_DEVICE_RESET;
 1984                 ccb->ccb_h.timeout_ch = timeout(ahatimeout, (caddr_t)accb, 2 * hz);
 1985                 aha->recovery_accb->hccb.opcode = INITIATOR_BUS_DEV_RESET;
 1986 
 1987                 /* No Data Transfer */
 1988                 aha->recovery_accb->hccb.datain = TRUE;
 1989                 aha->recovery_accb->hccb.dataout = TRUE;
 1990                 aha->recovery_accb->hccb.ahastat = 0;
 1991                 aha->recovery_accb->hccb.sdstat = 0;
 1992                 aha->recovery_accb->hccb.target = ccb->ccb_h.target_id;
 1993 
 1994                 /* Tell the adapter about this command */
 1995                 paddr = ahaccbvtop(aha, aha->recovery_accb);
 1996                 ahautoa24(paddr, aha->cur_outbox->ccb_addr);
 1997                 aha->cur_outbox->action_code = AMBO_START;
 1998                 aha_outb(aha, COMMAND_REG, AOP_START_MBOX);
 1999                 ahanextoutbox(aha);
 2000         }
 2001 
 2002         splx(s);
 2003 }

Cache object: 2599464727477389af0c90af4de22adf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.