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/advansys/advlib.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Low level routines for the Advanced Systems Inc. SCSI controllers chips
    3  *
    4  * Copyright (c) 1996-1997, 1999-2000 Justin Gibbs.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions, and the following disclaimer,
   12  *    without modification, immediately at the beginning of the file.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  * $FreeBSD: stable/4/sys/dev/advansys/advlib.c 59227 2000-04-14 13:32:54Z nyan $
   32  */
   33 /*
   34  * Ported from:
   35  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
   36  *     
   37  * Copyright (c) 1995-1996 Advanced System Products, Inc.
   38  * All Rights Reserved.
   39  *   
   40  * Redistribution and use in source and binary forms, with or without
   41  * modification, are permitted provided that redistributions of source
   42  * code retain the above copyright notice and this comment without
   43  * modification.
   44  */
   45 
   46 #include <sys/param.h>
   47 #include <sys/kernel.h>
   48 #include <sys/systm.h>
   49 
   50 #include <machine/bus_pio.h>
   51 #include <machine/bus.h>
   52 #include <machine/clock.h>
   53 #include <machine/resource.h>
   54 #include <sys/bus.h> 
   55 #include <sys/rman.h> 
   56 
   57 #include <cam/cam.h>
   58 #include <cam/cam_ccb.h>
   59 #include <cam/cam_sim.h>
   60 #include <cam/cam_xpt_sim.h>
   61 
   62 #include <cam/scsi/scsi_all.h>
   63 #include <cam/scsi/scsi_message.h>
   64 #include <cam/scsi/scsi_da.h>
   65 #include <cam/scsi/scsi_cd.h>
   66 
   67 #include <vm/vm.h>
   68 #include <vm/vm_param.h>
   69 #include <vm/pmap.h>
   70 
   71 #include <dev/advansys/advansys.h>
   72 #include <dev/advansys/advmcode.h>
   73 
   74 struct adv_quirk_entry {
   75         struct scsi_inquiry_pattern inq_pat;
   76         u_int8_t quirks;
   77 #define ADV_QUIRK_FIX_ASYN_XFER_ALWAYS  0x01
   78 #define ADV_QUIRK_FIX_ASYN_XFER         0x02
   79 };
   80 
   81 static struct adv_quirk_entry adv_quirk_table[] =
   82 {
   83         {
   84                 { T_CDROM, SIP_MEDIA_REMOVABLE, "HP", "*", "*" },
   85                 ADV_QUIRK_FIX_ASYN_XFER_ALWAYS|ADV_QUIRK_FIX_ASYN_XFER
   86         },
   87         {
   88                 { T_CDROM, SIP_MEDIA_REMOVABLE, "NEC", "CD-ROM DRIVE", "*" },
   89                 0
   90         },
   91         {
   92                 {
   93                   T_SEQUENTIAL, SIP_MEDIA_REMOVABLE,
   94                   "TANDBERG", " TDC 36", "*"
   95                 },
   96                 0
   97         },
   98         {
   99                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK", "*", "*" },
  100                 0
  101         },
  102         {
  103                 {
  104                   T_PROCESSOR, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
  105                   "*", "*", "*"
  106                 },
  107                 0
  108         },
  109         {
  110                 {
  111                   T_SCANNER, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
  112                   "*", "*", "*"
  113                 },
  114                 0
  115         },
  116         {
  117                 /* Default quirk entry */
  118                 {
  119                   T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
  120                   /*vendor*/"*", /*product*/"*", /*revision*/"*"
  121                 }, 
  122                 ADV_QUIRK_FIX_ASYN_XFER,
  123         }
  124 };
  125 
  126 /*
  127  * Allowable periods in ns
  128  */
  129 static u_int8_t adv_sdtr_period_tbl[] =
  130 {
  131         25,
  132         30,
  133         35,
  134         40,
  135         50,
  136         60,
  137         70,
  138         85
  139 };
  140 
  141 static u_int8_t adv_sdtr_period_tbl_ultra[] =
  142 {
  143         12,
  144         19,
  145         25,
  146         32,
  147         38,
  148         44,
  149         50,
  150         57,
  151         63,
  152         69,
  153         75,
  154         82,
  155         88, 
  156         94,
  157         100,
  158         107
  159 };
  160 
  161 struct ext_msg {
  162         u_int8_t msg_type;
  163         u_int8_t msg_len;
  164         u_int8_t msg_req;
  165         union {
  166                 struct {
  167                         u_int8_t sdtr_xfer_period;
  168                         u_int8_t sdtr_req_ack_offset;
  169                 } sdtr;
  170                 struct {
  171                         u_int8_t wdtr_width;
  172                 } wdtr;
  173                 struct {
  174                         u_int8_t mdp[4];
  175                 } mdp;
  176         } u_ext_msg;
  177         u_int8_t res;
  178 };
  179 
  180 #define xfer_period     u_ext_msg.sdtr.sdtr_xfer_period
  181 #define req_ack_offset  u_ext_msg.sdtr.sdtr_req_ack_offset
  182 #define wdtr_width      u_ext_msg.wdtr.wdtr_width
  183 #define mdp_b3          u_ext_msg.mdp_b3
  184 #define mdp_b2          u_ext_msg.mdp_b2
  185 #define mdp_b1          u_ext_msg.mdp_b1
  186 #define mdp_b0          u_ext_msg.mdp_b0
  187 
  188 /*
  189  * Some of the early PCI adapters have problems with
  190  * async transfers.  Instead use an offset of 1.
  191  */
  192 #define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
  193 
  194 /* LRAM routines */
  195 static void      adv_read_lram_16_multi(struct adv_softc *adv, u_int16_t s_addr,
  196                                         u_int16_t *buffer, int count);
  197 static void      adv_write_lram_16_multi(struct adv_softc *adv,
  198                                          u_int16_t s_addr, u_int16_t *buffer,
  199                                          int count);
  200 static void      adv_mset_lram_16(struct adv_softc *adv, u_int16_t s_addr,
  201                                   u_int16_t set_value, int count);
  202 static u_int32_t adv_msum_lram_16(struct adv_softc *adv, u_int16_t s_addr,
  203                                   int count);
  204 
  205 static int       adv_write_and_verify_lram_16(struct adv_softc *adv,
  206                                               u_int16_t addr, u_int16_t value);
  207 static u_int32_t adv_read_lram_32(struct adv_softc *adv, u_int16_t addr);
  208 
  209 
  210 static void      adv_write_lram_32(struct adv_softc *adv, u_int16_t addr,
  211                                    u_int32_t value);
  212 static void      adv_write_lram_32_multi(struct adv_softc *adv,
  213                                          u_int16_t s_addr, u_int32_t *buffer,
  214                                          int count);
  215 
  216 /* EEPROM routines */
  217 static u_int16_t adv_read_eeprom_16(struct adv_softc *adv, u_int8_t addr);
  218 static u_int16_t adv_write_eeprom_16(struct adv_softc *adv, u_int8_t addr,
  219                                      u_int16_t value);
  220 static int       adv_write_eeprom_cmd_reg(struct adv_softc *adv,
  221                                           u_int8_t cmd_reg);
  222 static int       adv_set_eeprom_config_once(struct adv_softc *adv,
  223                                             struct adv_eeprom_config *eeconfig);
  224 
  225 /* Initialization */
  226 static u_int32_t adv_load_microcode(struct adv_softc *adv, u_int16_t s_addr,
  227                                     u_int16_t *mcode_buf, u_int16_t mcode_size);
  228 
  229 static void      adv_reinit_lram(struct adv_softc *adv);
  230 static void      adv_init_lram(struct adv_softc *adv);
  231 static int       adv_init_microcode_var(struct adv_softc *adv);
  232 static void      adv_init_qlink_var(struct adv_softc *adv);
  233 
  234 /* Interrupts */
  235 static void      adv_disable_interrupt(struct adv_softc *adv);
  236 static void      adv_enable_interrupt(struct adv_softc *adv);
  237 static void      adv_toggle_irq_act(struct adv_softc *adv);
  238 
  239 /* Chip Control */
  240 static int       adv_host_req_chip_halt(struct adv_softc *adv);
  241 static void      adv_set_chip_ih(struct adv_softc *adv, u_int16_t ins_code);
  242 #if UNUSED
  243 static u_int8_t  adv_get_chip_scsi_ctrl(struct adv_softc *adv);
  244 #endif
  245 
  246 /* Queue handling and execution */
  247 static __inline int
  248                  adv_sgcount_to_qcount(int sgcount);
  249 
  250 static __inline int
  251 adv_sgcount_to_qcount(int sgcount)
  252 {
  253         int     n_sg_list_qs;
  254 
  255         n_sg_list_qs = ((sgcount - 1) / ADV_SG_LIST_PER_Q);
  256         if (((sgcount - 1) % ADV_SG_LIST_PER_Q) != 0)
  257                 n_sg_list_qs++;
  258         return (n_sg_list_qs + 1);
  259 }
  260 
  261 static void      adv_get_q_info(struct adv_softc *adv, u_int16_t s_addr,
  262                                 u_int16_t *inbuf, int words);
  263 static u_int     adv_get_num_free_queues(struct adv_softc *adv, u_int8_t n_qs);
  264 static u_int8_t  adv_alloc_free_queues(struct adv_softc *adv,
  265                                        u_int8_t free_q_head, u_int8_t n_free_q);
  266 static u_int8_t  adv_alloc_free_queue(struct adv_softc *adv,
  267                                       u_int8_t free_q_head);
  268 static int       adv_send_scsi_queue(struct adv_softc *adv,
  269                                      struct adv_scsi_q *scsiq,
  270                                      u_int8_t n_q_required);
  271 static void      adv_put_ready_sg_list_queue(struct adv_softc *adv,
  272                                              struct adv_scsi_q *scsiq,
  273                                              u_int q_no);
  274 static void      adv_put_ready_queue(struct adv_softc *adv,
  275                                      struct adv_scsi_q *scsiq, u_int q_no);
  276 static void      adv_put_scsiq(struct adv_softc *adv, u_int16_t s_addr,
  277                                u_int16_t *buffer, int words);
  278 
  279 /* Messages */
  280 static void      adv_handle_extmsg_in(struct adv_softc *adv,
  281                                       u_int16_t halt_q_addr, u_int8_t q_cntl,
  282                                       target_bit_vector target_id,
  283                                       int tid);
  284 static void      adv_msgout_sdtr(struct adv_softc *adv, u_int8_t sdtr_period,
  285                                  u_int8_t sdtr_offset);
  286 static void      adv_set_sdtr_reg_at_id(struct adv_softc *adv, int id,
  287                                         u_int8_t sdtr_data);
  288 
  289 
  290 /* Exported functions first */
  291 
  292 void
  293 advasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
  294 {
  295         struct adv_softc *adv;
  296 
  297         adv = (struct adv_softc *)callback_arg;
  298         switch (code) {
  299         case AC_FOUND_DEVICE:
  300         {
  301                 struct ccb_getdev *cgd;
  302                 target_bit_vector target_mask;
  303                 int num_entries;
  304                 caddr_t match;
  305                 struct adv_quirk_entry *entry;
  306                 struct adv_target_transinfo* tinfo;
  307  
  308                 cgd = (struct ccb_getdev *)arg;
  309 
  310                 target_mask = ADV_TID_TO_TARGET_MASK(cgd->ccb_h.target_id);
  311 
  312                 num_entries = sizeof(adv_quirk_table)/sizeof(*adv_quirk_table);
  313                 match = cam_quirkmatch((caddr_t)&cgd->inq_data,
  314                                        (caddr_t)adv_quirk_table,
  315                                        num_entries, sizeof(*adv_quirk_table),
  316                                        scsi_inquiry_match);
  317         
  318                 if (match == NULL)
  319                         panic("advasync: device didn't match wildcard entry!!");
  320 
  321                 entry = (struct adv_quirk_entry *)match;
  322 
  323                 if (adv->bug_fix_control & ADV_BUG_FIX_ASYN_USE_SYN) {
  324                         if ((entry->quirks & ADV_QUIRK_FIX_ASYN_XFER_ALWAYS)!=0)
  325                                 adv->fix_asyn_xfer_always |= target_mask;
  326                         else
  327                                 adv->fix_asyn_xfer_always &= ~target_mask;
  328                         /*
  329                          * We start out life with all bits set and clear them
  330                          * after we've determined that the fix isn't necessary.
  331                          * It may well be that we've already cleared a target
  332                          * before the full inquiry session completes, so don't
  333                          * gratuitously set a target bit even if it has this
  334                          * quirk.  But, if the quirk exonerates a device, clear
  335                          * the bit now.
  336                          */
  337                         if ((entry->quirks & ADV_QUIRK_FIX_ASYN_XFER) == 0)
  338                                 adv->fix_asyn_xfer &= ~target_mask;
  339                 }
  340                 /*
  341                  * Reset our sync settings now that we've determined
  342                  * what quirks are in effect for the device.
  343                  */
  344                 tinfo = &adv->tinfo[cgd->ccb_h.target_id];
  345                 adv_set_syncrate(adv, cgd->ccb_h.path,
  346                                  cgd->ccb_h.target_id,
  347                                  tinfo->current.period,
  348                                  tinfo->current.offset,
  349                                  ADV_TRANS_CUR);
  350                 break;
  351         }
  352         case AC_LOST_DEVICE:
  353         {
  354                 u_int target_mask;
  355 
  356                 if (adv->bug_fix_control & ADV_BUG_FIX_ASYN_USE_SYN) {
  357                         target_mask = 0x01 << xpt_path_target_id(path);
  358                         adv->fix_asyn_xfer |= target_mask;
  359                 }
  360 
  361                 /*
  362                  * Revert to async transfers
  363                  * for the next device.
  364                  */
  365                 adv_set_syncrate(adv, /*path*/NULL,
  366                                  xpt_path_target_id(path),
  367                                  /*period*/0,
  368                                  /*offset*/0,
  369                                  ADV_TRANS_GOAL|ADV_TRANS_CUR);
  370         }
  371         default:
  372                 break;
  373         }
  374 }
  375 
  376 void
  377 adv_set_bank(struct adv_softc *adv, u_int8_t bank)
  378 {
  379         u_int8_t control;
  380 
  381         /*
  382          * Start out with the bank reset to 0
  383          */
  384         control = ADV_INB(adv, ADV_CHIP_CTRL)
  385                   &  (~(ADV_CC_SINGLE_STEP | ADV_CC_TEST
  386                         | ADV_CC_DIAG | ADV_CC_SCSI_RESET
  387                         | ADV_CC_CHIP_RESET | ADV_CC_BANK_ONE));
  388         if (bank == 1) {
  389                 control |= ADV_CC_BANK_ONE;
  390         } else if (bank == 2) {
  391                 control |= ADV_CC_DIAG | ADV_CC_BANK_ONE;
  392         }
  393         ADV_OUTB(adv, ADV_CHIP_CTRL, control);
  394 }
  395 
  396 u_int8_t
  397 adv_read_lram_8(struct adv_softc *adv, u_int16_t addr)
  398 {
  399         u_int8_t   byte_data;
  400         u_int16_t  word_data;
  401 
  402         /*
  403          * LRAM is accessed on 16bit boundaries.
  404          */
  405         ADV_OUTW(adv, ADV_LRAM_ADDR, addr & 0xFFFE);
  406         word_data = ADV_INW(adv, ADV_LRAM_DATA);
  407         if (addr & 1) {
  408 #if BYTE_ORDER == BIG_ENDIAN
  409                 byte_data = (u_int8_t)(word_data & 0xFF);
  410 #else
  411                 byte_data = (u_int8_t)((word_data >> 8) & 0xFF);
  412 #endif
  413         } else {
  414 #if BYTE_ORDER == BIG_ENDIAN
  415                 byte_data = (u_int8_t)((word_data >> 8) & 0xFF);
  416 #else           
  417                 byte_data = (u_int8_t)(word_data & 0xFF);
  418 #endif
  419         }
  420         return (byte_data);
  421 }
  422 
  423 void
  424 adv_write_lram_8(struct adv_softc *adv, u_int16_t addr, u_int8_t value)
  425 {
  426         u_int16_t word_data;
  427 
  428         word_data = adv_read_lram_16(adv, addr & 0xFFFE);
  429         if (addr & 1) {
  430                 word_data &= 0x00FF;
  431                 word_data |= (((u_int8_t)value << 8) & 0xFF00);
  432         } else {
  433                 word_data &= 0xFF00;
  434                 word_data |= ((u_int8_t)value & 0x00FF);
  435         }
  436         adv_write_lram_16(adv, addr & 0xFFFE, word_data);
  437 }
  438 
  439 
  440 u_int16_t
  441 adv_read_lram_16(struct adv_softc *adv, u_int16_t addr)
  442 {
  443         ADV_OUTW(adv, ADV_LRAM_ADDR, addr);
  444         return (ADV_INW(adv, ADV_LRAM_DATA));
  445 }
  446 
  447 void
  448 adv_write_lram_16(struct adv_softc *adv, u_int16_t addr, u_int16_t value)
  449 {
  450         ADV_OUTW(adv, ADV_LRAM_ADDR, addr);
  451         ADV_OUTW(adv, ADV_LRAM_DATA, value);
  452 }
  453 
  454 /*
  455  * Determine if there is a board at "iobase" by looking
  456  * for the AdvanSys signatures.  Return 1 if a board is
  457  * found, 0 otherwise.
  458  */
  459 int                         
  460 adv_find_signature(bus_space_tag_t tag, bus_space_handle_t bsh)
  461 {                            
  462         u_int16_t signature;
  463 
  464         if (bus_space_read_1(tag, bsh, ADV_SIGNATURE_BYTE) == ADV_1000_ID1B) {
  465                 signature = bus_space_read_2(tag, bsh, ADV_SIGNATURE_WORD);
  466                 if ((signature == ADV_1000_ID0W)
  467                  || (signature == ADV_1000_ID0W_FIX))
  468                         return (1);
  469         }
  470         return (0);
  471 }
  472 
  473 void
  474 adv_lib_init(struct adv_softc *adv)
  475 {
  476         if ((adv->type & ADV_ULTRA) != 0) {
  477                 adv->sdtr_period_tbl = adv_sdtr_period_tbl_ultra;
  478                 adv->sdtr_period_tbl_size = sizeof(adv_sdtr_period_tbl_ultra);
  479         } else {
  480                 adv->sdtr_period_tbl = adv_sdtr_period_tbl;
  481                 adv->sdtr_period_tbl_size = sizeof(adv_sdtr_period_tbl);                
  482         }
  483 }
  484 
  485 u_int16_t
  486 adv_get_eeprom_config(struct adv_softc *adv, struct
  487                       adv_eeprom_config  *eeprom_config)
  488 {
  489         u_int16_t       sum;
  490         u_int16_t       *wbuf;
  491         u_int8_t        cfg_beg;
  492         u_int8_t        cfg_end;
  493         u_int8_t        s_addr;
  494 
  495         wbuf = (u_int16_t *)eeprom_config;
  496         sum = 0;
  497 
  498         for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
  499                 *wbuf = adv_read_eeprom_16(adv, s_addr);
  500                 sum += *wbuf;
  501         }
  502 
  503         if (adv->type & ADV_VL) {
  504                 cfg_beg = ADV_EEPROM_CFG_BEG_VL;
  505                 cfg_end = ADV_EEPROM_MAX_ADDR_VL;
  506         } else {
  507                 cfg_beg = ADV_EEPROM_CFG_BEG;
  508                 cfg_end = ADV_EEPROM_MAX_ADDR;
  509         }
  510 
  511         for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
  512                 *wbuf = adv_read_eeprom_16(adv, s_addr);
  513                 sum += *wbuf;
  514 #if ADV_DEBUG_EEPROM
  515                 printf("Addr 0x%x: 0x%04x\n", s_addr, *wbuf);
  516 #endif
  517         }
  518         *wbuf = adv_read_eeprom_16(adv, s_addr);
  519         return (sum);
  520 }
  521 
  522 int
  523 adv_set_eeprom_config(struct adv_softc *adv,
  524                       struct adv_eeprom_config *eeprom_config)
  525 {
  526         int     retry;
  527 
  528         retry = 0;
  529         while (1) {
  530                 if (adv_set_eeprom_config_once(adv, eeprom_config) == 0) {
  531                         break;
  532                 }
  533                 if (++retry > ADV_EEPROM_MAX_RETRY) {
  534                         break;
  535                 }
  536         }
  537         return (retry > ADV_EEPROM_MAX_RETRY);
  538 }
  539 
  540 int
  541 adv_reset_chip(struct adv_softc *adv, int reset_bus)
  542 {
  543         adv_stop_chip(adv);
  544         ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_CHIP_RESET | ADV_CC_HALT
  545                                      | (reset_bus ? ADV_CC_SCSI_RESET : 0));
  546         DELAY(60);
  547 
  548         adv_set_chip_ih(adv, ADV_INS_RFLAG_WTM);
  549         adv_set_chip_ih(adv, ADV_INS_HALT);
  550 
  551         if (reset_bus)
  552                 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_CHIP_RESET | ADV_CC_HALT);
  553 
  554         ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
  555         if (reset_bus)
  556                 DELAY(200 * 1000);
  557 
  558         ADV_OUTW(adv, ADV_CHIP_STATUS, ADV_CIW_CLR_SCSI_RESET_INT);
  559         ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
  560         return (adv_is_chip_halted(adv));
  561 }
  562 
  563 int
  564 adv_test_external_lram(struct adv_softc* adv)
  565 {
  566         u_int16_t       q_addr;
  567         u_int16_t       saved_value;
  568         int             success;
  569 
  570         success = 0;
  571 
  572         q_addr = ADV_QNO_TO_QADDR(241);
  573         saved_value = adv_read_lram_16(adv, q_addr);
  574         if (adv_write_and_verify_lram_16(adv, q_addr, 0x55AA) == 0) {
  575                 success = 1;
  576                 adv_write_lram_16(adv, q_addr, saved_value);
  577         }
  578         return (success);
  579 }
  580 
  581 
  582 int
  583 adv_init_lram_and_mcode(struct adv_softc *adv)
  584 {
  585         u_int32_t       retval;
  586 
  587         adv_disable_interrupt(adv);
  588 
  589         adv_init_lram(adv);
  590 
  591         retval = adv_load_microcode(adv, 0, (u_int16_t *)adv_mcode,
  592                                     adv_mcode_size);
  593         if (retval != adv_mcode_chksum) {
  594                 printf("adv%d: Microcode download failed checksum!\n",
  595                        adv->unit);
  596                 return (1);
  597         }
  598         
  599         if (adv_init_microcode_var(adv) != 0)
  600                 return (1);
  601 
  602         adv_enable_interrupt(adv);
  603         return (0);
  604 }
  605 
  606 u_int8_t
  607 adv_get_chip_irq(struct adv_softc *adv)
  608 {
  609         u_int16_t       cfg_lsw;
  610         u_int8_t        chip_irq;
  611 
  612         cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW);
  613 
  614         if ((adv->type & ADV_VL) != 0) {
  615                 chip_irq = (u_int8_t)(((cfg_lsw >> 2) & 0x07));
  616                 if ((chip_irq == 0) ||
  617                     (chip_irq == 4) ||
  618                     (chip_irq == 7)) {
  619                         return (0);
  620                 }
  621                 return (chip_irq + (ADV_MIN_IRQ_NO - 1));
  622         }
  623         chip_irq = (u_int8_t)(((cfg_lsw >> 2) & 0x03));
  624         if (chip_irq == 3)
  625                 chip_irq += 2;
  626         return (chip_irq + ADV_MIN_IRQ_NO);
  627 }
  628 
  629 u_int8_t
  630 adv_set_chip_irq(struct adv_softc *adv, u_int8_t irq_no)
  631 {
  632         u_int16_t       cfg_lsw;
  633 
  634         if ((adv->type & ADV_VL) != 0) {
  635                 if (irq_no != 0) {
  636                         if ((irq_no < ADV_MIN_IRQ_NO)
  637                          || (irq_no > ADV_MAX_IRQ_NO)) {
  638                                 irq_no = 0;
  639                         } else {
  640                                 irq_no -= ADV_MIN_IRQ_NO - 1;
  641                         }
  642                 }
  643                 cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW) & 0xFFE3;
  644                 cfg_lsw |= 0x0010;
  645                 ADV_OUTW(adv, ADV_CONFIG_LSW, cfg_lsw);
  646                 adv_toggle_irq_act(adv);
  647 
  648                 cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW) & 0xFFE0;
  649                 cfg_lsw |= (irq_no & 0x07) << 2;
  650                 ADV_OUTW(adv, ADV_CONFIG_LSW, cfg_lsw);
  651                 adv_toggle_irq_act(adv);
  652         } else if ((adv->type & ADV_ISA) != 0) {
  653                 if (irq_no == 15)
  654                         irq_no -= 2;
  655                 irq_no -= ADV_MIN_IRQ_NO;
  656                 cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW) & 0xFFF3;
  657                 cfg_lsw |= (irq_no & 0x03) << 2;
  658                 ADV_OUTW(adv, ADV_CONFIG_LSW, cfg_lsw);
  659         }
  660         return (adv_get_chip_irq(adv));
  661 }
  662 
  663 void
  664 adv_set_chip_scsiid(struct adv_softc *adv, int new_id)
  665 {
  666         u_int16_t cfg_lsw;
  667 
  668         cfg_lsw = ADV_INW(adv, ADV_CONFIG_LSW);
  669         if (ADV_CONFIG_SCSIID(cfg_lsw) == new_id)
  670                 return;
  671         cfg_lsw &= ~ADV_CFG_LSW_SCSIID;
  672         cfg_lsw |= (new_id & ADV_MAX_TID) << ADV_CFG_LSW_SCSIID_SHIFT;
  673         ADV_OUTW(adv, ADV_CONFIG_LSW, cfg_lsw);
  674 }
  675 
  676 int
  677 adv_execute_scsi_queue(struct adv_softc *adv, struct adv_scsi_q *scsiq,
  678                        u_int32_t datalen)
  679 {
  680         struct          adv_target_transinfo* tinfo;
  681         u_int32_t       *p_data_addr;
  682         u_int32_t       *p_data_bcount;
  683         int             disable_syn_offset_one_fix;
  684         int             retval;
  685         u_int           n_q_required;
  686         u_int32_t       addr;
  687         u_int8_t        sg_entry_cnt;
  688         u_int8_t        target_ix;
  689         u_int8_t        sg_entry_cnt_minus_one;
  690         u_int8_t        tid_no;
  691 
  692         scsiq->q1.q_no = 0;
  693         retval = 1;  /* Default to error case */
  694         target_ix = scsiq->q2.target_ix;
  695         tid_no = ADV_TIX_TO_TID(target_ix);
  696         tinfo = &adv->tinfo[tid_no];
  697 
  698         if (scsiq->cdbptr[0] == REQUEST_SENSE) {
  699                 /* Renegotiate if appropriate. */
  700                 adv_set_syncrate(adv, /*struct cam_path */NULL,
  701                                  tid_no, /*period*/0, /*offset*/0,
  702                                  ADV_TRANS_CUR);
  703                 if (tinfo->current.period != tinfo->goal.period) {
  704                         adv_msgout_sdtr(adv, tinfo->goal.period,
  705                                         tinfo->goal.offset);
  706                         scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
  707                 }
  708         }
  709 
  710         if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
  711                 sg_entry_cnt = scsiq->sg_head->entry_cnt;
  712                 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
  713 
  714 #ifdef DIAGNOSTIC
  715                 if (sg_entry_cnt <= 1) 
  716                         panic("adv_execute_scsi_queue: Queue "
  717                               "with QC_SG_HEAD set but %d segs.", sg_entry_cnt);
  718 
  719                 if (sg_entry_cnt > ADV_MAX_SG_LIST)
  720                         panic("adv_execute_scsi_queue: "
  721                               "Queue with too many segs.");
  722 
  723                 if ((adv->type & (ADV_ISA | ADV_VL | ADV_EISA)) != 0) {
  724                         int i;
  725 
  726                         for (i = 0; i < sg_entry_cnt_minus_one; i++) {
  727                                 addr = scsiq->sg_head->sg_list[i].addr +
  728                                        scsiq->sg_head->sg_list[i].bytes;
  729 
  730                                 if ((addr & 0x0003) != 0)
  731                                         panic("adv_execute_scsi_queue: SG "
  732                                               "with odd address or byte count");
  733                         }
  734                 }
  735 #endif
  736                 p_data_addr =
  737                     &scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].addr;
  738                 p_data_bcount =
  739                     &scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
  740 
  741                 n_q_required = adv_sgcount_to_qcount(sg_entry_cnt);
  742                 scsiq->sg_head->queue_cnt = n_q_required - 1;
  743         } else {
  744                 p_data_addr = &scsiq->q1.data_addr;
  745                 p_data_bcount = &scsiq->q1.data_cnt;
  746                 n_q_required = 1;
  747         }
  748 
  749         disable_syn_offset_one_fix = FALSE;
  750 
  751         if ((adv->fix_asyn_xfer & scsiq->q1.target_id) != 0
  752          && (adv->fix_asyn_xfer_always & scsiq->q1.target_id) == 0) {
  753 
  754                 if (datalen != 0) {
  755                         if (datalen < 512) {
  756                                 disable_syn_offset_one_fix = TRUE;
  757                         } else {
  758                                 if (scsiq->cdbptr[0] == INQUIRY
  759                                  || scsiq->cdbptr[0] == REQUEST_SENSE
  760                                  || scsiq->cdbptr[0] == READ_CAPACITY
  761                                  || scsiq->cdbptr[0] == MODE_SELECT_6 
  762                                  || scsiq->cdbptr[0] == MODE_SENSE_6
  763                                  || scsiq->cdbptr[0] == MODE_SENSE_10 
  764                                  || scsiq->cdbptr[0] == MODE_SELECT_10 
  765                                  || scsiq->cdbptr[0] == READ_TOC) {
  766                                         disable_syn_offset_one_fix = TRUE;
  767                                 }
  768                         }
  769                 }
  770         }
  771 
  772         if (disable_syn_offset_one_fix) {
  773                 scsiq->q2.tag_code &=
  774                     ~(MSG_SIMPLE_Q_TAG|MSG_HEAD_OF_Q_TAG|MSG_ORDERED_Q_TAG);
  775                 scsiq->q2.tag_code |= (ADV_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX
  776                                      | ADV_TAG_FLAG_DISABLE_DISCONNECT);
  777         }
  778 
  779         if ((adv->bug_fix_control & ADV_BUG_FIX_IF_NOT_DWB) != 0
  780          && (scsiq->cdbptr[0] == READ_10 || scsiq->cdbptr[0] == READ_6)) {
  781                 u_int8_t extra_bytes;
  782 
  783                 addr = *p_data_addr + *p_data_bcount;
  784                 extra_bytes = addr & 0x0003;
  785                 if (extra_bytes != 0
  786                  && ((scsiq->q1.cntl & QC_SG_HEAD) != 0
  787                   || (scsiq->q1.data_cnt & 0x01FF) == 0)) {
  788                         scsiq->q2.tag_code |= ADV_TAG_FLAG_EXTRA_BYTES;
  789                         scsiq->q1.extra_bytes = extra_bytes;
  790                         *p_data_bcount -= extra_bytes;
  791                 }
  792         }
  793 
  794         if ((adv_get_num_free_queues(adv, n_q_required) >= n_q_required)
  795          || ((scsiq->q1.cntl & QC_URGENT) != 0))
  796                 retval = adv_send_scsi_queue(adv, scsiq, n_q_required);
  797         
  798         return (retval);
  799 }
  800 
  801 
  802 u_int8_t
  803 adv_copy_lram_doneq(struct adv_softc *adv, u_int16_t q_addr,
  804                     struct adv_q_done_info *scsiq, u_int32_t max_dma_count)
  805 {
  806         u_int16_t val;
  807         u_int8_t  sg_queue_cnt;
  808 
  809         adv_get_q_info(adv, q_addr + ADV_SCSIQ_DONE_INFO_BEG,
  810                        (u_int16_t *)scsiq,
  811                        (sizeof(scsiq->d2) + sizeof(scsiq->d3)) / 2);
  812 
  813 #if BYTE_ORDER == BIG_ENDIAN
  814         adv_adj_endian_qdone_info(scsiq);
  815 #endif
  816 
  817         val = adv_read_lram_16(adv, q_addr + ADV_SCSIQ_B_STATUS);
  818         scsiq->q_status = val & 0xFF;
  819         scsiq->q_no = (val >> 8) & 0XFF;
  820 
  821         val = adv_read_lram_16(adv, q_addr + ADV_SCSIQ_B_CNTL);
  822         scsiq->cntl = val & 0xFF;
  823         sg_queue_cnt = (val >> 8) & 0xFF;
  824 
  825         val = adv_read_lram_16(adv,q_addr + ADV_SCSIQ_B_SENSE_LEN);
  826         scsiq->sense_len = val & 0xFF;
  827         scsiq->extra_bytes = (val >> 8) & 0xFF;
  828 
  829         /*
  830          * Due to a bug in accessing LRAM on the 940UA, the residual
  831          * is split into separate high and low 16bit quantities.
  832          */
  833         scsiq->remain_bytes =
  834             adv_read_lram_16(adv, q_addr + ADV_SCSIQ_DW_REMAIN_XFER_CNT);
  835         scsiq->remain_bytes |=
  836             adv_read_lram_16(adv, q_addr + ADV_SCSIQ_W_ALT_DC1) << 16;
  837 
  838         /*
  839          * XXX Is this just a safeguard or will the counter really
  840          * have bogus upper bits?
  841          */
  842         scsiq->remain_bytes &= max_dma_count;
  843 
  844         return (sg_queue_cnt);
  845 }
  846 
  847 int
  848 adv_start_chip(struct adv_softc *adv)
  849 {
  850         ADV_OUTB(adv, ADV_CHIP_CTRL, 0);
  851         if ((ADV_INW(adv, ADV_CHIP_STATUS) & ADV_CSW_HALTED) != 0)
  852                 return (0);
  853         return (1);
  854 }
  855 
  856 int
  857 adv_stop_execution(struct adv_softc *adv)
  858 {
  859         int count;
  860 
  861         count = 0;
  862         if (adv_read_lram_8(adv, ADV_STOP_CODE_B) == 0) {
  863                 adv_write_lram_8(adv, ADV_STOP_CODE_B,
  864                                  ADV_STOP_REQ_RISC_STOP);
  865                 do {
  866                         if (adv_read_lram_8(adv, ADV_STOP_CODE_B) &
  867                                 ADV_STOP_ACK_RISC_STOP) {
  868                                 return (1);
  869                         }
  870                         DELAY(1000);
  871                 } while (count++ < 20);
  872         }
  873         return (0);
  874 }
  875 
  876 int
  877 adv_is_chip_halted(struct adv_softc *adv)
  878 {
  879         if ((ADV_INW(adv, ADV_CHIP_STATUS) & ADV_CSW_HALTED) != 0) {
  880                 if ((ADV_INB(adv, ADV_CHIP_CTRL) & ADV_CC_HALT) != 0) {
  881                         return (1);
  882                 }
  883         }
  884         return (0);
  885 }
  886 
  887 /*
  888  * XXX The numeric constants and the loops in this routine
  889  * need to be documented.
  890  */
  891 void
  892 adv_ack_interrupt(struct adv_softc *adv)
  893 {
  894         u_int8_t        host_flag;
  895         u_int8_t        risc_flag;
  896         int             loop;
  897 
  898         loop = 0;
  899         do {
  900                 risc_flag = adv_read_lram_8(adv, ADVV_RISC_FLAG_B);
  901                 if (loop++ > 0x7FFF) {
  902                         break;
  903                 }
  904         } while ((risc_flag & ADV_RISC_FLAG_GEN_INT) != 0);
  905 
  906         host_flag = adv_read_lram_8(adv, ADVV_HOST_FLAG_B);
  907         adv_write_lram_8(adv, ADVV_HOST_FLAG_B,
  908                          host_flag | ADV_HOST_FLAG_ACK_INT);
  909 
  910         ADV_OUTW(adv, ADV_CHIP_STATUS, ADV_CIW_INT_ACK);
  911         loop = 0;
  912         while (ADV_INW(adv, ADV_CHIP_STATUS) & ADV_CSW_INT_PENDING) {
  913                 ADV_OUTW(adv, ADV_CHIP_STATUS, ADV_CIW_INT_ACK);
  914                 if (loop++ > 3) {
  915                         break;
  916                 }
  917         }
  918 
  919         adv_write_lram_8(adv, ADVV_HOST_FLAG_B, host_flag);
  920 }
  921 
  922 /*
  923  * Handle all conditions that may halt the chip waiting
  924  * for us to intervene.
  925  */
  926 void
  927 adv_isr_chip_halted(struct adv_softc *adv)
  928 {
  929         u_int16_t         int_halt_code;
  930         u_int16_t         halt_q_addr;
  931         target_bit_vector target_mask;
  932         target_bit_vector scsi_busy;
  933         u_int8_t          halt_qp;
  934         u_int8_t          target_ix;
  935         u_int8_t          q_cntl;
  936         u_int8_t          tid_no;
  937 
  938         int_halt_code = adv_read_lram_16(adv, ADVV_HALTCODE_W);
  939         halt_qp = adv_read_lram_8(adv, ADVV_CURCDB_B);
  940         halt_q_addr = ADV_QNO_TO_QADDR(halt_qp);
  941         target_ix = adv_read_lram_8(adv, halt_q_addr + ADV_SCSIQ_B_TARGET_IX);
  942         q_cntl = adv_read_lram_8(adv, halt_q_addr + ADV_SCSIQ_B_CNTL);
  943         tid_no = ADV_TIX_TO_TID(target_ix);
  944         target_mask = ADV_TID_TO_TARGET_MASK(tid_no);
  945         if (int_halt_code == ADV_HALT_DISABLE_ASYN_USE_SYN_FIX) {
  946                 /*
  947                  * Temporarily disable the async fix by removing
  948                  * this target from the list of affected targets,
  949                  * setting our async rate, and then putting us
  950                  * back into the mask.
  951                  */
  952                 adv->fix_asyn_xfer &= ~target_mask;
  953                 adv_set_syncrate(adv, /*struct cam_path */NULL,
  954                                  tid_no, /*period*/0, /*offset*/0,
  955                                  ADV_TRANS_ACTIVE);
  956                 adv->fix_asyn_xfer |= target_mask;
  957         } else if (int_halt_code == ADV_HALT_ENABLE_ASYN_USE_SYN_FIX) {
  958                 adv_set_syncrate(adv, /*struct cam_path */NULL,
  959                                  tid_no, /*period*/0, /*offset*/0,
  960                                  ADV_TRANS_ACTIVE);
  961         } else if (int_halt_code == ADV_HALT_EXTMSG_IN) {
  962                 adv_handle_extmsg_in(adv, halt_q_addr, q_cntl,
  963                                      target_mask, tid_no);
  964         } else if (int_halt_code == ADV_HALT_CHK_CONDITION) {
  965                 struct    adv_target_transinfo* tinfo;
  966                 union     ccb *ccb;
  967                 u_int32_t cinfo_index;
  968                 u_int8_t  tag_code;
  969                 u_int8_t  q_status;
  970 
  971                 tinfo = &adv->tinfo[tid_no];
  972                 q_cntl |= QC_REQ_SENSE;
  973 
  974                 /* Renegotiate if appropriate. */
  975                 adv_set_syncrate(adv, /*struct cam_path */NULL,
  976                                  tid_no, /*period*/0, /*offset*/0,
  977                                  ADV_TRANS_CUR);
  978                 if (tinfo->current.period != tinfo->goal.period) {
  979                         adv_msgout_sdtr(adv, tinfo->goal.period,
  980                                         tinfo->goal.offset);
  981                         q_cntl |= QC_MSG_OUT;
  982                 }
  983                 adv_write_lram_8(adv, halt_q_addr + ADV_SCSIQ_B_CNTL, q_cntl);
  984 
  985                 /* Don't tag request sense commands */
  986                 tag_code = adv_read_lram_8(adv,
  987                                            halt_q_addr + ADV_SCSIQ_B_TAG_CODE);
  988                 tag_code &=
  989                     ~(MSG_SIMPLE_Q_TAG|MSG_HEAD_OF_Q_TAG|MSG_ORDERED_Q_TAG);
  990 
  991                 if ((adv->fix_asyn_xfer & target_mask) != 0
  992                  && (adv->fix_asyn_xfer_always & target_mask) == 0) {
  993                         tag_code |= (ADV_TAG_FLAG_DISABLE_DISCONNECT
  994                                  | ADV_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
  995                 }
  996                 adv_write_lram_8(adv, halt_q_addr + ADV_SCSIQ_B_TAG_CODE,
  997                                  tag_code);
  998                 q_status = adv_read_lram_8(adv,
  999                                            halt_q_addr + ADV_SCSIQ_B_STATUS);
 1000                 q_status |= (QS_READY | QS_BUSY);
 1001                 adv_write_lram_8(adv, halt_q_addr + ADV_SCSIQ_B_STATUS,
 1002                                  q_status);
 1003                 /*
 1004                  * Freeze the devq until we can handle the sense condition.
 1005                  */
 1006                 cinfo_index =
 1007                     adv_read_lram_32(adv, halt_q_addr + ADV_SCSIQ_D_CINFO_IDX);
 1008                 ccb = adv->ccb_infos[cinfo_index].ccb;
 1009                 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
 1010                 ccb->ccb_h.status |= CAM_DEV_QFRZN;
 1011                 adv_abort_ccb(adv, tid_no, ADV_TIX_TO_LUN(target_ix),
 1012                               /*ccb*/NULL, CAM_REQUEUE_REQ,
 1013                               /*queued_only*/TRUE);
 1014                 scsi_busy = adv_read_lram_8(adv, ADVV_SCSIBUSY_B);
 1015                 scsi_busy &= ~target_mask;
 1016                 adv_write_lram_8(adv, ADVV_SCSIBUSY_B, scsi_busy);
 1017                 /*
 1018                  * Ensure we have enough time to actually
 1019                  * retrieve the sense.
 1020                  */
 1021                 untimeout(adv_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch);
 1022                 ccb->ccb_h.timeout_ch =
 1023                     timeout(adv_timeout, (caddr_t)ccb, 5 * hz);
 1024         } else if (int_halt_code == ADV_HALT_SDTR_REJECTED) {
 1025                 struct  ext_msg out_msg;
 1026 
 1027                 adv_read_lram_16_multi(adv, ADVV_MSGOUT_BEG,
 1028                                        (u_int16_t *) &out_msg,
 1029                                        sizeof(out_msg)/2);
 1030 
 1031                 if ((out_msg.msg_type == MSG_EXTENDED)
 1032                  && (out_msg.msg_len == MSG_EXT_SDTR_LEN)
 1033                  && (out_msg.msg_req == MSG_EXT_SDTR)) {
 1034 
 1035                         /* Revert to Async */
 1036                         adv_set_syncrate(adv, /*struct cam_path */NULL,
 1037                                          tid_no, /*period*/0, /*offset*/0,
 1038                                          ADV_TRANS_GOAL|ADV_TRANS_ACTIVE);
 1039                 }
 1040                 q_cntl &= ~QC_MSG_OUT;
 1041                 adv_write_lram_8(adv, halt_q_addr + ADV_SCSIQ_B_CNTL, q_cntl);
 1042         } else if (int_halt_code == ADV_HALT_SS_QUEUE_FULL) {
 1043                 u_int8_t scsi_status;
 1044                 union ccb *ccb;
 1045                 u_int32_t cinfo_index;
 1046                 
 1047                 scsi_status = adv_read_lram_8(adv, halt_q_addr
 1048                                               + ADV_SCSIQ_SCSI_STATUS);
 1049                 cinfo_index =
 1050                     adv_read_lram_32(adv, halt_q_addr + ADV_SCSIQ_D_CINFO_IDX);
 1051                 ccb = adv->ccb_infos[cinfo_index].ccb;
 1052                 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
 1053                 ccb->ccb_h.status |= CAM_DEV_QFRZN|CAM_SCSI_STATUS_ERROR;
 1054                 ccb->csio.scsi_status = SCSI_STATUS_QUEUE_FULL; 
 1055                 adv_abort_ccb(adv, tid_no, ADV_TIX_TO_LUN(target_ix),
 1056                               /*ccb*/NULL, CAM_REQUEUE_REQ,
 1057                               /*queued_only*/TRUE);
 1058                 scsi_busy = adv_read_lram_8(adv, ADVV_SCSIBUSY_B);
 1059                 scsi_busy &= ~target_mask;
 1060                 adv_write_lram_8(adv, ADVV_SCSIBUSY_B, scsi_busy);              
 1061         } else {
 1062                 printf("Unhandled Halt Code %x\n", int_halt_code);
 1063         }
 1064         adv_write_lram_16(adv, ADVV_HALTCODE_W, 0);
 1065 }
 1066 
 1067 void
 1068 adv_sdtr_to_period_offset(struct adv_softc *adv,
 1069                           u_int8_t sync_data, u_int8_t *period,
 1070                           u_int8_t *offset, int tid)
 1071 {
 1072         if (adv->fix_asyn_xfer & ADV_TID_TO_TARGET_MASK(tid)
 1073          && (sync_data == ASYN_SDTR_DATA_FIX_PCI_REV_AB)) {
 1074                 *period = *offset = 0;
 1075         } else {
 1076                 *period = adv->sdtr_period_tbl[((sync_data >> 4) & 0xF)];
 1077                 *offset = sync_data & 0xF;
 1078         }
 1079 }
 1080 
 1081 void
 1082 adv_set_syncrate(struct adv_softc *adv, struct cam_path *path,
 1083                  u_int tid, u_int period, u_int offset, u_int type)
 1084 {
 1085         struct adv_target_transinfo* tinfo;
 1086         u_int old_period;
 1087         u_int old_offset;
 1088         u_int8_t sdtr_data;
 1089 
 1090         tinfo = &adv->tinfo[tid];
 1091 
 1092         /* Filter our input */
 1093         sdtr_data = adv_period_offset_to_sdtr(adv, &period,
 1094                                               &offset, tid);
 1095 
 1096         old_period = tinfo->current.period;
 1097         old_offset = tinfo->current.offset;
 1098 
 1099         if ((type & ADV_TRANS_CUR) != 0
 1100          && ((old_period != period || old_offset != offset)
 1101           || period == 0 || offset == 0) /*Changes in asyn fix settings*/) {
 1102                 int s;
 1103                 int halted;
 1104 
 1105                 s = splcam();
 1106                 halted = adv_is_chip_halted(adv);
 1107                 if (halted == 0)
 1108                         /* Must halt the chip first */
 1109                         adv_host_req_chip_halt(adv);
 1110 
 1111                 /* Update current hardware settings */
 1112                 adv_set_sdtr_reg_at_id(adv, tid, sdtr_data);
 1113 
 1114                 /*
 1115                  * If a target can run in sync mode, we don't need
 1116                  * to check it for sync problems.
 1117                  */
 1118                 if (offset != 0)
 1119                         adv->fix_asyn_xfer &= ~ADV_TID_TO_TARGET_MASK(tid);
 1120 
 1121                 if (halted == 0)
 1122                         /* Start the chip again */
 1123                         adv_start_chip(adv);
 1124 
 1125                 splx(s);
 1126                 tinfo->current.period = period;
 1127                 tinfo->current.offset = offset;
 1128 
 1129                 if (path != NULL) {
 1130                         /*
 1131                          * Tell the SCSI layer about the
 1132                          * new transfer parameters.
 1133                          */
 1134                         struct  ccb_trans_settings neg;
 1135 
 1136                         neg.sync_period = period;
 1137                         neg.sync_offset = offset;
 1138                         neg.valid = CCB_TRANS_SYNC_RATE_VALID
 1139                                   | CCB_TRANS_SYNC_OFFSET_VALID;
 1140                         xpt_setup_ccb(&neg.ccb_h, path, /*priority*/1);
 1141                         xpt_async(AC_TRANSFER_NEG, path, &neg);
 1142                 }
 1143         }
 1144 
 1145         if ((type & ADV_TRANS_GOAL) != 0) {
 1146                 tinfo->goal.period = period;
 1147                 tinfo->goal.offset = offset;
 1148         }
 1149 
 1150         if ((type & ADV_TRANS_USER) != 0) {
 1151                 tinfo->user.period = period;
 1152                 tinfo->user.offset = offset;
 1153         }
 1154 }
 1155 
 1156 u_int8_t
 1157 adv_period_offset_to_sdtr(struct adv_softc *adv, u_int *period,
 1158                           u_int *offset, int tid)
 1159 {
 1160         u_int i;
 1161         u_int dummy_offset;
 1162         u_int dummy_period;
 1163 
 1164         if (offset == NULL) {
 1165                 dummy_offset = 0;
 1166                 offset = &dummy_offset;
 1167         }
 1168 
 1169         if (period == NULL) {
 1170                 dummy_period = 0;
 1171                 period = &dummy_period;
 1172         }
 1173 
 1174 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 1175 
 1176         *offset = MIN(ADV_SYN_MAX_OFFSET, *offset);
 1177         if (*period != 0 && *offset != 0) {
 1178                 for (i = 0; i < adv->sdtr_period_tbl_size; i++) {
 1179                         if (*period <= adv->sdtr_period_tbl[i]) {
 1180                                 /*       
 1181                                  * When responding to a target that requests
 1182                                  * sync, the requested  rate may fall between
 1183                                  * two rates that we can output, but still be
 1184                                  * a rate that we can receive.  Because of this,
 1185                                  * we want to respond to the target with
 1186                                  * the same rate that it sent to us even
 1187                                  * if the period we use to send data to it
 1188                                  * is lower.  Only lower the response period
 1189                                  * if we must.
 1190                                  */        
 1191                                 if (i == 0 /* Our maximum rate */)
 1192                                         *period = adv->sdtr_period_tbl[0];
 1193                                 return ((i << 4) | *offset);
 1194                         }
 1195                 }
 1196         }
 1197         
 1198         /* Must go async */
 1199         *period = 0;
 1200         *offset = 0;
 1201         if (adv->fix_asyn_xfer & ADV_TID_TO_TARGET_MASK(tid))
 1202                 return (ASYN_SDTR_DATA_FIX_PCI_REV_AB);
 1203         return (0);
 1204 }
 1205 
 1206 /* Internal Routines */
 1207 
 1208 static void
 1209 adv_read_lram_16_multi(struct adv_softc *adv, u_int16_t s_addr,
 1210                        u_int16_t *buffer, int count)
 1211 {
 1212         ADV_OUTW(adv, ADV_LRAM_ADDR, s_addr);
 1213         ADV_INSW(adv, ADV_LRAM_DATA, buffer, count);
 1214 }
 1215 
 1216 static void
 1217 adv_write_lram_16_multi(struct adv_softc *adv, u_int16_t s_addr,
 1218                         u_int16_t *buffer, int count)
 1219 {
 1220         ADV_OUTW(adv, ADV_LRAM_ADDR, s_addr);
 1221         ADV_OUTSW(adv, ADV_LRAM_DATA, buffer, count);
 1222 }
 1223 
 1224 static void
 1225 adv_mset_lram_16(struct adv_softc *adv, u_int16_t s_addr,
 1226                  u_int16_t set_value, int count)
 1227 {
 1228         ADV_OUTW(adv, ADV_LRAM_ADDR, s_addr);
 1229         bus_space_set_multi_2(adv->tag, adv->bsh, ADV_LRAM_DATA,
 1230                               set_value, count);
 1231 }
 1232 
 1233 static u_int32_t
 1234 adv_msum_lram_16(struct adv_softc *adv, u_int16_t s_addr, int count)
 1235 {
 1236         u_int32_t       sum;
 1237         int             i;
 1238 
 1239         sum = 0;
 1240         ADV_OUTW(adv, ADV_LRAM_ADDR, s_addr);
 1241         for (i = 0; i < count; i++)
 1242                 sum += ADV_INW(adv, ADV_LRAM_DATA);
 1243         return (sum);
 1244 }
 1245 
 1246 static int
 1247 adv_write_and_verify_lram_16(struct adv_softc *adv, u_int16_t addr,
 1248                              u_int16_t value)
 1249 {
 1250         int     retval;
 1251 
 1252         retval = 0;
 1253         ADV_OUTW(adv, ADV_LRAM_ADDR, addr);
 1254         ADV_OUTW(adv, ADV_LRAM_DATA, value);
 1255         DELAY(10000);
 1256         ADV_OUTW(adv, ADV_LRAM_ADDR, addr);
 1257         if (value != ADV_INW(adv, ADV_LRAM_DATA))
 1258                 retval = 1;
 1259         return (retval);
 1260 }
 1261 
 1262 static u_int32_t
 1263 adv_read_lram_32(struct adv_softc *adv, u_int16_t addr)
 1264 {
 1265         u_int16_t           val_low, val_high;
 1266 
 1267         ADV_OUTW(adv, ADV_LRAM_ADDR, addr);
 1268 
 1269 #if BYTE_ORDER == BIG_ENDIAN
 1270         val_high = ADV_INW(adv, ADV_LRAM_DATA);
 1271         val_low = ADV_INW(adv, ADV_LRAM_DATA);
 1272 #else
 1273         val_low = ADV_INW(adv, ADV_LRAM_DATA);
 1274         val_high = ADV_INW(adv, ADV_LRAM_DATA);
 1275 #endif
 1276 
 1277         return (((u_int32_t)val_high << 16) | (u_int32_t)val_low);
 1278 }
 1279 
 1280 static void
 1281 adv_write_lram_32(struct adv_softc *adv, u_int16_t addr, u_int32_t value)
 1282 {
 1283         ADV_OUTW(adv, ADV_LRAM_ADDR, addr);
 1284 
 1285 #if BYTE_ORDER == BIG_ENDIAN
 1286         ADV_OUTW(adv, ADV_LRAM_DATA, (u_int16_t)((value >> 16) & 0xFFFF));
 1287         ADV_OUTW(adv, ADV_LRAM_DATA, (u_int16_t)(value & 0xFFFF));
 1288 #else
 1289         ADV_OUTW(adv, ADV_LRAM_DATA, (u_int16_t)(value & 0xFFFF));
 1290         ADV_OUTW(adv, ADV_LRAM_DATA, (u_int16_t)((value >> 16) & 0xFFFF));
 1291 #endif
 1292 }
 1293 
 1294 static void
 1295 adv_write_lram_32_multi(struct adv_softc *adv, u_int16_t s_addr,
 1296                         u_int32_t *buffer, int count)
 1297 {
 1298         ADV_OUTW(adv, ADV_LRAM_ADDR, s_addr);
 1299         ADV_OUTSW(adv, ADV_LRAM_DATA, (u_int16_t *)buffer, count * 2);
 1300 }
 1301 
 1302 static u_int16_t
 1303 adv_read_eeprom_16(struct adv_softc *adv, u_int8_t addr)
 1304 {
 1305         u_int16_t read_wval;
 1306         u_int8_t  cmd_reg;
 1307 
 1308         adv_write_eeprom_cmd_reg(adv, ADV_EEPROM_CMD_WRITE_DISABLE);
 1309         DELAY(1000);
 1310         cmd_reg = addr | ADV_EEPROM_CMD_READ;
 1311         adv_write_eeprom_cmd_reg(adv, cmd_reg);
 1312         DELAY(1000);
 1313         read_wval = ADV_INW(adv, ADV_EEPROM_DATA);
 1314         DELAY(1000);
 1315         return (read_wval);
 1316 }
 1317 
 1318 static u_int16_t
 1319 adv_write_eeprom_16(struct adv_softc *adv, u_int8_t addr, u_int16_t value)
 1320 {
 1321         u_int16_t       read_value;
 1322 
 1323         read_value = adv_read_eeprom_16(adv, addr);
 1324         if (read_value != value) {
 1325                 adv_write_eeprom_cmd_reg(adv, ADV_EEPROM_CMD_WRITE_ENABLE);
 1326                 DELAY(1000);
 1327                 
 1328                 ADV_OUTW(adv, ADV_EEPROM_DATA, value);
 1329                 DELAY(1000);
 1330 
 1331                 adv_write_eeprom_cmd_reg(adv, ADV_EEPROM_CMD_WRITE | addr);
 1332                 DELAY(20 * 1000);
 1333 
 1334                 adv_write_eeprom_cmd_reg(adv, ADV_EEPROM_CMD_WRITE_DISABLE);
 1335                 DELAY(1000);
 1336                 read_value = adv_read_eeprom_16(adv, addr);
 1337         }
 1338         return (read_value);
 1339 }
 1340 
 1341 static int
 1342 adv_write_eeprom_cmd_reg(struct adv_softc *adv, u_int8_t cmd_reg)
 1343 {
 1344         u_int8_t read_back;
 1345         int      retry;
 1346 
 1347         retry = 0;
 1348         while (1) {
 1349                 ADV_OUTB(adv, ADV_EEPROM_CMD, cmd_reg);
 1350                 DELAY(1000);
 1351                 read_back = ADV_INB(adv, ADV_EEPROM_CMD);
 1352                 if (read_back == cmd_reg) {
 1353                         return (1);
 1354                 }
 1355                 if (retry++ > ADV_EEPROM_MAX_RETRY) {
 1356                         return (0);
 1357                 }
 1358         }
 1359 }
 1360 
 1361 static int
 1362 adv_set_eeprom_config_once(struct adv_softc *adv,
 1363                            struct adv_eeprom_config *eeprom_config)
 1364 {
 1365         int             n_error;
 1366         u_int16_t       *wbuf;
 1367         u_int16_t       sum;
 1368         u_int8_t        s_addr;
 1369         u_int8_t        cfg_beg;
 1370         u_int8_t        cfg_end;
 1371 
 1372         wbuf = (u_int16_t *)eeprom_config;
 1373         n_error = 0;
 1374         sum = 0;
 1375         for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
 1376                 sum += *wbuf;
 1377                 if (*wbuf != adv_write_eeprom_16(adv, s_addr, *wbuf)) {
 1378                         n_error++;
 1379                 }
 1380         }
 1381         if (adv->type & ADV_VL) {
 1382                 cfg_beg = ADV_EEPROM_CFG_BEG_VL;
 1383                 cfg_end = ADV_EEPROM_MAX_ADDR_VL;
 1384         } else {
 1385                 cfg_beg = ADV_EEPROM_CFG_BEG;
 1386                 cfg_end = ADV_EEPROM_MAX_ADDR;
 1387         }
 1388 
 1389         for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
 1390                 sum += *wbuf;
 1391                 if (*wbuf != adv_write_eeprom_16(adv, s_addr, *wbuf)) {
 1392                         n_error++;
 1393                 }
 1394         }
 1395         *wbuf = sum;
 1396         if (sum != adv_write_eeprom_16(adv, s_addr, sum)) {
 1397                 n_error++;
 1398         }
 1399         wbuf = (u_int16_t *)eeprom_config;
 1400         for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
 1401                 if (*wbuf != adv_read_eeprom_16(adv, s_addr)) {
 1402                         n_error++;
 1403                 }
 1404         }
 1405         for (s_addr = cfg_beg; s_addr <= cfg_end; s_addr++, wbuf++) {
 1406                 if (*wbuf != adv_read_eeprom_16(adv, s_addr)) {
 1407                         n_error++;
 1408                 }
 1409         }
 1410         return (n_error);
 1411 }
 1412 
 1413 static u_int32_t
 1414 adv_load_microcode(struct adv_softc *adv, u_int16_t s_addr,
 1415                    u_int16_t *mcode_buf, u_int16_t mcode_size)
 1416 {
 1417         u_int32_t chksum;
 1418         u_int16_t mcode_lram_size;
 1419         u_int16_t mcode_chksum;
 1420 
 1421         mcode_lram_size = mcode_size >> 1;
 1422         /* XXX Why zero the memory just before you write the whole thing?? */
 1423         adv_mset_lram_16(adv, s_addr, 0, mcode_lram_size);
 1424         adv_write_lram_16_multi(adv, s_addr, mcode_buf, mcode_lram_size);
 1425 
 1426         chksum = adv_msum_lram_16(adv, s_addr, mcode_lram_size);
 1427         mcode_chksum = (u_int16_t)adv_msum_lram_16(adv, ADV_CODE_SEC_BEG,
 1428                                                    ((mcode_size - s_addr
 1429                                                      - ADV_CODE_SEC_BEG) >> 1));
 1430         adv_write_lram_16(adv, ADVV_MCODE_CHKSUM_W, mcode_chksum);
 1431         adv_write_lram_16(adv, ADVV_MCODE_SIZE_W, mcode_size);
 1432         return (chksum);
 1433 }
 1434 
 1435 static void
 1436 adv_reinit_lram(struct adv_softc *adv) {
 1437         adv_init_lram(adv);
 1438         adv_init_qlink_var(adv);
 1439 }
 1440 
 1441 static void
 1442 adv_init_lram(struct adv_softc *adv)
 1443 {
 1444         u_int8_t  i;
 1445         u_int16_t s_addr;
 1446 
 1447         adv_mset_lram_16(adv, ADV_QADR_BEG, 0,
 1448                          (((adv->max_openings + 2 + 1) * 64) >> 1));
 1449         
 1450         i = ADV_MIN_ACTIVE_QNO;
 1451         s_addr = ADV_QADR_BEG + ADV_QBLK_SIZE;
 1452 
 1453         adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_FWD, i + 1);
 1454         adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_BWD, adv->max_openings);
 1455         adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_QNO, i);
 1456         i++;
 1457         s_addr += ADV_QBLK_SIZE;
 1458         for (; i < adv->max_openings; i++, s_addr += ADV_QBLK_SIZE) {
 1459                 adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_FWD, i + 1);
 1460                 adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_BWD, i - 1);
 1461                 adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_QNO, i);
 1462         }
 1463 
 1464         adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_FWD, ADV_QLINK_END);
 1465         adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_BWD, adv->max_openings - 1);
 1466         adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_QNO, adv->max_openings);
 1467         i++;
 1468         s_addr += ADV_QBLK_SIZE;
 1469 
 1470         for (; i <= adv->max_openings + 3; i++, s_addr += ADV_QBLK_SIZE) {
 1471                 adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_FWD, i);
 1472                 adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_BWD, i);
 1473                 adv_write_lram_8(adv, s_addr + ADV_SCSIQ_B_QNO, i);
 1474         }
 1475 }
 1476 
 1477 static int
 1478 adv_init_microcode_var(struct adv_softc *adv)
 1479 {
 1480         int      i;
 1481 
 1482         for (i = 0; i <= ADV_MAX_TID; i++) {
 1483                 
 1484                 /* Start out async all around */
 1485                 adv_set_syncrate(adv, /*path*/NULL,
 1486                                  i, 0, 0,
 1487                                  ADV_TRANS_GOAL|ADV_TRANS_CUR);
 1488         }
 1489 
 1490         adv_init_qlink_var(adv);
 1491 
 1492         adv_write_lram_8(adv, ADVV_DISC_ENABLE_B, adv->disc_enable);
 1493         adv_write_lram_8(adv, ADVV_HOSTSCSI_ID_B, 0x01 << adv->scsi_id);
 1494 
 1495         adv_write_lram_32(adv, ADVV_OVERRUN_PADDR_D, adv->overrun_physbase);
 1496 
 1497         adv_write_lram_32(adv, ADVV_OVERRUN_BSIZE_D, ADV_OVERRUN_BSIZE);
 1498 
 1499         ADV_OUTW(adv, ADV_REG_PROG_COUNTER, ADV_MCODE_START_ADDR);
 1500         if (ADV_INW(adv, ADV_REG_PROG_COUNTER) != ADV_MCODE_START_ADDR) {
 1501                 printf("adv%d: Unable to set program counter. Aborting.\n",
 1502                        adv->unit);
 1503                 return (1);
 1504         }
 1505         return (0);
 1506 }
 1507 
 1508 static void
 1509 adv_init_qlink_var(struct adv_softc *adv)
 1510 {
 1511         int       i;
 1512         u_int16_t lram_addr;
 1513 
 1514         adv_write_lram_8(adv, ADVV_NEXTRDY_B, 1);
 1515         adv_write_lram_8(adv, ADVV_DONENEXT_B, adv->max_openings);
 1516 
 1517         adv_write_lram_16(adv, ADVV_FREE_Q_HEAD_W, 1);
 1518         adv_write_lram_16(adv, ADVV_DONE_Q_TAIL_W, adv->max_openings);
 1519 
 1520         adv_write_lram_8(adv, ADVV_BUSY_QHEAD_B,
 1521                          (u_int8_t)((int) adv->max_openings + 1));
 1522         adv_write_lram_8(adv, ADVV_DISC1_QHEAD_B,
 1523                          (u_int8_t)((int) adv->max_openings + 2));
 1524 
 1525         adv_write_lram_8(adv, ADVV_TOTAL_READY_Q_B, adv->max_openings);
 1526 
 1527         adv_write_lram_16(adv, ADVV_ASCDVC_ERR_CODE_W, 0);
 1528         adv_write_lram_16(adv, ADVV_HALTCODE_W, 0);
 1529         adv_write_lram_8(adv, ADVV_STOP_CODE_B, 0);
 1530         adv_write_lram_8(adv, ADVV_SCSIBUSY_B, 0);
 1531         adv_write_lram_8(adv, ADVV_WTM_FLAG_B, 0);
 1532         adv_write_lram_8(adv, ADVV_Q_DONE_IN_PROGRESS_B, 0);
 1533 
 1534         lram_addr = ADV_QADR_BEG;
 1535         for (i = 0; i < 32; i++, lram_addr += 2)
 1536                 adv_write_lram_16(adv, lram_addr, 0);
 1537 }
 1538 
 1539 static void
 1540 adv_disable_interrupt(struct adv_softc *adv)
 1541 {
 1542         u_int16_t cfg;
 1543 
 1544         cfg = ADV_INW(adv, ADV_CONFIG_LSW);
 1545         ADV_OUTW(adv, ADV_CONFIG_LSW, cfg & ~ADV_CFG_LSW_HOST_INT_ON);
 1546 }
 1547 
 1548 static void
 1549 adv_enable_interrupt(struct adv_softc *adv)
 1550 {
 1551         u_int16_t cfg;
 1552 
 1553         cfg = ADV_INW(adv, ADV_CONFIG_LSW);
 1554         ADV_OUTW(adv, ADV_CONFIG_LSW, cfg | ADV_CFG_LSW_HOST_INT_ON);
 1555 }
 1556 
 1557 static void
 1558 adv_toggle_irq_act(struct adv_softc *adv)
 1559 {
 1560         ADV_OUTW(adv, ADV_CHIP_STATUS, ADV_CIW_IRQ_ACT);
 1561         ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
 1562 }
 1563 
 1564 void
 1565 adv_start_execution(struct adv_softc *adv)
 1566 {
 1567         if (adv_read_lram_8(adv, ADV_STOP_CODE_B) != 0) {
 1568                 adv_write_lram_8(adv, ADV_STOP_CODE_B, 0);
 1569         }
 1570 }
 1571 
 1572 int
 1573 adv_stop_chip(struct adv_softc *adv)
 1574 {
 1575         u_int8_t cc_val;
 1576 
 1577         cc_val = ADV_INB(adv, ADV_CHIP_CTRL)
 1578                  & (~(ADV_CC_SINGLE_STEP | ADV_CC_TEST | ADV_CC_DIAG));
 1579         ADV_OUTB(adv, ADV_CHIP_CTRL, cc_val | ADV_CC_HALT);
 1580         adv_set_chip_ih(adv, ADV_INS_HALT);
 1581         adv_set_chip_ih(adv, ADV_INS_RFLAG_WTM);
 1582         if ((ADV_INW(adv, ADV_CHIP_STATUS) & ADV_CSW_HALTED) == 0) {
 1583                 return (0);
 1584         }
 1585         return (1);
 1586 }
 1587 
 1588 static int
 1589 adv_host_req_chip_halt(struct adv_softc *adv)
 1590 {       
 1591         int      count;
 1592         u_int8_t saved_stop_code;
 1593 
 1594         if (adv_is_chip_halted(adv))
 1595                 return (1);
 1596 
 1597         count = 0;
 1598         saved_stop_code = adv_read_lram_8(adv, ADVV_STOP_CODE_B);
 1599         adv_write_lram_8(adv, ADVV_STOP_CODE_B,
 1600                          ADV_STOP_HOST_REQ_RISC_HALT | ADV_STOP_REQ_RISC_STOP);
 1601         while (adv_is_chip_halted(adv) == 0
 1602             && count++ < 2000)
 1603                 ;
 1604 
 1605         adv_write_lram_8(adv, ADVV_STOP_CODE_B, saved_stop_code);
 1606         return (count < 2000); 
 1607 }
 1608 
 1609 static void
 1610 adv_set_chip_ih(struct adv_softc *adv, u_int16_t ins_code)
 1611 {
 1612         adv_set_bank(adv, 1);
 1613         ADV_OUTW(adv, ADV_REG_IH, ins_code);
 1614         adv_set_bank(adv, 0);
 1615 }
 1616 
 1617 #if UNUSED
 1618 static u_int8_t
 1619 adv_get_chip_scsi_ctrl(struct adv_softc *adv)
 1620 {
 1621         u_int8_t scsi_ctrl;
 1622 
 1623         adv_set_bank(adv, 1);
 1624         scsi_ctrl = ADV_INB(adv, ADV_REG_SC);
 1625         adv_set_bank(adv, 0);
 1626         return (scsi_ctrl);
 1627 }
 1628 #endif
 1629 
 1630 /*
 1631  * XXX Looks like more padding issues in this routine as well.
 1632  *     There has to be a way to turn this into an insw.
 1633  */
 1634 static void
 1635 adv_get_q_info(struct adv_softc *adv, u_int16_t s_addr,
 1636                u_int16_t *inbuf, int words)
 1637 {
 1638         int     i;
 1639 
 1640         ADV_OUTW(adv, ADV_LRAM_ADDR, s_addr);
 1641         for (i = 0; i < words; i++, inbuf++) {
 1642                 if (i == 5) {
 1643                         continue;
 1644                 }
 1645                 *inbuf = ADV_INW(adv, ADV_LRAM_DATA);
 1646         }
 1647 }
 1648 
 1649 static u_int
 1650 adv_get_num_free_queues(struct adv_softc *adv, u_int8_t n_qs)
 1651 {
 1652         u_int     cur_used_qs;
 1653         u_int     cur_free_qs;
 1654 
 1655         cur_used_qs = adv->cur_active + ADV_MIN_FREE_Q;
 1656 
 1657         if ((cur_used_qs + n_qs) <= adv->max_openings) {
 1658                 cur_free_qs = adv->max_openings - cur_used_qs;
 1659                 return (cur_free_qs);
 1660         }
 1661         adv->openings_needed = n_qs;
 1662         return (0);
 1663 }
 1664 
 1665 static u_int8_t
 1666 adv_alloc_free_queues(struct adv_softc *adv, u_int8_t free_q_head,
 1667                       u_int8_t n_free_q)
 1668 {
 1669         int i;
 1670 
 1671         for (i = 0; i < n_free_q; i++) {
 1672                 free_q_head = adv_alloc_free_queue(adv, free_q_head);
 1673                 if (free_q_head == ADV_QLINK_END)
 1674                         break;
 1675         }
 1676         return (free_q_head);
 1677 }
 1678 
 1679 static u_int8_t
 1680 adv_alloc_free_queue(struct adv_softc *adv, u_int8_t free_q_head)
 1681 {
 1682         u_int16_t       q_addr;
 1683         u_int8_t        next_qp;
 1684         u_int8_t        q_status;
 1685 
 1686         next_qp = ADV_QLINK_END;
 1687         q_addr = ADV_QNO_TO_QADDR(free_q_head);
 1688         q_status = adv_read_lram_8(adv, q_addr + ADV_SCSIQ_B_STATUS);
 1689         
 1690         if ((q_status & QS_READY) == 0)
 1691                 next_qp = adv_read_lram_8(adv, q_addr + ADV_SCSIQ_B_FWD);
 1692 
 1693         return (next_qp);
 1694 }
 1695 
 1696 static int
 1697 adv_send_scsi_queue(struct adv_softc *adv, struct adv_scsi_q *scsiq,
 1698                     u_int8_t n_q_required)
 1699 {
 1700         u_int8_t        free_q_head;
 1701         u_int8_t        next_qp;
 1702         u_int8_t        tid_no;
 1703         u_int8_t        target_ix;
 1704         int             retval;
 1705 
 1706         retval = 1;
 1707         target_ix = scsiq->q2.target_ix;
 1708         tid_no = ADV_TIX_TO_TID(target_ix);
 1709         free_q_head = adv_read_lram_16(adv, ADVV_FREE_Q_HEAD_W) & 0xFF;
 1710         if ((next_qp = adv_alloc_free_queues(adv, free_q_head, n_q_required))
 1711             != ADV_QLINK_END) {
 1712                 scsiq->q1.q_no = free_q_head;
 1713 
 1714                 /*
 1715                  * Now that we know our Q number, point our sense
 1716                  * buffer pointer to a bus dma mapped area where
 1717                  * we can dma the data to.
 1718                  */
 1719                 scsiq->q1.sense_addr = adv->sense_physbase
 1720                     + ((free_q_head - 1) * sizeof(struct scsi_sense_data));
 1721                 adv_put_ready_sg_list_queue(adv, scsiq, free_q_head);
 1722                 adv_write_lram_16(adv, ADVV_FREE_Q_HEAD_W, next_qp);
 1723                 adv->cur_active += n_q_required;
 1724                 retval = 0;
 1725         }
 1726         return (retval);
 1727 }
 1728 
 1729 
 1730 static void
 1731 adv_put_ready_sg_list_queue(struct adv_softc *adv, struct adv_scsi_q *scsiq,
 1732                             u_int q_no)
 1733 {
 1734         u_int8_t        sg_list_dwords;
 1735         u_int8_t        sg_index, i;
 1736         u_int8_t        sg_entry_cnt;
 1737         u_int8_t        next_qp;
 1738         u_int16_t       q_addr;
 1739         struct          adv_sg_head *sg_head;
 1740         struct          adv_sg_list_q scsi_sg_q;
 1741 
 1742         sg_head = scsiq->sg_head;
 1743 
 1744         if (sg_head) {
 1745                 sg_entry_cnt = sg_head->entry_cnt - 1;
 1746 #ifdef DIAGNOSTIC
 1747                 if (sg_entry_cnt == 0)
 1748                         panic("adv_put_ready_sg_list_queue: ScsiQ with "
 1749                               "a SG list but only one element");
 1750                 if ((scsiq->q1.cntl & QC_SG_HEAD) == 0)
 1751                         panic("adv_put_ready_sg_list_queue: ScsiQ with "
 1752                               "a SG list but QC_SG_HEAD not set");
 1753 #endif                  
 1754                 q_addr = ADV_QNO_TO_QADDR(q_no);
 1755                 sg_index = 1;
 1756                 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
 1757                 scsi_sg_q.sg_head_qp = q_no;
 1758                 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
 1759                 for (i = 0; i < sg_head->queue_cnt; i++) {
 1760                         u_int8_t segs_this_q;
 1761 
 1762                         if (sg_entry_cnt > ADV_SG_LIST_PER_Q)
 1763                                 segs_this_q = ADV_SG_LIST_PER_Q;
 1764                         else {
 1765                                 /* This will be the last segment then */
 1766                                 segs_this_q = sg_entry_cnt;
 1767                                 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
 1768                         }
 1769                         scsi_sg_q.seq_no = i + 1;
 1770                         sg_list_dwords = segs_this_q << 1;
 1771                         if (i == 0) {
 1772                                 scsi_sg_q.sg_list_cnt = segs_this_q;
 1773                                 scsi_sg_q.sg_cur_list_cnt = segs_this_q;
 1774                         } else {
 1775                                 scsi_sg_q.sg_list_cnt = segs_this_q - 1;
 1776                                 scsi_sg_q.sg_cur_list_cnt = segs_this_q - 1;
 1777                         }
 1778                         next_qp = adv_read_lram_8(adv, q_addr + ADV_SCSIQ_B_FWD);
 1779                         scsi_sg_q.q_no = next_qp;
 1780                         q_addr = ADV_QNO_TO_QADDR(next_qp);
 1781 
 1782                         adv_write_lram_16_multi(adv,
 1783                                                 q_addr + ADV_SCSIQ_SGHD_CPY_BEG,
 1784                                                 (u_int16_t *)&scsi_sg_q,
 1785                                                 sizeof(scsi_sg_q) >> 1);
 1786                         adv_write_lram_32_multi(adv, q_addr + ADV_SGQ_LIST_BEG,
 1787                                                 (u_int32_t *)&sg_head->sg_list[sg_index],
 1788                                                 sg_list_dwords);
 1789                         sg_entry_cnt -= segs_this_q;
 1790                         sg_index += ADV_SG_LIST_PER_Q;
 1791                 }
 1792         }
 1793         adv_put_ready_queue(adv, scsiq, q_no);
 1794 }
 1795 
 1796 static void
 1797 adv_put_ready_queue(struct adv_softc *adv, struct adv_scsi_q *scsiq,
 1798                     u_int q_no)
 1799 {
 1800         struct          adv_target_transinfo* tinfo;
 1801         u_int           q_addr;
 1802         u_int           tid_no;
 1803 
 1804         tid_no = ADV_TIX_TO_TID(scsiq->q2.target_ix);
 1805         tinfo = &adv->tinfo[tid_no];
 1806         if ((tinfo->current.period != tinfo->goal.period)
 1807          || (tinfo->current.offset != tinfo->goal.offset)) {
 1808 
 1809                 adv_msgout_sdtr(adv, tinfo->goal.period, tinfo->goal.offset);
 1810                 scsiq->q1.cntl |= QC_MSG_OUT;
 1811         }
 1812         q_addr = ADV_QNO_TO_QADDR(q_no);
 1813 
 1814         scsiq->q1.status = QS_FREE;
 1815 
 1816         adv_write_lram_16_multi(adv, q_addr + ADV_SCSIQ_CDB_BEG,
 1817                                 (u_int16_t *)scsiq->cdbptr,
 1818                                 scsiq->q2.cdb_len >> 1);
 1819 
 1820 #if BYTE_ORDER == BIG_ENDIAN
 1821         adv_adj_scsiq_endian(scsiq);
 1822 #endif
 1823 
 1824         adv_put_scsiq(adv, q_addr + ADV_SCSIQ_CPY_BEG,
 1825                       (u_int16_t *) &scsiq->q1.cntl,
 1826                       ((sizeof(scsiq->q1) + sizeof(scsiq->q2)) / 2) - 1);
 1827 
 1828 #if CC_WRITE_IO_COUNT
 1829         adv_write_lram_16(adv, q_addr + ADV_SCSIQ_W_REQ_COUNT,
 1830                           adv->req_count);
 1831 #endif
 1832 
 1833 #if CC_CLEAR_DMA_REMAIN
 1834 
 1835         adv_write_lram_32(adv, q_addr + ADV_SCSIQ_DW_REMAIN_XFER_ADDR, 0);
 1836         adv_write_lram_32(adv, q_addr + ADV_SCSIQ_DW_REMAIN_XFER_CNT, 0);
 1837 #endif
 1838 
 1839         adv_write_lram_16(adv, q_addr + ADV_SCSIQ_B_STATUS,
 1840                           (scsiq->q1.q_no << 8) | QS_READY);
 1841 }
 1842 
 1843 static void
 1844 adv_put_scsiq(struct adv_softc *adv, u_int16_t s_addr,
 1845               u_int16_t *buffer, int words)
 1846 {
 1847         int     i;
 1848 
 1849         /*
 1850          * XXX This routine makes *gross* assumptions
 1851          * about padding in the data structures.
 1852          * Either the data structures should have explicit
 1853          * padding members added, or they should have padding
 1854          * turned off via compiler attributes depending on
 1855          * which yields better overall performance.  My hunch
 1856          * would be that turning off padding would be the
 1857          * faster approach as an outsw is much faster than
 1858          * this crude loop and accessing un-aligned data
 1859          * members isn't *that* expensive.  The other choice
 1860          * would be to modify the ASC script so that the
 1861          * the adv_scsiq_1 structure can be re-arranged so
 1862          * padding isn't required.
 1863          */
 1864         ADV_OUTW(adv, ADV_LRAM_ADDR, s_addr);
 1865         for (i = 0; i < words; i++, buffer++) {
 1866                 if (i == 2 || i == 10) {
 1867                         continue;
 1868                 }
 1869                 ADV_OUTW(adv, ADV_LRAM_DATA, *buffer);
 1870         }
 1871 }
 1872 
 1873 static void
 1874 adv_handle_extmsg_in(struct adv_softc *adv, u_int16_t halt_q_addr,
 1875                      u_int8_t q_cntl, target_bit_vector target_mask,
 1876                      int tid_no)
 1877 {
 1878         struct  ext_msg ext_msg;
 1879 
 1880         adv_read_lram_16_multi(adv, ADVV_MSGIN_BEG, (u_int16_t *) &ext_msg,
 1881                                sizeof(ext_msg) >> 1);
 1882         if ((ext_msg.msg_type == MSG_EXTENDED)
 1883          && (ext_msg.msg_req == MSG_EXT_SDTR)
 1884          && (ext_msg.msg_len == MSG_EXT_SDTR_LEN)) {
 1885                 union     ccb *ccb;
 1886                 struct    adv_target_transinfo* tinfo;
 1887                 u_int32_t cinfo_index;
 1888                 u_int    period;
 1889                 u_int    offset;
 1890                 int      sdtr_accept;
 1891                 u_int8_t orig_offset;
 1892 
 1893                 cinfo_index =
 1894                     adv_read_lram_32(adv, halt_q_addr + ADV_SCSIQ_D_CINFO_IDX);
 1895                 ccb = adv->ccb_infos[cinfo_index].ccb;
 1896                 tinfo = &adv->tinfo[tid_no];
 1897                 sdtr_accept = TRUE;
 1898 
 1899                 orig_offset = ext_msg.req_ack_offset;
 1900                 if (ext_msg.xfer_period < tinfo->goal.period) {
 1901                         sdtr_accept = FALSE;
 1902                         ext_msg.xfer_period = tinfo->goal.period;
 1903                 }
 1904 
 1905                 /* Perform range checking */
 1906                 period = ext_msg.xfer_period;
 1907                 offset = ext_msg.req_ack_offset;
 1908                 adv_period_offset_to_sdtr(adv, &period,  &offset, tid_no);
 1909                 ext_msg.xfer_period = period;
 1910                 ext_msg.req_ack_offset = offset;
 1911                 
 1912                 /* Record our current sync settings */
 1913                 adv_set_syncrate(adv, ccb->ccb_h.path,
 1914                                  tid_no, ext_msg.xfer_period,
 1915                                  ext_msg.req_ack_offset,
 1916                                  ADV_TRANS_GOAL|ADV_TRANS_ACTIVE);
 1917 
 1918                 /* Offset too high or large period forced async */
 1919                 if (orig_offset != ext_msg.req_ack_offset)
 1920                         sdtr_accept = FALSE;
 1921 
 1922                 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
 1923                         /* Valid response to our requested negotiation */
 1924                         q_cntl &= ~QC_MSG_OUT;
 1925                 } else {
 1926                         /* Must Respond */
 1927                         q_cntl |= QC_MSG_OUT;
 1928                         adv_msgout_sdtr(adv, ext_msg.xfer_period,
 1929                                         ext_msg.req_ack_offset);
 1930                 }
 1931 
 1932         } else if (ext_msg.msg_type == MSG_EXTENDED
 1933                 && ext_msg.msg_req == MSG_EXT_WDTR
 1934                 && ext_msg.msg_len == MSG_EXT_WDTR_LEN) {
 1935 
 1936                 ext_msg.wdtr_width = 0;
 1937                 adv_write_lram_16_multi(adv, ADVV_MSGOUT_BEG,
 1938                                         (u_int16_t *)&ext_msg,
 1939                                         sizeof(ext_msg) >> 1);
 1940                 q_cntl |= QC_MSG_OUT;
 1941         } else {
 1942 
 1943                 ext_msg.msg_type = MSG_MESSAGE_REJECT;
 1944                 adv_write_lram_16_multi(adv, ADVV_MSGOUT_BEG,
 1945                                         (u_int16_t *)&ext_msg,
 1946                                         sizeof(ext_msg) >> 1);
 1947                 q_cntl |= QC_MSG_OUT;
 1948         }
 1949         adv_write_lram_8(adv, halt_q_addr + ADV_SCSIQ_B_CNTL, q_cntl);
 1950 }
 1951 
 1952 static void
 1953 adv_msgout_sdtr(struct adv_softc *adv, u_int8_t sdtr_period,
 1954                 u_int8_t sdtr_offset)
 1955 {
 1956         struct   ext_msg sdtr_buf;
 1957 
 1958         sdtr_buf.msg_type = MSG_EXTENDED;
 1959         sdtr_buf.msg_len = MSG_EXT_SDTR_LEN;
 1960         sdtr_buf.msg_req = MSG_EXT_SDTR;
 1961         sdtr_buf.xfer_period = sdtr_period;
 1962         sdtr_offset &= ADV_SYN_MAX_OFFSET;
 1963         sdtr_buf.req_ack_offset = sdtr_offset;
 1964         adv_write_lram_16_multi(adv, ADVV_MSGOUT_BEG,
 1965                                 (u_int16_t *) &sdtr_buf,
 1966                                 sizeof(sdtr_buf) / 2);
 1967 }
 1968 
 1969 int
 1970 adv_abort_ccb(struct adv_softc *adv, int target, int lun, union ccb *ccb,
 1971               u_int32_t status, int queued_only)
 1972 {
 1973         u_int16_t q_addr;
 1974         u_int8_t  q_no;
 1975         struct adv_q_done_info scsiq_buf;
 1976         struct adv_q_done_info *scsiq;
 1977         u_int8_t  target_ix;
 1978         int       count;
 1979 
 1980         scsiq = &scsiq_buf;
 1981         target_ix = ADV_TIDLUN_TO_IX(target, lun);
 1982         count = 0;
 1983         for (q_no = ADV_MIN_ACTIVE_QNO; q_no <= adv->max_openings; q_no++) {
 1984                 struct adv_ccb_info *ccb_info;
 1985                 q_addr = ADV_QNO_TO_QADDR(q_no);
 1986 
 1987                 adv_copy_lram_doneq(adv, q_addr, scsiq, adv->max_dma_count);
 1988                 ccb_info = &adv->ccb_infos[scsiq->d2.ccb_index];
 1989                 if (((scsiq->q_status & QS_READY) != 0)
 1990                  && ((scsiq->q_status & QS_ABORTED) == 0)
 1991                  && ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)
 1992                  && (scsiq->d2.target_ix == target_ix)
 1993                  && (queued_only == 0
 1994                   || !(scsiq->q_status & (QS_DISC1|QS_DISC2|QS_BUSY|QS_DONE)))
 1995                  && (ccb == NULL || (ccb == ccb_info->ccb))) {
 1996                         union ccb *aborted_ccb;
 1997                         struct adv_ccb_info *cinfo;
 1998 
 1999                         scsiq->q_status |= QS_ABORTED;
 2000                         adv_write_lram_8(adv, q_addr + ADV_SCSIQ_B_STATUS,
 2001                                          scsiq->q_status);
 2002                         aborted_ccb = ccb_info->ccb;
 2003                         /* Don't clobber earlier error codes */
 2004                         if ((aborted_ccb->ccb_h.status & CAM_STATUS_MASK)
 2005                           == CAM_REQ_INPROG)
 2006                                 aborted_ccb->ccb_h.status |= status;
 2007                         cinfo = (struct adv_ccb_info *)
 2008                             aborted_ccb->ccb_h.ccb_cinfo_ptr;
 2009                         cinfo->state |= ACCB_ABORT_QUEUED;
 2010                         count++;
 2011                 }
 2012         }
 2013         return (count);
 2014 }
 2015 
 2016 int
 2017 adv_reset_bus(struct adv_softc *adv, int initiate_bus_reset)
 2018 {
 2019         int count; 
 2020         int i;
 2021         union ccb *ccb;
 2022 
 2023         i = 200;
 2024         while ((ADV_INW(adv, ADV_CHIP_STATUS) & ADV_CSW_SCSI_RESET_ACTIVE) != 0
 2025             && i--)
 2026                 DELAY(1000);
 2027         adv_reset_chip(adv, initiate_bus_reset);
 2028         adv_reinit_lram(adv);
 2029         for (i = 0; i <= ADV_MAX_TID; i++)
 2030                 adv_set_syncrate(adv, NULL, i, /*period*/0,
 2031                                  /*offset*/0, ADV_TRANS_CUR);
 2032         ADV_OUTW(adv, ADV_REG_PROG_COUNTER, ADV_MCODE_START_ADDR);
 2033 
 2034         /* Tell the XPT layer that a bus reset occured */
 2035         if (adv->path != NULL)
 2036                 xpt_async(AC_BUS_RESET, adv->path, NULL);
 2037 
 2038         count = 0;
 2039         while ((ccb = (union ccb *)LIST_FIRST(&adv->pending_ccbs)) != NULL) {
 2040                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)
 2041                         ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
 2042                 adv_done(adv, ccb, QD_ABORTED_BY_HOST, 0, 0, 0);
 2043                 count++;
 2044         }
 2045 
 2046         adv_start_chip(adv);
 2047         return (count);
 2048 }
 2049 
 2050 static void
 2051 adv_set_sdtr_reg_at_id(struct adv_softc *adv, int tid, u_int8_t sdtr_data)
 2052 {
 2053         int orig_id;
 2054 
 2055         adv_set_bank(adv, 1);
 2056         orig_id = ffs(ADV_INB(adv, ADV_HOST_SCSIID)) - 1;
 2057         ADV_OUTB(adv, ADV_HOST_SCSIID, tid);
 2058         if (ADV_INB(adv, ADV_HOST_SCSIID) == (0x01 << tid)) {
 2059                 adv_set_bank(adv, 0);
 2060                 ADV_OUTB(adv, ADV_SYN_OFFSET, sdtr_data);
 2061         }
 2062         adv_set_bank(adv, 1);
 2063         ADV_OUTB(adv, ADV_HOST_SCSIID, orig_id);
 2064         adv_set_bank(adv, 0);
 2065 }

Cache object: 8cf98a16c29615afa9445cae4e217550


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