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

Cache object: a9a458fd64ce856a424f304b89fb770e


[ 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.