LCOV - code coverage report
Current view: top level - dev/pci - arc.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1157 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 54 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: arc.c,v 1.107 2015/09/10 18:10:33 deraadt Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : /*
      20             :  * Ching Huang   Support ARC1880,1882,1213,1223,1214
      21             :  */
      22             : #include "bio.h"
      23             : 
      24             : #include <sys/param.h>
      25             : #include <sys/systm.h>
      26             : #include <sys/buf.h>
      27             : #include <sys/kernel.h>
      28             : #include <sys/malloc.h>
      29             : #include <sys/mutex.h>
      30             : #include <sys/device.h>
      31             : #include <sys/rwlock.h>
      32             : #include <sys/task.h>
      33             : 
      34             : #include <machine/bus.h>
      35             : 
      36             : #include <dev/pci/pcireg.h>
      37             : #include <dev/pci/pcivar.h>
      38             : #include <dev/pci/pcidevs.h>
      39             : 
      40             : #include <scsi/scsi_all.h>
      41             : #include <scsi/scsiconf.h>
      42             : 
      43             : #include <sys/sensors.h>
      44             : #if NBIO > 0
      45             : #include <sys/ioctl.h>
      46             : #include <dev/biovar.h>
      47             : #endif
      48             : 
      49             : #ifdef ARC_DEBUG
      50             : #define ARC_D_INIT      (1<<0)
      51             : #define ARC_D_RW        (1<<1)
      52             : #define ARC_D_DB        (1<<2)
      53             : 
      54             : int arcdebug = 0;
      55             : 
      56             : #define DPRINTF(p...)           do { if (arcdebug) printf(p); } while (0)
      57             : #define DNPRINTF(n, p...)       do { if ((n) & arcdebug) printf(p); } while (0)
      58             : 
      59             : #else
      60             : #define DPRINTF(p...)           /* p */
      61             : #define DNPRINTF(n, p...)       /* n, p */
      62             : #endif
      63             : 
      64             : #define ARC_HBA_TYPE_A    0x00000001
      65             : #define ARC_HBA_TYPE_B    0x00000002
      66             : #define ARC_HBA_TYPE_C    0x00000003
      67             : #define ARC_HBA_TYPE_D    0x00000004
      68             : 
      69             : #define ARC_RA_PCI_BAR                  PCI_MAPREG_START
      70             : #define ARC_RB_DOORBELL_BAR             PCI_MAPREG_START
      71             : #define ARC_RB_RWBUFFER_BAR             PCI_MAPREG_PPB_END
      72             : #define ARC_RC_PCI_BAR                  PCI_MAPREG_PCB_END
      73             : #define ARC_RD_PCI_BAR                  PCI_MAPREG_START
      74             : 
      75             : #define ARCMSR_MAX_CCB_COUNT            264
      76             : #define ARCMSR_MAX_HBB_POSTQUEUE        264
      77             : #define ARCMSR_MAX_HBD_POSTQUEUE        256
      78             : 
      79             : /* Areca boards using the Intel IOP are Type A (RA) */
      80             : 
      81             : #define ARC_RA_INB_MSG0                         0x0010
      82             : #define  ARC_RA_INB_MSG0_NOP                    (0x00000000)
      83             : #define  ARC_RA_INB_MSG0_GET_CONFIG             (0x00000001)
      84             : #define  ARC_RA_INB_MSG0_SET_CONFIG             (0x00000002)
      85             : #define  ARC_RA_INB_MSG0_ABORT_CMD              (0x00000003)
      86             : #define  ARC_RA_INB_MSG0_STOP_BGRB              (0x00000004)
      87             : #define  ARC_RA_INB_MSG0_FLUSH_CACHE            (0x00000005)
      88             : #define  ARC_RA_INB_MSG0_START_BGRB             (0x00000006)
      89             : #define  ARC_RA_INB_MSG0_CHK331PENDING          (0x00000007)
      90             : #define  ARC_RA_INB_MSG0_SYNC_TIMER             (0x00000008)
      91             : #define ARC_RA_INB_MSG1                         0x0014
      92             : #define ARC_RA_OUTB_ADDR0                       0x0018
      93             : #define ARC_RA_OUTB_ADDR1                       0x001c
      94             : #define  ARC_RA_OUTB_ADDR1_FIRMWARE_OK          (1<<31)
      95             : #define ARC_RA_INB_DOORBELL                     0x0020
      96             : #define  ARC_RA_INB_DOORBELL_WRITE_OK           (1<<0)
      97             : #define  ARC_RA_INB_DOORBELL_READ_OK            (1<<1)
      98             : #define ARC_RA_OUTB_DOORBELL                    0x002c
      99             : #define  ARC_RA_OUTB_DOORBELL_WRITE_OK          (1<<0)
     100             : #define  ARC_RA_OUTB_DOORBELL_READ_OK           (1<<1)
     101             : #define ARC_RA_INTRSTAT                         0x0030
     102             : #define  ARC_RA_INTRSTAT_MSG0                   (1<<0)
     103             : #define  ARC_RA_INTRSTAT_MSG1                   (1<<1)
     104             : #define  ARC_RA_INTRSTAT_DOORBELL               (1<<2)
     105             : #define  ARC_RA_INTRSTAT_POSTQUEUE              (1<<3)
     106             : #define  ARC_RA_INTRSTAT_PCI                    (1<<4)
     107             : #define  ARC_RA_INTR_STAT_ALL                   0x1F
     108             : #define ARC_RA_INTRMASK                         0x0034
     109             : #define  ARC_RA_INTRMASK_MSG0                   (1<<0)
     110             : #define  ARC_RA_INTRMASK_MSG1                   (1<<1)
     111             : #define  ARC_RA_INTRMASK_DOORBELL               (1<<2)
     112             : #define  ARC_RA_INTRMASK_POSTQUEUE              (1<<3)
     113             : #define  ARC_RA_INTRMASK_PCI                    (1<<4)
     114             : #define  ARC_RA_INTR_MASK_ALL                   0x1F
     115             : #define ARC_RA_POST_QUEUE                       0x0040
     116             : #define  ARC_RA_POST_QUEUE_ADDR_SHIFT           5
     117             : #define  ARC_RA_POST_QUEUE_IAMBIOS              (1<<30)
     118             : #define  ARC_RA_POST_QUEUE_BIGFRAME             (1<<31)
     119             : #define ARC_RA_REPLY_QUEUE                      0x0044
     120             : #define  ARC_RA_REPLY_QUEUE_ADDR_SHIFT          5
     121             : #define  ARC_RA_REPLY_QUEUE_ERR                 (1<<28)
     122             : #define  ARC_RA_REPLY_QUEUE_IAMBIOS             (1<<30)
     123             : #define ARC_RA_MSGBUF                           0x0a00
     124             : #define  ARC_RA_MSGBUF_LEN                      1024
     125             : #define ARC_RA_IOC_WBUF_LEN                     0x0e00
     126             : #define ARC_RA_IOC_WBUF                         0x0e04
     127             : #define ARC_RA_IOC_RBUF_LEN                     0x0f00
     128             : #define ARC_RA_IOC_RBUF                         0x0f04
     129             : #define  ARC_RA_IOC_RWBUF_MAXLEN                124 /* for both RBUF and WBUF */
     130             : 
     131             : /* Areca boards using the Marvel IOP0 are Type B (RB) */
     132             : 
     133             : #define ARC_RB_DRV2IOP_DOORBELL         0x00020400
     134             : #define ARC_RB_DRV2IOP_DOORBELL_MASK    0x00020404
     135             : #define ARC_RB_IOP2DRV_DOORBELL         0x00020408
     136             : #define ARC_RB_IOP2DRV_DOORBELL_FIRMWARE_OK     (1<<31)
     137             : #define ARC_RB_IOP2DRV_DOORBELL_MASK    0x0002040c
     138             : 
     139             : /* Areca boards using the LSI IOP are Type C (RC) */
     140             : 
     141             : #define ARC_RC_INB_DOORBELL             0x20
     142             : #define ARC_RC_INTR_STAT                0x30
     143             : #define ARC_RC_INTR_MASK                0x34
     144             : #define ARC_RC_OUTB_DOORBELL            0x9C
     145             : #define ARC_RC_OUTB_DOORBELL_CLR        0xA0
     146             : #define ARC_RC_D2I_MSG_CMD_DONE         0x08
     147             : #define ARC_RC_I2D_MSG_CMD_DONE         0x08
     148             : #define ARC_RC_I2D_MSG_CMD_DONE_CLR     0x08
     149             : #define ARC_RC_INB_MSGADDR0             0xB0
     150             : #define ARC_RC_INB_MSGADDR1             0xB4
     151             : #define ARC_RC_OUTB_MSGADDR0            0xB8
     152             : #define ARC_RC_OUTB_MSGADDR1            0xBC
     153             : #define ARC_RC_OUTB_MSG_FIRMWARE_OK     0x80000000
     154             : #define ARC_RC_INB_POSTQ_LOW            0xC0
     155             : #define ARC_RC_INB_POSTQ_HIGH           0xC4
     156             : #define ARC_RC_OUTB_REPLYQ_LOW          0xC8
     157             : #define ARC_RC_OUTB_REPLYQ_HIGH         0xCC
     158             : #define ARC_RC_MSG_WBUF_LEN             0x2000
     159             : #define ARC_RC_MSG_WBUF                 0x2004
     160             : #define ARC_RC_MSG_RBUF_LEN             0x2100
     161             : #define ARC_RC_MSG_RBUF                 0x2104
     162             : #define ARC_RC_MSG_RWBUF                0x2200
     163             : 
     164             : #define ARC_RC_INB_MSG0_NOP             (0x00000000)
     165             : #define ARC_RC_INB_MSG0_GET_CONFIG      (0x00000001)
     166             : #define ARC_RC_INB_MSG0_SET_CONFIG      (0x00000002)
     167             : #define ARC_RC_INB_MSG0_ABORT_CMD       (0x00000003)
     168             : #define ARC_RC_INB_MSG0_STOP_BGRB       (0x00000004)
     169             : #define ARC_RC_INB_MSG0_FLUSH_CACHE     (0x00000005)
     170             : #define ARC_RC_INB_MSG0_START_BGRB      (0x00000006)
     171             : #define ARC_RC_INB_MSG0_CHK331PENDING   (0x00000007)
     172             : #define ARC_RC_INB_MSG0_SYNC_TIMER      (0x00000008)
     173             : 
     174             : #define ARC_RC_D2I_DATA_WRITE_OK        0x00000002
     175             : #define ARC_RC_D2I_DATA_READ_OK         0x00000004
     176             : #define ARC_RC_D2I_MESSAGE_CMD_DONE     0x00000008
     177             : #define ARC_RC_D2I_POSTQUEUE_THROTTLING 0x00000010
     178             : #define ARC_RC_I2D_DATA_WRITE_OK        0x00000002
     179             : #define ARC_RC_I2D_DATA_WRITE_OK_CLEAR  0x00000002
     180             : #define ARC_RC_I2D_DATA_READ_OK         0x00000004
     181             : #define ARC_RC_I2D_DATA_READ_OK_CLEAR   0x00000004
     182             : #define ARC_RC_I2D_MESSAGE_CMD_DONE     0x00000008
     183             : #define ARC_RC_I2D_MESSAGE_CMD_DONE_CLEAR 0x00000008
     184             : #define ARC_RC_MESSAGE_FIRMWARE_OK      0x80000000
     185             : 
     186             : #define ARC_RC_INTR_STAT_UTILITY_A      (1<<0)
     187             : #define ARC_RC_INTR_STAT_DOORBELL       (1<<2)
     188             : #define ARC_RC_INTR_STAT_POSTQUEUE      (1<<3)
     189             : #define ARC_RC_INTR_MASK_ALL            0x0000000D
     190             : #define ARC_RC_INTR_MASK_UTILITY_A      (1<<0)
     191             : #define ARC_RC_INTR_MASK_DOORBELL       (1<<2)
     192             : #define ARC_RC_INTR_MASK_POSTQUEUE      (1<<3)
     193             : #define ARC_RC_REPLY_QUEUE_ERR          1
     194             : #define ARC_RC_THROTTLE                 12
     195             : 
     196             : /* Areca boards using the Marvell IOP 9580 are Type D (RD) */
     197             : 
     198             : #define ARC_RD_INTR_STAT                0x200
     199             : #define ARC_RD_HOST_INT_ENABLE          0x204
     200             : #define ARC_RD_INTR_ENABLE              0x20C
     201             : #define ARC_RD_D2I_MSG_CMD_DONE         0x08
     202             : #define ARC_RD_I2D_MSG_CMD_DONE         0x2000000
     203             : #define ARC_RD_I2D_MSG_CMD_DONE_CLR     0x2000000
     204             : #define ARC_RD_INB_MSGADDR0             0x400
     205             : #define ARC_RD_INB_MSGADDR1             0x404
     206             : #define ARC_RD_OUTB_MSGADDR0            0x420
     207             : #define ARC_RD_OUTB_MSGADDR1            0x424
     208             : #define ARC_RD_INB_DOORBELL             0x460
     209             : #define ARC_RD_OUTB_DOORBELL            0x480
     210             : #define ARC_RD_OUTB_DOORBELL_CLR        0x480
     211             : #define ARC_RD_OUTB_DOORBELL_ENABLE     0x484
     212             : #define ARC_RD_OUTB_MSG_FIRMWARE_OK     0x80000000
     213             : #define ARC_RD_INB_POSTQ_LOW            0x1000
     214             : #define ARC_RD_INB_POSTQ_HIGH           0x1004
     215             : #define ARC_RD_OUTB_REPLYQ_LOW          0x1060
     216             : #define ARC_RD_OUTB_REPLYQ_HIGH         0x1064
     217             : 
     218             : #define ARC_RD_INB_WRITE_PTR            0x1018
     219             : #define ARC_RD_INB_READ_PTR             0x101C
     220             : #define ARC_RD_OUTB_COPY_PTR            0x106C
     221             : #define ARC_RD_OUTB_READ_PTR            0x1070
     222             : #define ARC_RD_OUTB_INTR_CAUSE          0x1088
     223             : #define ARC_RD_OUTB_INT_ENABLE          0x108C
     224             : #define ARC_RD_MSG_WBUF_LEN             0x2000
     225             : #define ARC_RD_MSG_WBUF                 0x2004
     226             : #define ARC_RD_MSG_RBUF_LEN             0x2100
     227             : #define ARC_RD_MSG_RBUF                 0x2104
     228             : #define ARC_RD_MSG_RWBUF                0x2200
     229             : 
     230             : #define ARC_RD_INB_MSG0_NOP             (0x00000000)
     231             : #define ARC_RD_INB_MSG0_GET_CONFIG      (0x00000001)
     232             : #define ARC_RD_INB_MSG0_SET_CONFIG      (0x00000002)
     233             : #define ARC_RD_INB_MSG0_ABORT_CMD       (0x00000003)
     234             : #define ARC_RD_INB_MSG0_STOP_BGRB       (0x00000004)
     235             : #define ARC_RD_INB_MSG0_FLUSH_CACHE     (0x00000005)
     236             : #define ARC_RD_INB_MSG0_START_BGRB      (0x00000006)
     237             : #define ARC_RD_INB_MSG0_CHK331PENDING   (0x00000007)
     238             : #define ARC_RD_INB_MSG0_SYNC_TIMER      (0x00000008)
     239             : 
     240             : #define ARC_RD_D2I_DATA_WRITE_OK        0x00000001
     241             : #define ARC_RD_D2I_DATA_READ_OK         0x00000002
     242             : #define ARC_RD_D2I_MESSAGE_CMD_DONE     0x02000000
     243             : #define ARC_RD_D2I_POSTQUEUE_THROTTLING 0x00000010
     244             : #define ARC_RD_I2D_DATA_WRITE_OK        0x00000001
     245             : #define ARC_RD_I2D_DATA_WRITE_CLEAR     0x00000001
     246             : #define ARC_RD_I2D_DATA_READ_OK         0x00000002
     247             : #define ARC_RD_I2D_DATA_READ_CLEAR      0x00000002
     248             : #define ARC_RD_I2D_MESSAGE_CMD_DONE     0x02000000
     249             : #define ARC_RD_I2D_MESSAGE_CMD_DONE_CLEAR 0x02000000
     250             : #define ARC_RD_MESSAGE_FIRMWARE_OK      0x80000000
     251             : 
     252             : #define ARC_RD_INTR_STAT_DOORBELL       0x00001000
     253             : #define ARC_RD_INTR_STAT_POSTQUEUE      0x00000010
     254             : #define ARC_RD_INTR_ENABLE_ALL          0x00001010
     255             : #define ARC_RD_INTR_DISABLE_ALL         0x00000000
     256             : #define ARC_RD_INTR_ENABLE_DOORBELL     0x00001000
     257             : #define ARC_RD_INTR_ENABLE_POSTQUEUE    0x00000010
     258             : #define ARC_RD_REPLY_QUEUE_ERR          1
     259             : #define ARC_RD_OUTB_LIST_INT_CLR        1
     260             : 
     261             : struct arc_msg_firmware_info {
     262             :         u_int32_t               signature;
     263             : #define ARC_FWINFO_SIGNATURE_GET_CONFIG         (0x87974060)
     264             : #define ARC_FWINFO_SIGNATURE_SET_CONFIG         (0x87974063)
     265             :         u_int32_t               request_len;
     266             :         u_int32_t               queue_len;
     267             :         u_int32_t               sdram_size;
     268             :         u_int32_t               sata_ports;
     269             :         u_int8_t                vendor[40];
     270             :         u_int8_t                model[8];
     271             :         u_int8_t                fw_version[16];
     272             :         u_int8_t                device_map[16];
     273             :         u_int32_t               cfgVersion;
     274             :         u_int8_t                cfgSerial[16];
     275             :         u_int32_t               cfgPicStatus;
     276             : } __packed;
     277             : 
     278             : /* definitions of the firmware commands sent via the doorbells */
     279             : 
     280             : struct arc_fw_hdr {
     281             :         u_int8_t                byte1;
     282             :         u_int8_t                byte2;
     283             :         u_int8_t                byte3;
     284             : } __packed;
     285             : 
     286             : /* the fw header must always equal this */
     287             : struct arc_fw_hdr arc_fw_hdr = { 0x5e, 0x01, 0x61 };
     288             : 
     289             : struct arc_fw_bufhdr {
     290             :         struct arc_fw_hdr       hdr;
     291             :         u_int16_t               len;
     292             : } __packed;
     293             : 
     294             : #define ARC_FW_RAIDINFO         0x20    /* opcode + raid# */
     295             : #define ARC_FW_VOLINFO          0x21    /* opcode + vol# */
     296             : #define ARC_FW_DISKINFO         0x22    /* opcode + physdisk# */
     297             : #define ARC_FW_SYSINFO          0x23    /* opcode. reply is fw_sysinfo */
     298             : #define ARC_FW_MUTE_ALARM       0x30    /* opcode only */
     299             : #define ARC_FW_SET_ALARM        0x31    /* opcode + 1 byte for setting */
     300             : #define ARC_FW_SET_ALARM_DISABLE        0x00
     301             : #define ARC_FW_SET_ALARM_ENABLE         0x01
     302             : #define ARC_FW_NOP              0x38    /* opcode only */
     303             : 
     304             : #define ARC_FW_CMD_OK           0x41
     305             : #define ARC_FW_BLINK            0x43
     306             : #define ARC_FW_BLINK_ENABLE             0x00
     307             : #define ARC_FW_BLINK_DISABLE    0x01
     308             : #define ARC_FW_CMD_PASS_REQD    0x4d
     309             : 
     310             : struct arc_fw_comminfo {
     311             :         u_int8_t                baud_rate;
     312             :         u_int8_t                data_bits;
     313             :         u_int8_t                stop_bits;
     314             :         u_int8_t                parity;
     315             :         u_int8_t                flow_control;
     316             : } __packed;
     317             : 
     318             : struct arc_fw_scsiattr {
     319             :         u_int8_t                channel; /* channel for SCSI target (0/1) */
     320             :         u_int8_t                target;
     321             :         u_int8_t                lun;
     322             :         u_int8_t                tagged;
     323             :         u_int8_t                cache;
     324             :         u_int8_t                speed;
     325             : } __packed;
     326             : 
     327             : struct arc_fw_raidinfo {
     328             :         u_int8_t                set_name[16];
     329             :         u_int32_t               capacity;
     330             :         u_int32_t               capacity2;
     331             :         u_int32_t               fail_mask;
     332             :         u_int8_t                device_array[32];
     333             :         u_int8_t                member_devices;
     334             :         u_int8_t                new_member_devices;
     335             :         u_int8_t                raid_state;
     336             :         u_int8_t                volumes;
     337             :         u_int8_t                volume_list[16];
     338             :         u_int8_t                reserved1[3];
     339             :         u_int8_t                free_segments;
     340             :         u_int32_t               raw_stripes[8];
     341             :         u_int32_t               reserved2[3];
     342             :         u_int8_t                vol_ListX[112];
     343             :         u_int8_t                devEncArray[32];
     344             : } __packed;
     345             : 
     346             : struct arc_fw_volinfo {
     347             :         u_int8_t                set_name[16];
     348             :         u_int32_t               capacity;
     349             :         u_int32_t               capacity2;
     350             :         u_int32_t               fail_mask;
     351             :         u_int32_t               stripe_size; /* in blocks */
     352             :         u_int32_t               new_fail_mask;
     353             :         u_int32_t               new_stripe_size;
     354             :         u_int32_t               volume_status;
     355             : #define ARC_FW_VOL_STATUS_NORMAL        0x00
     356             : #define ARC_FW_VOL_STATUS_INITTING      (1<<0)
     357             : #define ARC_FW_VOL_STATUS_FAILED        (1<<1)
     358             : #define ARC_FW_VOL_STATUS_MIGRATING     (1<<2)
     359             : #define ARC_FW_VOL_STATUS_REBUILDING    (1<<3)
     360             : #define ARC_FW_VOL_STATUS_NEED_INIT     (1<<4)
     361             : #define ARC_FW_VOL_STATUS_NEED_MIGRATE  (1<<5)
     362             : #define ARC_FW_VOL_STATUS_INIT_FLAG     (1<<6)
     363             : #define ARC_FW_VOL_STATUS_NEED_REGEN    (1<<7)
     364             : #define ARC_FW_VOL_STATUS_CHECKING      (1<<8)
     365             : #define ARC_FW_VOL_STATUS_NEED_CHECK    (1<<9)
     366             :         u_int32_t               progress;
     367             :         struct arc_fw_scsiattr  scsi_attr;
     368             :         u_int8_t                member_disks;
     369             :         u_int8_t                raid_level;
     370             : #define ARC_FW_VOL_RAIDLEVEL_0          0x00
     371             : #define ARC_FW_VOL_RAIDLEVEL_1          0x01
     372             : #define ARC_FW_VOL_RAIDLEVEL_3          0x02
     373             : #define ARC_FW_VOL_RAIDLEVEL_5          0x03
     374             : #define ARC_FW_VOL_RAIDLEVEL_6          0x04
     375             : #define ARC_FW_VOL_RAIDLEVEL_PASSTHRU   0x05
     376             :         u_int8_t                new_member_disks;
     377             :         u_int8_t                new_raid_level;
     378             :         u_int8_t                raid_set_number;
     379             :         u_int8_t                vol_state0;
     380             :         u_int32_t               host_speed;
     381             :         u_int32_t               vol_state;
     382             :         u_int8_t                vol_array[16];
     383             :         u_int8_t                num_5060volumes;
     384             :         u_int8_t                reserved[43];
     385             : } __packed;
     386             : 
     387             : struct arc_fw_diskinfo {
     388             :         u_int8_t                model[40];
     389             :         u_int8_t                serial[20];
     390             :         u_int8_t                firmware_rev[8];
     391             :         u_int32_t               capacity;
     392             :         u_int32_t               capacity2;
     393             :         u_int8_t                device_state;
     394             :         u_int8_t                pio_mode;
     395             :         u_int8_t                current_udma_mode;
     396             :         u_int8_t                udma_mode;
     397             :         u_int8_t                hot_spare_type;
     398             :         u_int8_t                raid_number; /* 0xff unowned */
     399             :         struct arc_fw_scsiattr  scsi_attr;
     400             :         u_int8_t                reserved[170];
     401             : } __packed;
     402             : 
     403             : struct arc_fw_sysinfo {
     404             :         u_int8_t                vendor_name[40];
     405             :         u_int8_t                serial_number[16];
     406             :         u_int8_t                firmware_version[16];
     407             :         u_int8_t                boot_version[16];
     408             :         u_int8_t                mb_version[16];
     409             :         u_int8_t                model_name[8];
     410             : 
     411             :         u_int8_t                local_ip[4];
     412             :         u_int8_t                current_ip[4];
     413             : 
     414             :         u_int32_t               time_tick;
     415             :         u_int32_t               cpu_speed;
     416             :         u_int32_t               icache;
     417             :         u_int32_t               dcache;
     418             :         u_int32_t               scache;
     419             :         u_int32_t               memory_size;
     420             :         u_int32_t               memory_speed;
     421             :         u_int32_t               events;
     422             : 
     423             :         u_int8_t                gsiMacAddress[6];
     424             :         u_int8_t                gsiDhcp;
     425             :         u_int8_t                alarm;
     426             :         u_int8_t                channel_usage;
     427             :         u_int8_t                max_ata_mode;
     428             :         u_int8_t                sdram_ecc;
     429             :         u_int8_t                rebuild_priority;
     430             :         struct arc_fw_comminfo  comm_a;
     431             :         struct arc_fw_comminfo  comm_b;
     432             :         u_int8_t                ide_channels;
     433             :         u_int8_t                scsi_host_channels;
     434             :         u_int8_t                ide_host_channels;
     435             :         u_int8_t                max_volume_set;
     436             :         u_int8_t                max_raid_set;
     437             :         u_int8_t                ether_port;
     438             :         u_int8_t                raid6_engine;
     439             :         u_int8_t                reserved[75];
     440             : } __packed;
     441             : 
     442             : struct arc_iop;
     443             : struct arc_ccb;
     444             : SLIST_HEAD(arc_ccb_list, arc_ccb);
     445             : 
     446             : struct InBound_SRB {
     447             :         u_int32_t addressLow;   /* pointer to SRB block */
     448             :         u_int32_t addressHigh;
     449             :         u_int32_t length;       /* in DWORDs */
     450             :         u_int32_t reserved0;
     451             : };
     452             : 
     453             : struct OutBound_SRB {
     454             :         u_int32_t addressLow;   /* pointer to SRB block */
     455             :         u_int32_t addressHigh;
     456             : };
     457             : 
     458             : struct arc_HBD_Msgu {
     459             :         struct InBound_SRB post_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE];
     460             :         struct OutBound_SRB done_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE+1];
     461             :         u_int16_t postq_index;
     462             :         u_int16_t doneq_index;
     463             : };
     464             : 
     465             : #define         ARC_MAX_CMDQ_PTR_LEN    sizeof(struct arc_HBD_Msgu)
     466             : 
     467             : struct arc_msg_scsicmd {
     468             :         u_int8_t                bus;
     469             :         u_int8_t                target;
     470             :         u_int8_t                lun;
     471             :         u_int8_t                function;
     472             : 
     473             :         u_int8_t                cdb_len;
     474             :         u_int8_t                sgl_len;
     475             :         u_int8_t                flags;
     476             : #define ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512      (1<<0)
     477             : #define ARC_MSG_SCSICMD_FLAG_FROM_BIOS          (1<<1)
     478             : #define ARC_MSG_SCSICMD_FLAG_WRITE              (1<<2)
     479             : #define ARC_MSG_SCSICMD_FLAG_SIMPLEQ    (0x00)
     480             : #define ARC_MSG_SCSICMD_FLAG_HEADQ              (0x08)
     481             : #define ARC_MSG_SCSICMD_FLAG_ORDERQ             (0x10)
     482             :         u_int8_t                msgPages;
     483             : 
     484             :         u_int32_t               context;
     485             :         u_int32_t               data_len;
     486             : 
     487             : #define ARC_MSG_CDBLEN                          16
     488             :         u_int8_t                cdb[ARC_MSG_CDBLEN];
     489             : 
     490             :         u_int8_t                status;
     491             : #define ARC_MSG_STATUS_SELTIMEOUT               0xf0
     492             : #define ARC_MSG_STATUS_ABORTED                  0xf1
     493             : #define ARC_MSG_STATUS_INIT_FAIL                0xf2
     494             : #define ARC_MSG_SENSELEN                        15
     495             :         u_int8_t                sense_data[ARC_MSG_SENSELEN];
     496             : 
     497             :         /* followed by an sgl */
     498             : } __packed;
     499             : 
     500             : struct arc_sge {
     501             :         u_int32_t               sg_length;
     502             : #define ARC_SGE_64BIT                           (1<<24)
     503             :         u_int32_t               sg_lo_addr;
     504             :         u_int32_t               sg_hi_addr;
     505             : } __packed;
     506             : 
     507             : #define ARC_MAX_TARGET          16
     508             : #define ARC_MAX_LUN             8
     509             : #define ARC_MAX_IOCMDLEN        512
     510             : #define ARC_BLOCKSIZE           512
     511             : 
     512             : /* the firmware deals with up to 256 or 512 byte command frames. */
     513             : /* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 38) == 508 */
     514             : #define ARC_SGL_MAXLEN          38
     515             : /* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 17) == 252 */
     516             : #define ARC_SGL_256LEN          17
     517             : 
     518             : struct arc_io_cmd {
     519             :         struct arc_msg_scsicmd  cmd;
     520             :         struct arc_sge  sgl[ARC_SGL_MAXLEN];
     521             :         u_int32_t               reserved1;
     522             :         struct arc_ccb  *ccb;
     523             :         u_int32_t               reserved2[6];
     524             : } __packed;
     525             : 
     526             : #define ARC_IO_CMD_LEN  512+32
     527             : 
     528             : /* stuff to manage a scsi command */
     529             : struct arc_ccb {
     530             :         struct arc_softc        *ccb_sc;
     531             : 
     532             :         struct scsi_xfer        *ccb_xs;
     533             : 
     534             :         bus_dmamap_t            ccb_dmamap;
     535             :         bus_addr_t              cmd_dma_offset;
     536             :         struct arc_io_cmd       *ccb_cmd;
     537             :         u_int32_t               ccb_cmd_post;
     538             : 
     539             :         SLIST_ENTRY(arc_ccb)    ccb_link;
     540             :         u_int32_t               arc_io_cmd_length;
     541             : };
     542             : 
     543             : struct arc_softc {
     544             :         struct device           sc_dev;
     545             :         const struct arc_iop    *sc_iop;
     546             :         struct scsi_link        sc_link;
     547             : 
     548             :         pci_chipset_tag_t       sc_pc;
     549             :         pcitag_t                sc_tag;
     550             : 
     551             :         bus_space_tag_t         sc_iot;
     552             :         bus_space_handle_t      sc_ioh;
     553             :         bus_size_t              sc_ios;
     554             :         bus_dma_tag_t           sc_dmat;
     555             : 
     556             :         void                    *sc_ih;
     557             : 
     558             :         u_int32_t               sc_req_count;
     559             : 
     560             :         struct arc_dmamem       *sc_requests;
     561             :         struct arc_ccb          *sc_ccbs;
     562             :         struct arc_ccb_list     sc_ccb_free;
     563             :         struct mutex            sc_ccb_mtx;
     564             : 
     565             :         struct scsi_iopool      sc_iopool;
     566             :         struct scsibus_softc    *sc_scsibus;
     567             : 
     568             :         struct rwlock           sc_lock;
     569             :         volatile int            sc_talking;
     570             : 
     571             :         struct ksensor          *sc_sensors;
     572             :         struct ksensordev       sc_sensordev;
     573             :         int                     sc_nsensors;
     574             : 
     575             :         u_int32_t               sc_ledmask;
     576             :         u_int32_t               sc_adp_type;
     577             :         u_int32_t               sc_ccb_phys_hi;
     578             :         u_int32_t               postQ_buffer;
     579             :         u_int32_t               doneQ_buffer;
     580             :         bus_addr_t              cmdQ_ptr_offset;
     581             :         struct arc_HBD_Msgu *pmu;
     582             : };
     583             : #define DEVNAME(_s)             ((_s)->sc_dev.dv_xname)
     584             : 
     585             : /* wrap up the bus_dma api */
     586             : struct arc_dmamem {
     587             :         bus_dmamap_t            adm_map;
     588             :         bus_dma_segment_t       adm_seg;
     589             :         size_t                  adm_size;
     590             :         caddr_t                 adm_kva;
     591             : };
     592             : #define ARC_DMA_MAP(_adm)       ((_adm)->adm_map)
     593             : #define ARC_DMA_DVA(_adm)       ((_adm)->adm_map->dm_segs[0].ds_addr)
     594             : #define ARC_DMA_KVA(_adm)       ((void *)(_adm)->adm_kva)
     595             : 
     596             : int     arc_match(struct device *, void *, void *);
     597             : void    arc_attach(struct device *, struct device *, void *);
     598             : int     arc_detach(struct device *, int);
     599             : int     arc_activate(struct device *, int);
     600             : int     arc_intr(void *);
     601             : int     arc_intr_A(void *);
     602             : int     arc_intr_C(void *);
     603             : int     arc_intr_D(void *);
     604             : 
     605             : /* interface for scsi midlayer to talk to */
     606             : void    arc_scsi_cmd(struct scsi_xfer *);
     607             : void    arc_minphys(struct buf *, struct scsi_link *);
     608             : 
     609             : /* code to deal with getting bits in and out of the bus space */
     610             : u_int32_t       arc_read(struct arc_softc *, bus_size_t);
     611             : void            arc_read_region(struct arc_softc *, bus_size_t,
     612             :                             void *, size_t);
     613             : void            arc_write(struct arc_softc *, bus_size_t, u_int32_t);
     614             : void            arc_write_region(struct arc_softc *, bus_size_t,
     615             :                             void *, size_t);
     616             : int                     arc_wait_eq(struct arc_softc *, bus_size_t,
     617             :                             u_int32_t, u_int32_t);
     618             : int                     arc_wait_ne(struct arc_softc *, bus_size_t,
     619             :                             u_int32_t, u_int32_t);
     620             : int                     arc_msg0(struct arc_softc *, u_int32_t);
     621             : 
     622             : struct arc_dmamem       *arc_dmamem_alloc(struct arc_softc *, size_t);
     623             : void            arc_dmamem_free(struct arc_softc *,
     624             :                             struct arc_dmamem *);
     625             : void arc_free_ccb_src(struct arc_softc *sc);
     626             : 
     627             : int                     arc_alloc_ccbs(struct arc_softc *);
     628             : struct arc_ccb  *arc_get_ccb(struct arc_softc *);
     629             : void            arc_put_ccb(struct arc_softc *, struct arc_ccb *);
     630             : int                     arc_load_xs(struct arc_ccb *);
     631             : int                     arc_complete(struct arc_softc *, struct arc_ccb *,
     632             :                             int);
     633             : void            arc_scsi_cmd_done(struct arc_softc *, struct arc_ccb *,
     634             :                             u_int32_t);
     635             : 
     636             : int                     arc_map_pci_resources(struct arc_softc *,
     637             :                             struct pci_attach_args *);
     638             : void            arc_unmap_pci_resources(struct arc_softc *);
     639             : int             arc_chipA_firmware(struct arc_softc *);
     640             : int             arc_chipB_firmware(struct arc_softc *);
     641             : int             arc_chipC_firmware(struct arc_softc *);
     642             : int             arc_chipD_firmware(struct arc_softc *);
     643             : void            arc_enable_all_intr(struct arc_softc *);
     644             : void            arc_disable_all_intr(struct arc_softc *);
     645             : void            arc_stop_bgrb_proc(struct arc_softc *sc);
     646             : void            arc_flush_cache(struct arc_softc *sc);
     647             : void            arc_iop_set_conf(struct arc_softc *sc);
     648             : 
     649             : #if NBIO > 0
     650             : /* stuff to do messaging via the doorbells */
     651             : void            arc_lock(struct arc_softc *);
     652             : void            arc_unlock(struct arc_softc *);
     653             : void            arc_wait(struct arc_softc *);
     654             : u_int8_t        arc_msg_cksum(void *, u_int16_t);
     655             : int                     arc_msgbuf(struct arc_softc *, void *, size_t,
     656             :                             void *, size_t, int);
     657             : 
     658             : /* bioctl */
     659             : int                     arc_bioctl(struct device *, u_long, caddr_t);
     660             : int                     arc_bio_inq(struct arc_softc *, struct bioc_inq *);
     661             : int                     arc_bio_vol(struct arc_softc *, struct bioc_vol *);
     662             : int                     arc_bio_disk(struct arc_softc *, struct bioc_disk *);
     663             : int                     arc_bio_alarm(struct arc_softc *, struct bioc_alarm *);
     664             : int                     arc_bio_alarm_state(struct arc_softc *,
     665             :                             struct bioc_alarm *);
     666             : int                     arc_bio_blink(struct arc_softc *, struct bioc_blink *);
     667             : 
     668             : int                     arc_bio_getvol(struct arc_softc *, int,
     669             :                             struct arc_fw_volinfo *);
     670             : 
     671             : #ifndef SMALL_KERNEL
     672             : struct arc_task {
     673             :         struct task t;
     674             :         struct arc_softc *sc;
     675             : };
     676             : /* sensors */
     677             : void                    arc_create_sensors(void *);
     678             : void                    arc_refresh_sensors(void *);
     679             : #endif /* SMALL_KERNEL */
     680             : #endif
     681             : 
     682             : struct cfattach arc_ca = {
     683             :         sizeof(struct arc_softc), arc_match, arc_attach, arc_detach,
     684             :         arc_activate
     685             : };
     686             : 
     687             : struct cfdriver arc_cd = {
     688             :         NULL, "arc", DV_DULL
     689             : };
     690             : 
     691             : struct scsi_adapter arc_switch = {
     692             :         arc_scsi_cmd, arc_minphys, NULL, NULL, NULL
     693             : };
     694             : 
     695             : /* real stuff for dealing with the hardware */
     696             : struct arc_iop {
     697             :         int                     (*iop_query_firmware)(struct arc_softc *);
     698             : };
     699             : 
     700             : static const struct arc_iop arc_intel = {
     701             :         arc_chipA_firmware
     702             : };
     703             : 
     704             : static const struct arc_iop arc_marvell = {
     705             :         arc_chipB_firmware
     706             : };
     707             : 
     708             : static const struct arc_iop arc_lsi = {
     709             :         arc_chipC_firmware
     710             : };
     711             : 
     712             : static const struct arc_iop arc_marvell2 = {
     713             :         arc_chipD_firmware
     714             : };
     715             : 
     716             : struct arc_board {
     717             :         pcireg_t                ab_vendor;
     718             :         pcireg_t                ab_product;
     719             :         const struct arc_iop    *ab_iop;
     720             : };
     721             : const struct arc_board  *arc_match_board(struct pci_attach_args *);
     722             : 
     723             : static const struct arc_board arc_devices[] = {
     724             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1110, &arc_intel },
     725             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1120, &arc_intel },
     726             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1130, &arc_intel },
     727             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1160, &arc_intel },
     728             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1170, &arc_intel },
     729             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1200, &arc_intel },
     730             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1200_B, &arc_marvell },
     731             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1202, &arc_intel },
     732             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1210, &arc_intel },
     733             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1214, &arc_marvell2 },
     734             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1220, &arc_intel },
     735             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1230, &arc_intel },
     736             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1260, &arc_intel },
     737             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1270, &arc_intel },
     738             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1280, &arc_intel },
     739             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1380, &arc_intel },
     740             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1381, &arc_intel },
     741             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1680, &arc_intel },
     742             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1681, &arc_intel },
     743             :         { PCI_VENDOR_ARECA, PCI_PRODUCT_ARECA_ARC1880, &arc_lsi }
     744             : };
     745             : 
     746             : const struct arc_board *
     747           0 : arc_match_board(struct pci_attach_args *pa)
     748             : {
     749             :         const struct arc_board          *ab;
     750             :         int                             i;
     751             : 
     752           0 :         for (i = 0; i < sizeof(arc_devices) / sizeof(arc_devices[0]); i++) {
     753           0 :                 ab = &arc_devices[i];
     754             : 
     755           0 :                 if (PCI_VENDOR(pa->pa_id) == ab->ab_vendor &&
     756           0 :                     PCI_PRODUCT(pa->pa_id) == ab->ab_product)
     757           0 :                         return (ab);
     758             :         }
     759             : 
     760           0 :         return (NULL);
     761           0 : }
     762             : 
     763             : int
     764           0 : arc_match(struct device *parent, void *match, void *aux)
     765             : {
     766           0 :         return ((arc_match_board(aux) == NULL) ? 0 : 1);
     767             : }
     768             : 
     769             : void
     770           0 : arc_attach(struct device *parent, struct device *self, void *aux)
     771             : {
     772           0 :         struct arc_softc                *sc = (struct arc_softc *)self;
     773           0 :         struct pci_attach_args          *pa = aux;
     774           0 :         struct scsibus_attach_args      saa;
     775             :         struct device                   *child;
     776             : 
     777           0 :         sc->sc_talking = 0;
     778           0 :         rw_init(&sc->sc_lock, "arcmsg");
     779             : 
     780           0 :         sc->sc_iop = arc_match_board(pa)->ab_iop;
     781           0 :         if(sc->sc_iop == &arc_intel)
     782           0 :                 sc->sc_adp_type = ARC_HBA_TYPE_A;
     783           0 :         else if(sc->sc_iop == &arc_marvell)
     784           0 :                 sc->sc_adp_type = ARC_HBA_TYPE_B;
     785           0 :         else if(sc->sc_iop == &arc_lsi)
     786           0 :                 sc->sc_adp_type = ARC_HBA_TYPE_C;
     787           0 :         else if(sc->sc_iop == &arc_marvell2)
     788           0 :                 sc->sc_adp_type = ARC_HBA_TYPE_D;
     789           0 :         if (arc_map_pci_resources(sc, pa) != 0) {
     790             :                 /* error message printed by arc_map_pci_resources */
     791           0 :                 return;
     792             :         }
     793             : 
     794           0 :         if (arc_alloc_ccbs(sc) != 0) {
     795             :                 /* error message printed by arc_alloc_ccbs */
     796             :                 goto unmap_pci;
     797             :         }
     798             : 
     799           0 :         arc_iop_set_conf(sc);
     800             : 
     801           0 :         if (sc->sc_iop->iop_query_firmware(sc) != 0) {
     802             :                 /* error message printed by arc_query_firmware */
     803             :                 goto unmap_pci;
     804             :         }
     805             : 
     806           0 :         sc->sc_link.adapter = &arc_switch;
     807           0 :         sc->sc_link.adapter_softc = sc;
     808           0 :         sc->sc_link.adapter_target = ARC_MAX_TARGET;
     809           0 :         sc->sc_link.adapter_buswidth = ARC_MAX_TARGET;
     810           0 :         sc->sc_link.openings = sc->sc_req_count;
     811           0 :         sc->sc_link.pool = &sc->sc_iopool;
     812             : 
     813           0 :         bzero(&saa, sizeof(saa));
     814           0 :         saa.saa_sc_link = &sc->sc_link;
     815             : 
     816           0 :         child = config_found(self, &saa, scsiprint);
     817           0 :         sc->sc_scsibus = (struct scsibus_softc *)child;
     818             : 
     819             :         /* enable interrupts */
     820           0 :         arc_enable_all_intr(sc);
     821             : 
     822             : #if NBIO > 0
     823           0 :         if (bio_register(self, arc_bioctl) != 0)
     824           0 :                 panic("%s: bioctl registration failed", DEVNAME(sc));
     825             : 
     826             : #ifndef SMALL_KERNEL
     827             :         /*
     828             :          * you need to talk to the firmware to get volume info. our firmware
     829             :          * interface relies on being able to sleep, so we need to use a thread
     830             :          * to do the work.
     831             :          */
     832             :         {
     833             :                 struct arc_task *at;
     834           0 :                 at = malloc(sizeof(*at), M_TEMP, M_WAITOK);
     835             : 
     836           0 :                 at->sc = sc;
     837           0 :                 task_set(&at->t, arc_create_sensors, at);
     838           0 :                 task_add(systq, &at->t);
     839             :         }
     840             : #endif
     841             : #endif
     842             : 
     843           0 :         return;
     844             : unmap_pci:
     845           0 :         arc_unmap_pci_resources(sc);
     846           0 : }
     847             : 
     848             : int
     849           0 : arc_activate(struct device *self, int act)
     850             : {
     851             :         int rv = 0;
     852             : 
     853           0 :         switch (act) {
     854             :         case DVACT_POWERDOWN:
     855             :                 rv = config_activate_children(self, act);
     856           0 :                 arc_detach(self, 0);
     857           0 :                 break;
     858             :         default:
     859             :                 rv = config_activate_children(self, act);
     860             :                 break;
     861             :         }
     862           0 :         return (rv);    
     863             : }
     864             : 
     865             : int
     866           0 : arc_detach(struct device *self, int flags)
     867             : {
     868           0 :         struct arc_softc                *sc = (struct arc_softc *)self;
     869             : 
     870           0 :         arc_stop_bgrb_proc(sc);
     871           0 :         arc_flush_cache(sc);
     872             : 
     873           0 :         return (0);
     874             : }
     875             : 
     876             : int
     877           0 : arc_intr_A(void *arg)
     878             : {
     879           0 :         struct arc_softc                *sc = arg;
     880             :         struct arc_ccb                  *ccb = NULL;
     881           0 :         char                            *kva = ARC_DMA_KVA(sc->sc_requests);
     882             :         struct arc_io_cmd               *cmd;
     883             :         u_int32_t                       reg, intrstat, error;
     884             :         int                             ret = 0;
     885             : 
     886           0 :         intrstat = arc_read(sc, ARC_RA_INTRSTAT);
     887           0 :         intrstat &= ARC_RA_INTRSTAT_POSTQUEUE | ARC_RA_INTRSTAT_DOORBELL |
     888             :                 ARC_RA_INTRSTAT_MSG0;
     889           0 :         arc_write(sc, ARC_RA_INTRSTAT, intrstat);
     890             : 
     891           0 :         if (intrstat & ARC_RA_INTRSTAT_DOORBELL) {
     892             :                 ret = 1;
     893           0 :                 if (sc->sc_talking) {
     894             :                         /* if an ioctl is talking, wake it up */
     895           0 :                         arc_write(sc, ARC_RA_INTRMASK,
     896             :                             ~ARC_RA_INTRMASK_POSTQUEUE);
     897           0 :                         wakeup(sc);
     898           0 :                 } else {
     899             :                         /* otherwise drop it */
     900           0 :                         reg = arc_read(sc, ARC_RA_OUTB_DOORBELL);
     901           0 :                         arc_write(sc, ARC_RA_OUTB_DOORBELL, reg);
     902           0 :                         if (reg & ARC_RA_OUTB_DOORBELL_WRITE_OK)
     903           0 :                                 arc_write(sc, ARC_RA_INB_DOORBELL,
     904             :                                     ARC_RA_INB_DOORBELL_READ_OK);
     905             :                 }
     906             :         }
     907             : 
     908           0 :         if (intrstat & ARC_RA_INTRSTAT_POSTQUEUE) {
     909           0 :                 while ((reg = arc_read(sc, ARC_RA_REPLY_QUEUE)) != 0xffffffff) {
     910             :                         ret = 1;
     911           0 :                         cmd = (struct arc_io_cmd *)(kva +
     912           0 :                         ((reg << ARC_RA_REPLY_QUEUE_ADDR_SHIFT) -
     913           0 :                         (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
     914           0 :                         ccb = cmd->ccb;
     915             : 
     916           0 :                         bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
     917             :                         ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
     918             :                         BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
     919             : 
     920           0 :                         error = (reg & ARC_RA_REPLY_QUEUE_ERR)? 1:0;
     921           0 :                         arc_scsi_cmd_done(sc, ccb, error);
     922             :                 }
     923             :         }
     924           0 :         return (ret);
     925             : }
     926             : 
     927             : int
     928           0 : arc_intr_C(void *arg)
     929             : {
     930           0 :         struct arc_softc                *sc = arg;
     931             :         struct arc_ccb                  *ccb = NULL;
     932           0 :         char                            *kva = ARC_DMA_KVA(sc->sc_requests);
     933             :         struct arc_io_cmd               *cmd;
     934             :         u_int32_t                       reg, intrstat, obmsg, error;
     935             :         int                             ret = 0, throttling;
     936             : 
     937           0 :         intrstat = arc_read(sc, ARC_RC_INTR_STAT);
     938           0 :         if (!(intrstat & (ARC_RC_INTR_STAT_POSTQUEUE | 
     939             :                 ARC_RC_INTR_STAT_DOORBELL)))
     940           0 :                 return (ret);
     941             : 
     942           0 :         if (intrstat & ARC_RC_INTR_STAT_DOORBELL) {
     943             :                 ret = 1;
     944           0 :                 if (sc->sc_talking) {
     945             :                         /* if an ioctl is talking, wake it up */
     946           0 :                         arc_write(sc, ARC_RC_INTR_MASK,
     947             :                             ~ARC_RC_INTR_MASK_POSTQUEUE);
     948           0 :                         wakeup(sc);
     949           0 :                 } else {
     950             :                         /* otherwise drop it */
     951           0 :                         reg = arc_read(sc, ARC_RC_OUTB_DOORBELL);
     952           0 :                         arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, reg);
     953           0 :                         if (reg & ARC_RC_I2D_DATA_WRITE_OK) {
     954           0 :                                 arc_write(sc, ARC_RC_INB_DOORBELL,
     955             :                                     ARC_RC_I2D_DATA_READ_OK);
     956           0 :                         }
     957             : /*                      if (reg & ARC_RC_I2D_DATA_READ_OK) {
     958             :                                 arc_write(sc, ARC_RC_INB_DOORBELL,
     959             :                                     ARC_RC_D2I_DATA_WRITE_OK);
     960             :                         }
     961             : */
     962           0 :                         if (reg & ARC_RC_I2D_MESSAGE_CMD_DONE) {
     963           0 :                                 arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR,
     964             :                                         ARC_RC_I2D_MSG_CMD_DONE_CLR);
     965           0 :                                 obmsg = arc_read(sc, ARC_RC_MSG_RWBUF);
     966             :                                 if (obmsg == ARC_FWINFO_SIGNATURE_GET_CONFIG)
     967             :                                         ;       /* handle devices hot-plug */
     968           0 :                         }
     969             :                         
     970             :                 }
     971             :         }
     972             : 
     973           0 :         if (intrstat & ARC_RC_INTR_STAT_POSTQUEUE) {
     974             :                 ret = 1;
     975             :                 throttling = 0;
     976           0 :                 while (arc_read(sc, ARC_RC_INTR_STAT) &
     977             :                         ARC_RC_INTR_STAT_POSTQUEUE) {
     978           0 :                         reg = arc_read(sc, ARC_RC_OUTB_REPLYQ_LOW);
     979           0 :                         cmd = (struct arc_io_cmd *)(kva + ((reg & 0xFFFFFFE0) -
     980           0 :                         (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
     981           0 :                         ccb = cmd->ccb;
     982             : 
     983           0 :                         bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
     984             :                         ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
     985             :                         BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
     986             : 
     987           0 :                         error = (reg & ARC_RC_REPLY_QUEUE_ERR);
     988           0 :                         arc_scsi_cmd_done(sc, ccb, error);
     989           0 :                         throttling++;
     990           0 :                         if(throttling == ARC_RC_THROTTLE) {
     991           0 :                                 arc_write(sc, ARC_RC_INB_DOORBELL,
     992             :                                     ARC_RC_D2I_POSTQUEUE_THROTTLING);
     993             :                                 throttling = 0;
     994           0 :                         }
     995             :                 }
     996             :         }
     997             : 
     998           0 :         return (ret);
     999           0 : }
    1000             : 
    1001             : static u_int16_t
    1002           0 : arcmsr_get_doneq_index(struct arc_HBD_Msgu *phbdmu)
    1003             : {
    1004             :         u_int16_t doneq_index, index_stripped;
    1005             : 
    1006           0 :         doneq_index = phbdmu->doneq_index;
    1007           0 :         if (doneq_index & 0x4000) {
    1008           0 :                 index_stripped = doneq_index & 0xFF;
    1009           0 :                 index_stripped += 1;
    1010           0 :                 index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
    1011           0 :                 phbdmu->doneq_index = index_stripped ?
    1012           0 :                     (index_stripped | 0x4000) : index_stripped;
    1013           0 :         } else {
    1014             :                 index_stripped = doneq_index;
    1015           0 :                 index_stripped += 1;
    1016           0 :                 index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
    1017           0 :                 phbdmu->doneq_index = index_stripped ?
    1018           0 :                     index_stripped : (index_stripped | 0x4000);
    1019             :         }
    1020           0 :         return (phbdmu->doneq_index);
    1021             : }
    1022             : 
    1023             : int
    1024           0 : arc_intr_D(void *arg)
    1025             : {
    1026           0 :         struct arc_softc                *sc = arg;
    1027             :         struct arc_ccb                  *ccb = NULL;
    1028           0 :         char                            *kva = ARC_DMA_KVA(sc->sc_requests);
    1029             :         struct arc_io_cmd               *cmd;
    1030             :         u_int32_t                       reg, intrstat, obmsg, error;
    1031             :         u_int32_t ob_write_ptr;
    1032             :         u_int16_t doneq_index;
    1033             :         int                             ret = 0;
    1034             :         struct arc_HBD_Msgu *pmu;
    1035             : 
    1036           0 :         intrstat = arc_read(sc, ARC_RD_INTR_STAT);
    1037           0 :         if (!(intrstat & (ARC_RD_INTR_STAT_POSTQUEUE | 
    1038             :                 ARC_RD_INTR_STAT_DOORBELL)))
    1039           0 :                 return (ret);
    1040             : 
    1041           0 :         if (intrstat & ARC_RD_INTR_STAT_DOORBELL) {
    1042             :                 ret = 1;
    1043           0 :                 if (sc->sc_talking) {
    1044             :                         /* if an ioctl is talking, wake it up */
    1045           0 :                         arc_write(sc, ARC_RD_INTR_ENABLE,
    1046             :                             ARC_RD_INTR_ENABLE_POSTQUEUE);
    1047           0 :                         wakeup(sc);
    1048           0 :                 } else {
    1049             :                         /* otherwise drop it */
    1050           0 :                         reg = arc_read(sc, ARC_RD_OUTB_DOORBELL);
    1051           0 :                         arc_write(sc, ARC_RD_OUTB_DOORBELL, reg);
    1052           0 :                         if (reg & ARC_RD_I2D_DATA_WRITE_OK) {
    1053           0 :                                 arc_write(sc, ARC_RD_INB_DOORBELL,
    1054             :                                     ARC_RD_I2D_DATA_READ_OK);
    1055           0 :                         }
    1056             : /*                      if (reg & ARC_RD_I2D_DATA_READ_OK) {
    1057             :                                 arc_write(sc, ARC_RD_INB_DOORBELL,
    1058             :                                     ARC_RD_D2I_DATA_WRITE_OK);
    1059             :                         }
    1060             : */
    1061           0 :                         if (reg & ARC_RD_I2D_MESSAGE_CMD_DONE) {
    1062           0 :                                 arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR,
    1063             :                                         ARC_RD_I2D_MSG_CMD_DONE_CLR);
    1064           0 :                                 obmsg = arc_read(sc, ARC_RD_MSG_RWBUF);
    1065             :                                 if (obmsg == ARC_FWINFO_SIGNATURE_GET_CONFIG)
    1066             :                                         ;       /* handle devices hot-plug */
    1067           0 :                         }
    1068             :                         
    1069             :                 }
    1070             :         }
    1071             : 
    1072           0 :         if (intrstat & ARC_RD_INTR_STAT_POSTQUEUE) {
    1073             :                 ret = 1;
    1074           0 :                 arc_write(sc, ARC_RD_OUTB_INTR_CAUSE, ARC_RD_OUTB_LIST_INT_CLR);
    1075           0 :                 bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
    1076             :                     sc->cmdQ_ptr_offset, ARC_MAX_CMDQ_PTR_LEN,
    1077             :                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    1078           0 :                 pmu = sc->pmu;
    1079           0 :                 ob_write_ptr = pmu->done_qbuffer[0].addressLow;
    1080           0 :                 doneq_index = pmu->doneq_index;
    1081           0 :                 while ((doneq_index & 0xFF) != (ob_write_ptr & 0xFF)) {
    1082           0 :                         doneq_index = arcmsr_get_doneq_index(pmu);
    1083           0 :                         reg = pmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
    1084           0 :                         cmd = (struct arc_io_cmd *)(kva + ((reg & 0xFFFFFFF0) -
    1085           0 :                         (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
    1086           0 :                         ccb = cmd->ccb;
    1087           0 :                         bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
    1088             :                                 ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
    1089             :                                 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    1090           0 :                         error = (reg & ARC_RD_REPLY_QUEUE_ERR);
    1091           0 :                         arc_scsi_cmd_done(sc, ccb, error);
    1092           0 :                         arc_write(sc, ARC_RD_OUTB_READ_PTR, doneq_index);
    1093           0 :                         ob_write_ptr = pmu->done_qbuffer[0].addressLow;
    1094             :                 }
    1095             :         }
    1096             : 
    1097           0 :         return (ret);
    1098           0 : }
    1099             : 
    1100             : int
    1101           0 : arc_intr(void *arg)
    1102             : {
    1103           0 :         struct arc_softc        *sc = arg;
    1104             :         int             ret = 0;
    1105             : 
    1106           0 :         switch(sc->sc_adp_type) {
    1107             :         case ARC_HBA_TYPE_A:
    1108           0 :                 ret = arc_intr_A(arg);
    1109           0 :                 break;
    1110             :         case ARC_HBA_TYPE_C:
    1111           0 :                 ret = arc_intr_C(arg);
    1112           0 :                 break;
    1113             :         case ARC_HBA_TYPE_D:
    1114           0 :                 ret = arc_intr_D(arg);
    1115           0 :                 break;
    1116             :         }
    1117           0 :         return (ret);
    1118             : }
    1119             : 
    1120             : void
    1121           0 : arc_scsi_cmd(struct scsi_xfer *xs)
    1122             : {
    1123           0 :         struct scsi_link                *link = xs->sc_link;
    1124           0 :         struct arc_softc                *sc = link->adapter_softc;
    1125             :         struct arc_ccb                  *ccb;
    1126             :         struct arc_msg_scsicmd          *cmd;
    1127             :         u_int32_t                       reg, cdb_len;
    1128             :         int                             s;
    1129             :         struct arc_HBD_Msgu *pmu;
    1130             :         u_int16_t index_stripped;
    1131             :         u_int16_t postq_index;
    1132             :         struct InBound_SRB *pinbound_srb;
    1133             : 
    1134           0 :         if (xs->cmdlen > ARC_MSG_CDBLEN) {
    1135           0 :                 bzero(&xs->sense, sizeof(xs->sense));
    1136           0 :                 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
    1137           0 :                 xs->sense.flags = SKEY_ILLEGAL_REQUEST;
    1138           0 :                 xs->sense.add_sense_code = 0x20;
    1139           0 :                 xs->error = XS_SENSE;
    1140           0 :                 scsi_done(xs);
    1141           0 :                 return;
    1142             :         }
    1143             : 
    1144           0 :         ccb = xs->io;
    1145           0 :         ccb->ccb_xs = xs;
    1146             : 
    1147           0 :         if (arc_load_xs(ccb) != 0) {
    1148           0 :                 xs->error = XS_DRIVER_STUFFUP;
    1149           0 :                 scsi_done(xs);
    1150           0 :                 return;
    1151             :         }
    1152             : 
    1153           0 :         cmd = &ccb->ccb_cmd->cmd;
    1154           0 :         reg = ccb->ccb_cmd_post;
    1155           0 :         ccb->ccb_cmd->ccb = ccb;
    1156             :         /* bus is always 0 */
    1157           0 :         cmd->target = link->target;
    1158           0 :         cmd->lun = link->lun;
    1159           0 :         cmd->function = 1; /* XXX magic number */
    1160             : 
    1161           0 :         cmd->cdb_len = xs->cmdlen;
    1162           0 :         cmd->sgl_len = ccb->ccb_dmamap->dm_nsegs;
    1163           0 :         if (xs->flags & SCSI_DATA_OUT)
    1164           0 :                 cmd->flags = ARC_MSG_SCSICMD_FLAG_WRITE;
    1165           0 :         if (ccb->ccb_dmamap->dm_nsegs > ARC_SGL_256LEN) {
    1166           0 :                 cmd->flags |= ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512;
    1167             : /*              reg |= ARC_RA_POST_QUEUE_BIGFRAME; */
    1168           0 :         }
    1169             : 
    1170           0 :         cmd->data_len = htole32(xs->datalen);
    1171             : 
    1172           0 :         bcopy(xs->cmd, cmd->cdb, xs->cmdlen);
    1173             : 
    1174             :         /* we've built the command, let's put it on the hw */
    1175           0 :         bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
    1176             :             ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
    1177             :             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    1178             : 
    1179           0 :         s = splbio();
    1180           0 :         switch(sc->sc_adp_type) {
    1181             :         case ARC_HBA_TYPE_A:
    1182           0 :                 if (cmd->flags & ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512)
    1183           0 :                         reg |= ARC_RA_POST_QUEUE_BIGFRAME;
    1184           0 :                 arc_write(sc, ARC_RA_POST_QUEUE, reg);
    1185           0 :                 break;
    1186             :         case ARC_HBA_TYPE_C:
    1187           0 :                 cdb_len = sizeof(struct arc_msg_scsicmd) +
    1188           0 :                         sizeof(struct arc_sge) * ccb->ccb_dmamap->dm_nsegs;
    1189           0 :                 if (cdb_len > 0x300)
    1190             :                         cdb_len = 0x300;
    1191           0 :                 reg = reg | ((cdb_len - 1) >> 6) | 1;
    1192           0 :                 if (sc->sc_ccb_phys_hi)
    1193           0 :                         arc_write(sc, ARC_RC_INB_POSTQ_HIGH, sc->sc_ccb_phys_hi);
    1194           0 :                 arc_write(sc, ARC_RC_INB_POSTQ_LOW, reg);
    1195           0 :                 break;
    1196             :         case ARC_HBA_TYPE_D:
    1197           0 :                         pmu = sc->pmu;
    1198           0 :                         postq_index = pmu->postq_index;
    1199           0 :                         pinbound_srb = (struct InBound_SRB *)&pmu->post_qbuffer[postq_index & 0xFF];
    1200             : 
    1201           0 :                         pinbound_srb->addressHigh = sc->sc_ccb_phys_hi;
    1202           0 :                         pinbound_srb->addressLow = ccb->ccb_cmd_post;
    1203           0 :                         pinbound_srb->length = ccb->arc_io_cmd_length >> 2;
    1204           0 :                         cmd->context = ccb->ccb_cmd_post;
    1205           0 :                         if (postq_index & 0x4000) {
    1206           0 :                                 index_stripped = postq_index & 0xFF;
    1207           0 :                                 index_stripped += 1;
    1208           0 :                                 index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
    1209           0 :                                 pmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped;
    1210           0 :                         } else {
    1211             :                                 index_stripped = postq_index;
    1212           0 :                                 index_stripped += 1;
    1213           0 :                                 index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
    1214           0 :                                 pmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000);
    1215             :                         }
    1216           0 :                         bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
    1217             :                             sc->cmdQ_ptr_offset, ARC_MAX_CMDQ_PTR_LEN,
    1218             :                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    1219           0 :                         arc_write(sc, ARC_RD_INB_WRITE_PTR, postq_index);
    1220           0 :                 break;
    1221             :         }
    1222           0 :         if (xs->flags & SCSI_POLL) {
    1223           0 :                 if (arc_complete(sc, ccb, xs->timeout) != 0) {
    1224           0 :                         xs->error = XS_DRIVER_STUFFUP;
    1225           0 :                         scsi_done(xs);
    1226           0 :                 }
    1227             :         }
    1228           0 :         splx(s);
    1229           0 : }
    1230             : 
    1231             : int
    1232           0 : arc_load_xs(struct arc_ccb *ccb)
    1233             : {
    1234           0 :         struct arc_softc                *sc = ccb->ccb_sc;
    1235           0 :         struct scsi_xfer                *xs = ccb->ccb_xs;
    1236           0 :         bus_dmamap_t                    dmap = ccb->ccb_dmamap;
    1237           0 :         struct arc_sge                  *sgl = ccb->ccb_cmd->sgl, *sge;
    1238             :         u_int64_t                       addr;
    1239             :         int                             i, error;
    1240             :         u_int32_t       msg_length;
    1241             : 
    1242           0 :         if (xs->datalen == 0)
    1243             :         {
    1244           0 :                 ccb->arc_io_cmd_length = sizeof(struct arc_msg_scsicmd);
    1245           0 :                 ccb->ccb_cmd->cmd.msgPages = 1;
    1246           0 :                 return (0);
    1247             :         }
    1248           0 :         error = bus_dmamap_load(sc->sc_dmat, dmap,
    1249             :             xs->data, xs->datalen, NULL,
    1250             :             (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
    1251           0 :         if (error != 0) {
    1252           0 :                 printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
    1253           0 :                 return (1);
    1254             :         }
    1255             : 
    1256           0 :         for (i = 0; i < dmap->dm_nsegs; i++) {
    1257           0 :                 sge = &sgl[i];
    1258             : 
    1259           0 :                 sge->sg_length = htole32(ARC_SGE_64BIT | dmap->dm_segs[i].ds_len);
    1260           0 :                 addr = dmap->dm_segs[i].ds_addr;
    1261           0 :                 sge->sg_hi_addr = htole32((u_int32_t)(addr >> 32));
    1262           0 :                 sge->sg_lo_addr = htole32((u_int32_t)addr);
    1263             :         }
    1264           0 :         ccb->arc_io_cmd_length = sizeof(struct arc_msg_scsicmd) + 
    1265           0 :             sizeof(struct arc_sge) * dmap->dm_nsegs;
    1266             :         msg_length = ccb->arc_io_cmd_length;
    1267           0 :         ccb->ccb_cmd->cmd.msgPages = (msg_length/256) + ((msg_length % 256) ? 1 : 0);
    1268             : 
    1269           0 :         bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
    1270             :             (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
    1271             :             BUS_DMASYNC_PREWRITE);
    1272             : 
    1273           0 :         return (0);
    1274           0 : }
    1275             : 
    1276             : void
    1277           0 : arc_scsi_cmd_done(struct arc_softc *sc, struct arc_ccb *ccb, u_int32_t error)
    1278             : {
    1279           0 :         struct scsi_xfer                *xs = ccb->ccb_xs;
    1280             :         struct arc_msg_scsicmd          *cmd;
    1281             : 
    1282           0 :         if (xs->datalen != 0) {
    1283           0 :                 bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
    1284             :                     ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
    1285             :                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
    1286           0 :                 bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
    1287           0 :         }
    1288             : 
    1289           0 :         if (error) {
    1290           0 :                 cmd = &ccb->ccb_cmd->cmd;
    1291             :                 DPRINTF("%s: arc_scsi_cmd_done error! target 0x%x, lun 0x%x, "
    1292             :                         "status = 0x%x\n", DEVNAME(sc), cmd->target, cmd->lun,
    1293             :                         cmd->status);
    1294             :                 DPRINTF("%s: scsi cdb: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x"
    1295             :                         ", 0x%x, 0x%x, 0x%x\n", DEVNAME(sc), cmd->cdb[0], cmd->cdb[1],
    1296             :                         cmd->cdb[2], cmd->cdb[3],cmd->cdb[4], cmd->cdb[5],
    1297             :                         cmd->cdb[6], cmd->cdb[7],cmd->cdb[8], cmd->cdb[9]);
    1298             : 
    1299           0 :                 switch (cmd->status) {
    1300             :                 case ARC_MSG_STATUS_SELTIMEOUT:
    1301             :                 case ARC_MSG_STATUS_ABORTED:
    1302             :                 case ARC_MSG_STATUS_INIT_FAIL:
    1303           0 :                         xs->status = SCSI_OK;
    1304           0 :                         xs->error = XS_SELTIMEOUT;
    1305           0 :                         break;
    1306             : 
    1307             :                 case SCSI_CHECK:
    1308           0 :                         bzero(&xs->sense, sizeof(xs->sense));
    1309           0 :                         bcopy(cmd->sense_data, &xs->sense,
    1310           0 :                             min(ARC_MSG_SENSELEN, sizeof(xs->sense)));
    1311           0 :                         xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
    1312           0 :                         xs->status = SCSI_CHECK;
    1313           0 :                         xs->error = XS_SENSE;
    1314           0 :                         xs->resid = 0;
    1315           0 :                         break;
    1316             : 
    1317             :                 default:
    1318             :                         /* unknown device status */
    1319           0 :                         xs->error = XS_BUSY; /* try again later? */
    1320           0 :                         xs->status = SCSI_BUSY;
    1321           0 :                         break;
    1322             :                 }
    1323             :         } else {
    1324           0 :                 xs->status = SCSI_OK;
    1325           0 :                 xs->error = XS_NOERROR;
    1326           0 :                 xs->resid = 0;
    1327             :         }
    1328             : 
    1329           0 :         scsi_done(xs);
    1330           0 : }
    1331             : 
    1332             : int
    1333           0 : arc_complete(struct arc_softc *sc, struct arc_ccb *nccb, int timeout)
    1334             : {
    1335             :         struct arc_ccb                  *ccb = NULL;
    1336           0 :         char                            *kva = ARC_DMA_KVA(sc->sc_requests);
    1337             :         struct arc_io_cmd               *cmd;
    1338             :         u_int32_t                       reg, error, write_ptr;
    1339             :         u_int16_t       doneq_index;
    1340             :         struct arc_HBD_Msgu *phbdmu;
    1341             :         int             ret = 0;
    1342             :         
    1343           0 :         arc_disable_all_intr(sc);
    1344           0 :         do {
    1345           0 :                 switch(sc->sc_adp_type) {
    1346             :                 case ARC_HBA_TYPE_A:
    1347           0 :                         reg = arc_read(sc, ARC_RA_REPLY_QUEUE);
    1348           0 :                         error = (reg & ARC_RA_REPLY_QUEUE_ERR)? 1:0;
    1349           0 :                         break;
    1350             :                 case ARC_HBA_TYPE_C:
    1351           0 :                         reg = arc_read(sc, ARC_RC_OUTB_REPLYQ_LOW);
    1352           0 :                         error = (reg & ARC_RC_REPLY_QUEUE_ERR);
    1353           0 :                         break;
    1354             :                 case ARC_HBA_TYPE_D:
    1355           0 :                         phbdmu = sc->pmu;
    1356           0 :                         write_ptr = phbdmu->done_qbuffer[0].addressLow;
    1357           0 :                         doneq_index = phbdmu->doneq_index;
    1358           0 :                         if((write_ptr & 0xff) == (doneq_index & 0xff)) {
    1359             : Loop0:
    1360             :                                 reg = 0xffffffff;
    1361           0 :                         }       
    1362             :                         else {
    1363           0 :                                 doneq_index = arcmsr_get_doneq_index(phbdmu);
    1364           0 :                                 reg = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
    1365           0 :                                 if (reg == 0)
    1366             :                                         goto Loop0;
    1367           0 :                                 arc_write(sc, ARC_RD_OUTB_READ_PTR, doneq_index);
    1368             :                         }
    1369           0 :                         error = (reg & ARC_RD_REPLY_QUEUE_ERR);
    1370           0 :                         break;
    1371             :                 }
    1372           0 :                 if (reg == 0xffffffff) {
    1373           0 :                         if (timeout-- == 0) {
    1374           0 :                                 return (1);
    1375             :                         }
    1376           0 :                         delay(1000);
    1377           0 :                         continue;
    1378             :                 }
    1379             : 
    1380           0 :                 switch(sc->sc_adp_type) {
    1381             :                 case ARC_HBA_TYPE_A:
    1382           0 :                         cmd = (struct arc_io_cmd *)(kva +
    1383           0 :                         ((reg << ARC_RA_REPLY_QUEUE_ADDR_SHIFT) -
    1384           0 :                         ARC_DMA_DVA(sc->sc_requests)));
    1385           0 :                     break;
    1386             :                 case ARC_HBA_TYPE_C:
    1387             :                 case ARC_HBA_TYPE_D:
    1388           0 :                         cmd = (struct arc_io_cmd *)(kva + ((reg & 0xFFFFFFE0) -
    1389           0 :                         ARC_DMA_DVA(sc->sc_requests)));
    1390           0 :                     break;
    1391             :                 }
    1392           0 :                 ccb = cmd->ccb;
    1393             : 
    1394           0 :                 bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
    1395             :                     ccb->cmd_dma_offset, ARC_MAX_IOCMDLEN,
    1396             :                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    1397             : 
    1398           0 :                 arc_scsi_cmd_done(sc, ccb, error);
    1399             :                         
    1400           0 :         } while (nccb != ccb);
    1401           0 :         arc_enable_all_intr(sc);
    1402             : 
    1403           0 :         return (ret);
    1404           0 : }
    1405             : 
    1406             : void
    1407           0 : arc_minphys(struct buf *bp, struct scsi_link *sl)
    1408             : {
    1409           0 :         if (bp->b_bcount > MAXPHYS)
    1410           0 :                 bp->b_bcount = MAXPHYS;
    1411           0 :         minphys(bp);
    1412           0 : }
    1413             : 
    1414             : void
    1415           0 : arc_enable_all_intr(struct arc_softc *sc)
    1416             : {
    1417             :         u_int32_t int_mask;
    1418             : 
    1419           0 :         switch(sc->sc_adp_type) {
    1420             :         case ARC_HBA_TYPE_A:
    1421           0 :                 int_mask = arc_read(sc, ARC_RA_INTRMASK);
    1422           0 :                 int_mask &= ~(ARC_RA_INTRMASK_POSTQUEUE |
    1423             :                         ARC_RA_INTRMASK_DOORBELL | ARC_RA_INTRMASK_MSG0);
    1424           0 :                 arc_write(sc, ARC_RA_INTRMASK, int_mask);
    1425           0 :             break;
    1426             :         case ARC_HBA_TYPE_C:
    1427           0 :                 int_mask = arc_read(sc, ARC_RC_INTR_MASK);
    1428           0 :                 int_mask &= ~(ARC_RC_INTR_MASK_POSTQUEUE |
    1429             :                         ARC_RC_INTR_MASK_DOORBELL | ARC_RC_INTR_MASK_UTILITY_A);
    1430           0 :                 arc_write(sc, ARC_RC_INTR_MASK, int_mask);
    1431           0 :             break;
    1432             :         case ARC_HBA_TYPE_D:
    1433           0 :                 int_mask = arc_read(sc, ARC_RD_INTR_ENABLE);
    1434           0 :                 int_mask |= ARC_RD_INTR_ENABLE_ALL;
    1435           0 :                 arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
    1436           0 :             break;
    1437             :         }
    1438           0 : }
    1439             : 
    1440             : void
    1441           0 : arc_disable_all_intr(struct arc_softc *sc)
    1442             : {
    1443             :         u_int32_t int_mask;
    1444             : 
    1445           0 :         switch(sc->sc_adp_type) {
    1446             :         case ARC_HBA_TYPE_A:
    1447           0 :                 int_mask = arc_read(sc, ARC_RA_INTRMASK);
    1448           0 :                 int_mask |= ARC_RA_INTR_MASK_ALL;
    1449           0 :                 arc_write(sc, ARC_RA_INTRMASK, int_mask);
    1450           0 :                 break;
    1451             :         case ARC_HBA_TYPE_C:
    1452           0 :                 int_mask = arc_read(sc, ARC_RC_INTR_MASK);
    1453           0 :                 int_mask |= ARC_RC_INTR_MASK_ALL;
    1454           0 :                 arc_write(sc, ARC_RC_INTR_MASK, int_mask);
    1455           0 :                 break;
    1456             :         case ARC_HBA_TYPE_D:
    1457           0 :                 int_mask = arc_read(sc, ARC_RD_INTR_ENABLE);
    1458             :                 int_mask &= ~ARC_RD_INTR_ENABLE_ALL;
    1459           0 :                 arc_write(sc, ARC_RD_INTR_ENABLE, ARC_RD_INTR_DISABLE_ALL);
    1460           0 :                 break;
    1461             :         }
    1462           0 : }
    1463             : 
    1464             : int
    1465           0 : arc_map_pci_resources(struct arc_softc *sc, struct pci_attach_args *pa)
    1466             : {
    1467             :         pcireg_t                        memtype;
    1468           0 :         pci_intr_handle_t               ih;
    1469             : 
    1470           0 :         sc->sc_pc = pa->pa_pc;
    1471           0 :         sc->sc_tag = pa->pa_tag;
    1472           0 :         sc->sc_dmat = pa->pa_dmat;
    1473             : 
    1474           0 :         switch(sc->sc_adp_type) {
    1475             :                 case ARC_HBA_TYPE_A:
    1476           0 :                 memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, ARC_RA_PCI_BAR);
    1477           0 :                 if (pci_mapreg_map(pa, ARC_RA_PCI_BAR, memtype, 0, &sc->sc_iot,
    1478           0 :                 &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
    1479           0 :                         printf(": unable to map ARC_HBA_TYPE_A system"
    1480             :                                 " interface register\n");
    1481           0 :                         return(1);
    1482             :                 }
    1483             :                 break;
    1484             :                 case ARC_HBA_TYPE_C:
    1485           0 :                 memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, ARC_RC_PCI_BAR);
    1486           0 :                 if (pci_mapreg_map(pa, ARC_RC_PCI_BAR, memtype, 0, &sc->sc_iot,
    1487           0 :                 &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
    1488           0 :                         printf(": unable to map ARC_HBA_TYPE_C system"
    1489             :                                 " interface register\n");
    1490           0 :                         return(1);
    1491             :                 }
    1492             :                 break;
    1493             :                 case ARC_HBA_TYPE_D:
    1494           0 :                 memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, ARC_RD_PCI_BAR);
    1495           0 :                 if (pci_mapreg_map(pa, ARC_RD_PCI_BAR, memtype, 0, &sc->sc_iot,
    1496           0 :                 &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
    1497           0 :                         printf(": unable to map ARC_HBA_TYPE_D system"
    1498             :                                 " interface register\n");
    1499           0 :                         return(1);
    1500             :                 }
    1501             :                 break; 
    1502             :         }
    1503             : 
    1504           0 :         arc_disable_all_intr(sc);
    1505             : 
    1506           0 :         if (pci_intr_map(pa, &ih) != 0) {
    1507           0 :                 printf(": unable to map interrupt\n");
    1508           0 :                 goto unmap;
    1509             :         }
    1510           0 :         sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
    1511           0 :             arc_intr, sc, DEVNAME(sc));
    1512           0 :         if (sc->sc_ih == NULL) {
    1513           0 :                 printf(": unable to map interrupt\n");
    1514           0 :                 goto unmap;
    1515             :         }
    1516           0 :         printf(": %s\n", pci_intr_string(pa->pa_pc, ih));
    1517             : 
    1518           0 :         return (0);
    1519             : 
    1520             : unmap:
    1521           0 :         bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    1522           0 :         sc->sc_ios = 0;
    1523           0 :         return (1);
    1524           0 : }
    1525             : 
    1526             : void
    1527           0 : arc_unmap_pci_resources(struct arc_softc *sc)
    1528             : {
    1529           0 :         pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    1530           0 :         bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    1531           0 :         sc->sc_ios = 0;
    1532           0 : }
    1533             : 
    1534             : int
    1535           0 : arc_chipA_firmware(struct arc_softc *sc)
    1536             : {
    1537           0 :         struct arc_msg_firmware_info    fwinfo;
    1538           0 :         char                            string[81]; /* sizeof(vendor)*2+1 */
    1539             :         u_int32_t       ob_doorbell;
    1540             : 
    1541           0 :         if (arc_wait_eq(sc, ARC_RA_OUTB_ADDR1, ARC_RA_OUTB_ADDR1_FIRMWARE_OK,
    1542           0 :             ARC_RA_OUTB_ADDR1_FIRMWARE_OK) != 0) {
    1543           0 :                 printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
    1544           0 :                 return (1);
    1545             :         }
    1546             : 
    1547           0 :         if (arc_msg0(sc, ARC_RA_INB_MSG0_GET_CONFIG) != 0) {
    1548           0 :                 printf("%s: timeout waiting for get config\n", DEVNAME(sc));
    1549           0 :                 return (1);
    1550             :         }
    1551             : 
    1552           0 :         arc_read_region(sc, ARC_RA_MSGBUF, &fwinfo, sizeof(fwinfo));
    1553             : 
    1554             :         DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
    1555             :             letoh32(fwinfo.signature));
    1556             : 
    1557           0 :         if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
    1558           0 :                 printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
    1559           0 :                 return (1);
    1560             :         }
    1561             : 
    1562             :         DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
    1563             :             letoh32(fwinfo.request_len));
    1564             :         DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
    1565             :             letoh32(fwinfo.queue_len));
    1566             :         DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
    1567             :             letoh32(fwinfo.sdram_size));
    1568             :         DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
    1569             :             letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
    1570             : 
    1571           0 :         scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
    1572             :         DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
    1573           0 :         scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
    1574             :         DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
    1575             : 
    1576           0 :         scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
    1577             :         DNPRINTF(ARC_D_INIT, "%s: firmware: \"%s\"\n", DEVNAME(sc), string);
    1578             : 
    1579           0 :         if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
    1580           0 :                 printf("%s: unexpected request frame size (%d != %d)\n",
    1581           0 :                     DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
    1582           0 :                 return (1);
    1583             :         }
    1584             : 
    1585           0 :         sc->sc_req_count = letoh32(fwinfo.queue_len);
    1586             : 
    1587           0 :         if (arc_msg0(sc, ARC_RA_INB_MSG0_START_BGRB) != 0) {
    1588           0 :                 printf("%s: timeout waiting to start bg rebuild\n",
    1589           0 :                     DEVNAME(sc));
    1590           0 :                 return (1);
    1591             :         }
    1592             : 
    1593             :         /* clear doorbell buffer */
    1594           0 :         ob_doorbell = arc_read(sc, ARC_RA_OUTB_DOORBELL);
    1595           0 :         arc_write(sc, ARC_RA_OUTB_DOORBELL, ob_doorbell);
    1596           0 :         arc_write(sc, ARC_RA_INB_DOORBELL, ARC_RA_INB_DOORBELL_READ_OK);
    1597             : 
    1598           0 :         printf("%s: %d ports, %dMB SDRAM, firmware %s\n",
    1599           0 :             DEVNAME(sc), letoh32(fwinfo.sata_ports),
    1600           0 :             letoh32(fwinfo.sdram_size), string);
    1601             : 
    1602           0 :         return (0);
    1603           0 : }
    1604             : 
    1605             : int
    1606           0 : arc_chipB_firmware(struct arc_softc *sc)
    1607             : {
    1608           0 :         if (arc_wait_eq(sc, ARC_RB_IOP2DRV_DOORBELL,
    1609             :             ARC_RA_OUTB_ADDR1_FIRMWARE_OK,
    1610           0 :             ARC_RA_OUTB_ADDR1_FIRMWARE_OK) != 0) {
    1611           0 :                 printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
    1612           0 :                 return (1);
    1613             :         }
    1614             : 
    1615           0 :         return (1);
    1616           0 : }
    1617             : 
    1618             : int
    1619           0 : arc_chipC_firmware(struct arc_softc *sc)
    1620             : {
    1621           0 :         struct arc_msg_firmware_info    fwinfo;
    1622           0 :         char    string[81]; /* sizeof(vendor)*2+1 */
    1623             :         u_int32_t       ob_doorbell;
    1624             : 
    1625           0 :         if (arc_wait_eq(sc, ARC_RC_OUTB_MSGADDR1, ARC_RC_OUTB_MSG_FIRMWARE_OK,
    1626           0 :             ARC_RC_OUTB_MSG_FIRMWARE_OK) != 0) {
    1627           0 :                 printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
    1628           0 :                 return (1);
    1629             :         }
    1630             : 
    1631           0 :         if (arc_msg0(sc, ARC_RC_INB_MSG0_GET_CONFIG) != 0) {
    1632           0 :                 printf("%s: timeout waiting for get config\n", DEVNAME(sc));
    1633           0 :                 return (1);
    1634             :         }
    1635             : 
    1636           0 :         arc_read_region(sc, ARC_RC_MSG_RWBUF, &fwinfo, sizeof(fwinfo));
    1637             : 
    1638             :         DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
    1639             :             letoh32(fwinfo.signature));
    1640             : 
    1641           0 :         if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
    1642           0 :                 printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
    1643           0 :                 return (1);
    1644             :         }
    1645             : 
    1646             :         DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
    1647             :             letoh32(fwinfo.request_len));
    1648             :         DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
    1649             :             letoh32(fwinfo.queue_len));
    1650             :         DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
    1651             :             letoh32(fwinfo.sdram_size));
    1652             :         DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
    1653             :             letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
    1654             : 
    1655           0 :         scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
    1656             :         DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
    1657           0 :         scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
    1658             :         DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
    1659             : 
    1660           0 :         scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
    1661             :         DNPRINTF(ARC_D_INIT, "%s: firmware: \"%s\"\n", DEVNAME(sc), string);
    1662             : 
    1663           0 :         if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
    1664           0 :                 printf("%s: unexpected request frame size (%d != %d)\n",
    1665           0 :                     DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
    1666           0 :                 return (1);
    1667             :         }
    1668             : 
    1669           0 :         sc->sc_req_count = letoh32(fwinfo.queue_len);
    1670             : 
    1671           0 :         if (arc_msg0(sc, ARC_RC_INB_MSG0_START_BGRB) != 0) {
    1672           0 :                 printf("%s: timeout waiting to start bg rebuild\n",
    1673           0 :                     DEVNAME(sc));
    1674           0 :                 return (1);
    1675             :         }
    1676             : 
    1677             :         /* clear doorbell buffer */
    1678           0 :         ob_doorbell = arc_read(sc, ARC_RC_OUTB_DOORBELL);
    1679           0 :         arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, ob_doorbell);
    1680           0 :         arc_write(sc, ARC_RC_INB_DOORBELL, ARC_RC_D2I_DATA_READ_OK);
    1681             : 
    1682           0 :         printf("%s: %d ports, %dMB SDRAM, firmware %s\n",
    1683           0 :             DEVNAME(sc), letoh32(fwinfo.sata_ports),
    1684           0 :             letoh32(fwinfo.sdram_size), string);
    1685             : 
    1686           0 :         return (0);
    1687           0 : }
    1688             : 
    1689             : int
    1690           0 : arc_chipD_firmware(struct arc_softc *sc)
    1691             : {
    1692           0 :         struct arc_msg_firmware_info    fwinfo;
    1693           0 :         char    string[81]; /* sizeof(vendor)*2+1 */
    1694             :         u_int32_t       ob_doorbell;
    1695             : 
    1696           0 :         if (arc_wait_eq(sc, ARC_RD_OUTB_MSGADDR1, ARC_RD_OUTB_MSG_FIRMWARE_OK,
    1697           0 :             ARC_RD_OUTB_MSG_FIRMWARE_OK) != 0) {
    1698           0 :                 printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
    1699           0 :                 return (1);
    1700             :         }
    1701             : 
    1702           0 :         if ((arc_read(sc, ARC_RD_OUTB_DOORBELL) & ARC_RD_I2D_MESSAGE_CMD_DONE))
    1703           0 :                 arc_write(sc, ARC_RD_OUTB_DOORBELL, ARC_RD_I2D_MESSAGE_CMD_DONE_CLEAR);
    1704             : 
    1705           0 :         if (arc_msg0(sc, ARC_RD_INB_MSG0_GET_CONFIG) != 0) {
    1706           0 :                 printf("%s: timeout waiting for get config\n", DEVNAME(sc));
    1707           0 :                 return (1);
    1708             :         }
    1709             : 
    1710           0 :         arc_read_region(sc, ARC_RD_MSG_RWBUF, &fwinfo, sizeof(fwinfo));
    1711             : 
    1712             :         DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
    1713             :             letoh32(fwinfo.signature));
    1714             : 
    1715           0 :         if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
    1716           0 :                 printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
    1717           0 :                 return (1);
    1718             :         }
    1719             : 
    1720             :         DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
    1721             :             letoh32(fwinfo.request_len));
    1722             :         DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
    1723             :             letoh32(fwinfo.queue_len));
    1724             :         DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
    1725             :             letoh32(fwinfo.sdram_size));
    1726             :         DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
    1727             :             letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
    1728             : 
    1729           0 :         scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
    1730             :         DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
    1731           0 :         scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
    1732             :         DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
    1733             : 
    1734           0 :         scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
    1735             :         DNPRINTF(ARC_D_INIT, "%s: firmware: \"%s\"\n", DEVNAME(sc), string);
    1736             : 
    1737           0 :         if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
    1738           0 :                 printf("%s: unexpected request frame size (%d != %d)\n",
    1739           0 :                     DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
    1740           0 :                 return (1);
    1741             :         }
    1742             : 
    1743           0 :         sc->sc_req_count = letoh32(fwinfo.queue_len) - 1;
    1744             : 
    1745           0 :         if (arc_msg0(sc, ARC_RD_INB_MSG0_START_BGRB) != 0) {
    1746           0 :                 printf("%s: timeout waiting to start bg rebuild\n",
    1747           0 :                     DEVNAME(sc));
    1748           0 :                 return (1);
    1749             :         }
    1750             : 
    1751             :         /* clear doorbell buffer */
    1752           0 :         ob_doorbell = arc_read(sc, ARC_RD_OUTB_DOORBELL);
    1753           0 :         arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR, ob_doorbell);
    1754           0 :         arc_write(sc, ARC_RD_INB_DOORBELL, ARC_RD_D2I_DATA_READ_OK);
    1755             : 
    1756           0 :         printf("%s: %d ports, %dMB SDRAM, firmware %s\n",
    1757           0 :             DEVNAME(sc), letoh32(fwinfo.sata_ports),
    1758           0 :             letoh32(fwinfo.sdram_size), string);
    1759             : 
    1760           0 :         return (0);
    1761           0 : }
    1762             : 
    1763             : void
    1764           0 : arc_stop_bgrb_proc(struct arc_softc *sc)
    1765             : {
    1766           0 :         switch(sc->sc_adp_type) {
    1767             :         case ARC_HBA_TYPE_A:
    1768           0 :                 if (arc_msg0(sc, ARC_RA_INB_MSG0_STOP_BGRB) != 0)
    1769           0 :                         printf("%s: timeout waiting to stop bg rebuild\n",
    1770           0 :                                 DEVNAME(sc));
    1771             :                 break;
    1772             :         case ARC_HBA_TYPE_C:
    1773           0 :                 if (arc_msg0(sc, ARC_RC_INB_MSG0_STOP_BGRB) != 0)
    1774           0 :                         printf("%s: timeout waiting to stop bg rebuild\n",
    1775           0 :                                 DEVNAME(sc));
    1776             :                 break;
    1777             :         case ARC_HBA_TYPE_D:
    1778           0 :                 if (arc_msg0(sc, ARC_RD_INB_MSG0_STOP_BGRB) != 0)
    1779           0 :                         printf("%s: timeout waiting to stop bg rebuild\n",
    1780           0 :                                 DEVNAME(sc));
    1781             :                 break;
    1782             :         }
    1783           0 : }
    1784             : 
    1785             : void
    1786           0 : arc_flush_cache(struct arc_softc *sc)
    1787             : {
    1788           0 :         switch(sc->sc_adp_type) {
    1789             :         case ARC_HBA_TYPE_A:
    1790           0 :                 if (arc_msg0(sc, ARC_RA_INB_MSG0_FLUSH_CACHE) != 0)
    1791           0 :                         printf("%s: timeout waiting to flush cache\n",
    1792           0 :                                 DEVNAME(sc));
    1793             :                 break;
    1794             :         case ARC_HBA_TYPE_C:
    1795           0 :                 if (arc_msg0(sc, ARC_RC_INB_MSG0_FLUSH_CACHE) != 0)
    1796           0 :                         printf("%s: timeout waiting to flush cache\n",
    1797           0 :                                 DEVNAME(sc));
    1798             :                 break;
    1799             :         case ARC_HBA_TYPE_D:
    1800           0 :                 if (arc_msg0(sc, ARC_RD_INB_MSG0_FLUSH_CACHE) != 0)
    1801           0 :                         printf("%s: timeout waiting to flush cache\n",
    1802           0 :                                 DEVNAME(sc));
    1803             :                 break;
    1804             :         }
    1805           0 : }
    1806             : 
    1807             : void
    1808           0 : arc_iop_set_conf(struct arc_softc *sc)
    1809             : {
    1810             :         u_int32_t ccb_phys_hi;
    1811             :         struct arc_HBD_Msgu *phbdmu;
    1812             : 
    1813           0 :         ccb_phys_hi = sc->sc_ccb_phys_hi;
    1814           0 :         switch (sc->sc_adp_type) {
    1815             :         case ARC_HBA_TYPE_A:
    1816           0 :                 arc_write(sc, ARC_RA_MSGBUF, ARC_FWINFO_SIGNATURE_SET_CONFIG);
    1817           0 :                 arc_write(sc, ARC_RA_MSGBUF+1, ccb_phys_hi);
    1818           0 :                 arc_msg0(sc, ARC_RA_INB_MSG0_SET_CONFIG);
    1819           0 :                 break;
    1820             :         case ARC_HBA_TYPE_C:
    1821           0 :                 arc_write(sc, ARC_RC_MSG_RWBUF, ARC_FWINFO_SIGNATURE_SET_CONFIG);
    1822           0 :                 arc_write(sc, ARC_RC_MSG_RWBUF+1, ccb_phys_hi);
    1823           0 :                 arc_msg0(sc, ARC_RC_INB_MSG0_SET_CONFIG);
    1824           0 :                 break;
    1825             :         case ARC_HBA_TYPE_D:
    1826           0 :                 phbdmu = sc->pmu;
    1827           0 :                 phbdmu->postq_index = 0;
    1828           0 :                 phbdmu->doneq_index = 0x40FF;
    1829           0 :                 arc_write(sc, ARC_RD_MSG_RWBUF, ARC_FWINFO_SIGNATURE_SET_CONFIG);
    1830           0 :                 arc_write(sc, ARC_RD_MSG_RWBUF+4, ccb_phys_hi);
    1831           0 :                 arc_write(sc, ARC_RD_MSG_RWBUF+8, sc->postQ_buffer);
    1832           0 :                 arc_write(sc, ARC_RD_MSG_RWBUF+12, sc->doneQ_buffer);
    1833           0 :                 arc_write(sc, ARC_RD_MSG_RWBUF+16, 0x100);
    1834           0 :                 arc_msg0(sc, ARC_RD_INB_MSG0_SET_CONFIG);
    1835           0 :                 break;
    1836             :         }
    1837           0 : }
    1838             : 
    1839             : #if NBIO > 0
    1840             : int
    1841           0 : arc_bioctl(struct device *self, u_long cmd, caddr_t addr)
    1842             : {
    1843           0 :         struct arc_softc                *sc = (struct arc_softc *)self;
    1844             :         int                             error = 0;
    1845             : 
    1846             :         DPRINTF("%s: arc_bioctl\n", DEVNAME(sc));
    1847           0 :         switch (cmd) {
    1848             :         case BIOCINQ:
    1849           0 :                 error = arc_bio_inq(sc, (struct bioc_inq *)addr);
    1850           0 :                 break;
    1851             : 
    1852             :         case BIOCVOL:
    1853           0 :                 error = arc_bio_vol(sc, (struct bioc_vol *)addr);
    1854           0 :                 break;
    1855             : 
    1856             :         case BIOCDISK:
    1857           0 :                 error = arc_bio_disk(sc, (struct bioc_disk *)addr);
    1858           0 :                 break;
    1859             : 
    1860             :         case BIOCALARM:
    1861           0 :                 error = arc_bio_alarm(sc, (struct bioc_alarm *)addr);
    1862           0 :                 break;
    1863             : 
    1864             :         case BIOCBLINK:
    1865           0 :                 error = arc_bio_blink(sc, (struct bioc_blink *)addr);
    1866           0 :                 break;
    1867             : 
    1868             :         default:
    1869             :                 error = ENOTTY;
    1870           0 :                 break;
    1871             :         }
    1872             : 
    1873           0 :         return (error);
    1874             : }
    1875             : 
    1876             : int
    1877           0 : arc_bio_alarm(struct arc_softc *sc, struct bioc_alarm *ba)
    1878             : {
    1879           0 :         u_int8_t                        request[2];
    1880           0 :         u_int8_t                        reply[1];
    1881             :         size_t                          len;
    1882             :         int                             error = 0;
    1883             : 
    1884             :         DPRINTF("%s: arc_bio_alarm\n", DEVNAME(sc));
    1885           0 :         switch (ba->ba_opcode) {
    1886             :         case BIOC_SAENABLE:
    1887             :         case BIOC_SADISABLE:
    1888           0 :                 request[0] = ARC_FW_SET_ALARM;
    1889           0 :                 request[1] = (ba->ba_opcode == BIOC_SAENABLE) ?
    1890             :                     ARC_FW_SET_ALARM_ENABLE : ARC_FW_SET_ALARM_DISABLE;
    1891             :                 len = sizeof(request);
    1892             : 
    1893           0 :                 break;
    1894             : 
    1895             :         case BIOC_SASILENCE:
    1896           0 :                 request[0] = ARC_FW_MUTE_ALARM;
    1897             :                 len = 1;
    1898             : 
    1899           0 :                 break;
    1900             : 
    1901             :         case BIOC_GASTATUS:
    1902             :                 /* system info is too big/ugly to deal with here */
    1903           0 :                 return (arc_bio_alarm_state(sc, ba));
    1904             : 
    1905             :         default:
    1906           0 :                 return (EOPNOTSUPP);
    1907             :         }
    1908             : 
    1909           0 :         arc_lock(sc);
    1910           0 :         error = arc_msgbuf(sc, request, len, reply, sizeof(reply), 0);
    1911           0 :         arc_unlock(sc);
    1912             : 
    1913           0 :         if (error != 0)
    1914           0 :                 return (error);
    1915             : 
    1916           0 :         switch (reply[0]) {
    1917             :         case ARC_FW_CMD_OK:
    1918           0 :                 return (0);
    1919             :         case ARC_FW_CMD_PASS_REQD:
    1920           0 :                 return (EPERM);
    1921             :         default:
    1922           0 :                 return (EIO);
    1923             :         }
    1924           0 : }
    1925             : 
    1926             : int
    1927           0 : arc_bio_alarm_state(struct arc_softc *sc, struct bioc_alarm *ba)
    1928             : {
    1929           0 :         u_int8_t                        request = ARC_FW_SYSINFO;
    1930             :         struct arc_fw_sysinfo           *sysinfo;
    1931             :         int                             error = 0;
    1932             : 
    1933           0 :         sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
    1934             : 
    1935           0 :         request = ARC_FW_SYSINFO;
    1936             : 
    1937           0 :         arc_lock(sc);
    1938           0 :         error = arc_msgbuf(sc, &request, sizeof(request),
    1939             :             sysinfo, sizeof(struct arc_fw_sysinfo), 0);
    1940           0 :         arc_unlock(sc);
    1941             : 
    1942           0 :         if (error != 0)
    1943             :                 goto out;
    1944             : 
    1945           0 :         ba->ba_status = sysinfo->alarm;
    1946             : 
    1947             : out:
    1948           0 :         free(sysinfo, M_TEMP, sizeof *sysinfo);
    1949           0 :         return (error);
    1950           0 : }
    1951             : 
    1952             : 
    1953             : int
    1954           0 : arc_bio_inq(struct arc_softc *sc, struct bioc_inq *bi)
    1955             : {
    1956           0 :         u_int8_t                        request[2];
    1957             :         struct arc_fw_sysinfo           *sysinfo;
    1958             :         struct arc_fw_volinfo           *volinfo;
    1959             :         int                             maxvols, nvols = 0, i;
    1960             :         int                             error = 0;
    1961           0 :         char    string[20];
    1962             : 
    1963             :         DPRINTF("%s: arc_bio_inq\n", DEVNAME(sc));
    1964           0 :         sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
    1965           0 :         volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
    1966             : 
    1967           0 :         arc_lock(sc);
    1968             : 
    1969           0 :         request[0] = ARC_FW_SYSINFO;
    1970           0 :         error = arc_msgbuf(sc, request, 1, sysinfo,
    1971             :             sizeof(struct arc_fw_sysinfo), 0);
    1972           0 :         if (error != 0) {
    1973             :                 DPRINTF("%s: arc_bio_inq get sysinfo failed!\n", DEVNAME(sc));
    1974             :                 goto out;
    1975             :         }
    1976             : 
    1977           0 :         maxvols = sysinfo->max_volume_set;
    1978             : 
    1979           0 :         request[0] = ARC_FW_VOLINFO;
    1980           0 :         for (i = 0; i < maxvols; i++) {
    1981           0 :                 request[1] = i;
    1982           0 :                 error = arc_msgbuf(sc, request, sizeof(request), volinfo,
    1983             :                     sizeof(struct arc_fw_volinfo), 0);
    1984           0 :                 if (error != 0) {
    1985             :                         DPRINTF("%s: arc_bio_inq get volinfo failed!\n", DEVNAME(sc));
    1986             :                         goto out;
    1987             :                 }
    1988             : 
    1989             :                 /*
    1990             :                  * I can't find an easy way to see if the volume exists or not
    1991             :                  * except to say that if it has no capacity then it isn't there.
    1992             :                  * Ignore passthru volumes, bioc_vol doesn't understand them.
    1993             :                  */
    1994           0 :                 if ((volinfo->capacity != 0 || volinfo->capacity2 != 0) &&
    1995           0 :                     volinfo->raid_level != ARC_FW_VOL_RAIDLEVEL_PASSTHRU) {
    1996           0 :                         nvols++;
    1997           0 :                         scsi_strvis(string, volinfo->set_name, 16);
    1998             :                         DPRINTF("%s: volume set: \"%s\"\n", DEVNAME(sc), string);
    1999           0 :                 }
    2000             :         }
    2001             : 
    2002           0 :         strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
    2003           0 :         bi->bi_novol = nvols;
    2004             :         DPRINTF("%s: volume set number = %d\n", DEVNAME(sc), nvols);
    2005             : out:
    2006           0 :         arc_unlock(sc);
    2007           0 :         free(volinfo, M_TEMP, sizeof *volinfo);
    2008           0 :         free(sysinfo, M_TEMP, sizeof *sysinfo);
    2009           0 :         return (error);
    2010           0 : }
    2011             : 
    2012             : int
    2013           0 : arc_bio_blink(struct arc_softc *sc, struct bioc_blink *blink)
    2014             : {
    2015           0 :         u_int8_t                         request[6];
    2016           0 :         u_int32_t                        mask;
    2017             :         int                              error = 0;
    2018             : 
    2019             :         DPRINTF("%s: arc_bio_blink\n", DEVNAME(sc));
    2020           0 :         request[0] = ARC_FW_BLINK;
    2021           0 :         request[1] = ARC_FW_BLINK_ENABLE;
    2022             : 
    2023           0 :         switch (blink->bb_status) {
    2024             :         case BIOC_SBUNBLINK:
    2025           0 :                 sc->sc_ledmask &= ~(1 << blink->bb_target);
    2026           0 :                 break;
    2027             :         case BIOC_SBBLINK:
    2028           0 :                 sc->sc_ledmask |= (1 << blink->bb_target);
    2029           0 :                 break;
    2030             :         default:
    2031           0 :                 return (EINVAL);
    2032             :         }
    2033             : 
    2034           0 :         mask = htole32(sc->sc_ledmask);
    2035           0 :         bcopy(&mask, &request[2], 4);
    2036             : 
    2037           0 :         arc_lock(sc);
    2038           0 :         error = arc_msgbuf(sc, request, sizeof(request), NULL, 0, 0);
    2039           0 :         arc_unlock(sc);
    2040           0 :         if (error)
    2041           0 :                 return (EIO);
    2042             : 
    2043           0 :         return (0);
    2044           0 : }
    2045             : 
    2046             : int
    2047           0 : arc_bio_getvol(struct arc_softc *sc, int vol, struct arc_fw_volinfo *volinfo)
    2048             : {
    2049           0 :         u_int8_t                        request[2];
    2050             :         struct arc_fw_sysinfo           *sysinfo;
    2051             :         int                             error = 0;
    2052             :         int                             maxvols, nvols = 0, i;
    2053             : 
    2054             :         DPRINTF("%s: arc_bio_getvol\n", DEVNAME(sc));
    2055           0 :         sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
    2056             : 
    2057           0 :         request[0] = ARC_FW_SYSINFO;
    2058           0 :         error = arc_msgbuf(sc, request, 1, sysinfo,
    2059             :             sizeof(struct arc_fw_sysinfo), 0);
    2060           0 :         if (error != 0)
    2061             :                 goto out;
    2062             : 
    2063           0 :         maxvols = sysinfo->max_volume_set;
    2064             : 
    2065           0 :         request[0] = ARC_FW_VOLINFO;
    2066           0 :         for (i = 0; i < maxvols; i++) {
    2067           0 :                 request[1] = i;
    2068           0 :                 error = arc_msgbuf(sc, request, sizeof(request), volinfo,
    2069             :                     sizeof(struct arc_fw_volinfo), 0);
    2070           0 :                 if (error != 0)
    2071             :                         goto out;
    2072             : 
    2073           0 :                 if ((volinfo->capacity == 0 && volinfo->capacity2 == 0) ||
    2074           0 :                     volinfo->raid_level == ARC_FW_VOL_RAIDLEVEL_PASSTHRU)
    2075             :                         continue;
    2076             : 
    2077           0 :                 if (nvols == vol)
    2078             :                         break;
    2079             : 
    2080           0 :                 nvols++;
    2081           0 :         }
    2082             : 
    2083           0 :         if (nvols != vol ||
    2084           0 :             (volinfo->capacity == 0 && volinfo->capacity2 == 0) ||
    2085           0 :             volinfo->raid_level == ARC_FW_VOL_RAIDLEVEL_PASSTHRU) {
    2086             :                 error = ENODEV;
    2087           0 :                 goto out;
    2088             :         }
    2089             : 
    2090             : out:
    2091           0 :         free(sysinfo, M_TEMP, sizeof *sysinfo);
    2092           0 :         return (error);
    2093           0 : }
    2094             : 
    2095             : int
    2096           0 : arc_bio_vol(struct arc_softc *sc, struct bioc_vol *bv)
    2097             : {
    2098             :         struct arc_fw_volinfo           *volinfo;
    2099             :         struct scsi_link                *sc_link;
    2100             :         struct device                   *dev;
    2101             :         u_int64_t                       blocks;
    2102             :         u_int32_t                       status;
    2103             :         int                             error = 0;
    2104             : 
    2105             :         DPRINTF("%s: arc_bio_vol\n", DEVNAME(sc));
    2106           0 :         volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
    2107             : 
    2108           0 :         arc_lock(sc);
    2109           0 :         error = arc_bio_getvol(sc, bv->bv_volid, volinfo);
    2110           0 :         arc_unlock(sc);
    2111             : 
    2112           0 :         if (error != 0)
    2113             :                 goto out;
    2114             : 
    2115           0 :         bv->bv_percent = -1;
    2116           0 :         bv->bv_seconds = 0;
    2117             : 
    2118           0 :         status = letoh32(volinfo->volume_status);
    2119           0 :         if (status == 0x0) {
    2120           0 :                 if (letoh32(volinfo->fail_mask) == 0x0)
    2121           0 :                         bv->bv_status = BIOC_SVONLINE;
    2122             :                 else
    2123           0 :                         bv->bv_status = BIOC_SVDEGRADED;
    2124           0 :         } else if (status & ARC_FW_VOL_STATUS_NEED_REGEN)
    2125           0 :                 bv->bv_status = BIOC_SVDEGRADED;
    2126           0 :         else if (status & ARC_FW_VOL_STATUS_FAILED)
    2127           0 :                 bv->bv_status = BIOC_SVOFFLINE;
    2128           0 :         else if (status & ARC_FW_VOL_STATUS_INITTING) {
    2129           0 :                 bv->bv_status = BIOC_SVBUILDING;
    2130           0 :                 bv->bv_percent = letoh32(volinfo->progress) / 10;
    2131           0 :         } else if (status & ARC_FW_VOL_STATUS_REBUILDING) {
    2132           0 :                 bv->bv_status = BIOC_SVREBUILD;
    2133           0 :                 bv->bv_percent = letoh32(volinfo->progress) / 10;
    2134           0 :         }
    2135             : 
    2136           0 :         blocks = (u_int64_t)letoh32(volinfo->capacity2) << 32;
    2137           0 :         blocks += (u_int64_t)letoh32(volinfo->capacity);
    2138           0 :         bv->bv_size = blocks * ARC_BLOCKSIZE; /* XXX */
    2139             : 
    2140           0 :         switch (volinfo->raid_level) {
    2141             :         case ARC_FW_VOL_RAIDLEVEL_0:
    2142           0 :                 bv->bv_level = 0;
    2143           0 :                 break;
    2144             :         case ARC_FW_VOL_RAIDLEVEL_1:
    2145           0 :                 bv->bv_level = 1;
    2146           0 :                 break;
    2147             :         case ARC_FW_VOL_RAIDLEVEL_3:
    2148           0 :                 bv->bv_level = 3;
    2149           0 :                 break;
    2150             :         case ARC_FW_VOL_RAIDLEVEL_5:
    2151           0 :                 bv->bv_level = 5;
    2152           0 :                 break;
    2153             :         case ARC_FW_VOL_RAIDLEVEL_6:
    2154           0 :                 bv->bv_level = 6;
    2155           0 :                 break;
    2156             :         case ARC_FW_VOL_RAIDLEVEL_PASSTHRU:
    2157             :         default:
    2158           0 :                 bv->bv_level = -1;
    2159           0 :                 break;
    2160             :         }
    2161             : 
    2162           0 :         bv->bv_nodisk = volinfo->member_disks;
    2163           0 :         sc_link = scsi_get_link(sc->sc_scsibus, volinfo->scsi_attr.target,
    2164           0 :             volinfo->scsi_attr.lun);
    2165           0 :         if (sc_link != NULL) {
    2166           0 :                 dev = sc_link->device_softc;
    2167           0 :                 strlcpy(bv->bv_dev, dev->dv_xname, sizeof(bv->bv_dev));
    2168           0 :         }
    2169             : 
    2170             : out:
    2171           0 :         free(volinfo, M_TEMP, sizeof *volinfo);
    2172           0 :         return (error);
    2173             : }
    2174             : 
    2175             : int
    2176           0 : arc_bio_disk(struct arc_softc *sc, struct bioc_disk *bd)
    2177             : {
    2178           0 :         u_int8_t                        request[2];
    2179             :         struct arc_fw_volinfo           *volinfo;
    2180             :         struct arc_fw_raidinfo          *raidinfo;
    2181             :         struct arc_fw_diskinfo          *diskinfo;
    2182             :         int                             error = 0;
    2183             :         u_int64_t                       blocks;
    2184           0 :         char                            model[81];
    2185           0 :         char                            serial[41];
    2186           0 :         char                            rev[17];
    2187             : 
    2188             :         DPRINTF("%s: arc_bio_disk\n", DEVNAME(sc));
    2189           0 :         volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
    2190           0 :         raidinfo = malloc(sizeof(struct arc_fw_raidinfo), M_TEMP, M_WAITOK);
    2191           0 :         diskinfo = malloc(sizeof(struct arc_fw_diskinfo), M_TEMP, M_WAITOK);
    2192             : 
    2193           0 :         arc_lock(sc);
    2194             : 
    2195           0 :         error = arc_bio_getvol(sc, bd->bd_volid, volinfo);
    2196           0 :         if (error != 0)
    2197             :                 goto out;
    2198             : 
    2199           0 :         request[0] = ARC_FW_RAIDINFO;
    2200           0 :         request[1] = volinfo->raid_set_number;
    2201           0 :         error = arc_msgbuf(sc, request, sizeof(request), raidinfo,
    2202             :             sizeof(struct arc_fw_raidinfo), 0);
    2203           0 :         if (error != 0)
    2204             :                 goto out;
    2205             : 
    2206           0 :         if (bd->bd_diskid > raidinfo->member_devices) {
    2207             :                 error = ENODEV;
    2208           0 :                 goto out;
    2209             :         }
    2210             : 
    2211           0 :         if (raidinfo->device_array[bd->bd_diskid] == 0xff) {
    2212             :                 /*
    2213             :                  * the disk doesn't exist anymore. bio is too dumb to be
    2214             :                  * able to display that, so put it on another bus
    2215             :                  */
    2216           0 :                 bd->bd_channel = 1;
    2217           0 :                 bd->bd_target = 0;
    2218           0 :                 bd->bd_lun = 0;
    2219           0 :                 bd->bd_status = BIOC_SDOFFLINE;
    2220           0 :                 strlcpy(bd->bd_vendor, "disk missing", sizeof(bd->bd_vendor));
    2221           0 :                 goto out;
    2222             :         }
    2223             : 
    2224           0 :         request[0] = ARC_FW_DISKINFO;
    2225           0 :         request[1] = raidinfo->device_array[bd->bd_diskid];
    2226           0 :         error = arc_msgbuf(sc, request, sizeof(request), diskinfo,
    2227             :             sizeof(struct arc_fw_diskinfo), 1);
    2228           0 :         if (error != 0)
    2229             :                 goto out;
    2230             : 
    2231             : #if 0
    2232             :         bd->bd_channel = diskinfo->scsi_attr.channel;
    2233             :         bd->bd_target = diskinfo->scsi_attr.target;
    2234             :         bd->bd_lun = diskinfo->scsi_attr.lun;
    2235             : #endif
    2236             :         /*
    2237             :          * the firwmare doesnt seem to fill scsi_attr in, so fake it with
    2238             :          * the diskid.
    2239             :          */
    2240           0 :         bd->bd_channel = 0;
    2241           0 :         bd->bd_target = raidinfo->device_array[bd->bd_diskid];
    2242           0 :         bd->bd_lun = 0;
    2243             : 
    2244           0 :         bd->bd_status = BIOC_SDONLINE;
    2245           0 :         blocks = (u_int64_t)letoh32(diskinfo->capacity2) << 32;
    2246           0 :         blocks += (u_int64_t)letoh32(diskinfo->capacity);
    2247           0 :         bd->bd_size = blocks * ARC_BLOCKSIZE; /* XXX */
    2248             : 
    2249           0 :         scsi_strvis(model, diskinfo->model, sizeof(diskinfo->model));
    2250           0 :         scsi_strvis(serial, diskinfo->serial, sizeof(diskinfo->serial));
    2251           0 :         scsi_strvis(rev, diskinfo->firmware_rev,
    2252             :             sizeof(diskinfo->firmware_rev));
    2253             : 
    2254           0 :         snprintf(bd->bd_vendor, sizeof(bd->bd_vendor), "%s %s",
    2255             :             model, rev);
    2256           0 :         strlcpy(bd->bd_serial, serial, sizeof(bd->bd_serial));
    2257             : 
    2258             : out:
    2259           0 :         arc_unlock(sc);
    2260           0 :         free(diskinfo, M_TEMP, sizeof *diskinfo);
    2261           0 :         free(raidinfo, M_TEMP, sizeof *raidinfo);
    2262           0 :         free(volinfo, M_TEMP, sizeof *volinfo);
    2263           0 :         return (error);
    2264           0 : }
    2265             : 
    2266             : u_int8_t
    2267           0 : arc_msg_cksum(void *cmd, u_int16_t len)
    2268             : {
    2269             :         u_int8_t                        *buf = cmd;
    2270             :         u_int8_t                        cksum;
    2271             :         int                             i;
    2272             : 
    2273           0 :         cksum = (u_int8_t)(len >> 8) + (u_int8_t)len;
    2274           0 :         for (i = 0; i < len; i++)
    2275           0 :                 cksum += buf[i];
    2276             : 
    2277           0 :         return (cksum);
    2278             : }
    2279             : 
    2280             : int
    2281           0 : arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wbuflen, void *rptr,
    2282             :     size_t rbuflen, int sreadok)
    2283             : {
    2284           0 :         u_int8_t                        rwbuf[ARC_RA_IOC_RWBUF_MAXLEN];
    2285             :         u_int8_t                        *wbuf, *rbuf, cksum;
    2286             :         int                             wlen, wdone = 0, rlen, rdone = 0;
    2287             :         u_int16_t                       rlenhdr = 0;
    2288             :         struct arc_fw_bufhdr            *bufhdr;
    2289             :         u_int32_t                       reg, rwlen, write_ok, read_ok;
    2290             :         int                             error = 0;
    2291             : #ifdef ARC_DEBUG
    2292             :         int                             i;
    2293             : #endif
    2294             : 
    2295             :         DPRINTF("%s: arc_msgbuf wbuflen: %d rbuflen: %d\n",
    2296             :             DEVNAME(sc), wbuflen, rbuflen);
    2297             : 
    2298           0 :         switch(sc->sc_adp_type) {
    2299             :         case ARC_HBA_TYPE_A:
    2300           0 :                 reg = arc_read(sc, ARC_RA_OUTB_DOORBELL);
    2301           0 :                 break;
    2302             :         case ARC_HBA_TYPE_C:
    2303           0 :                 reg = arc_read(sc, ARC_RC_OUTB_DOORBELL);
    2304           0 :                 break;
    2305             :         case ARC_HBA_TYPE_D:
    2306           0 :                 reg = arc_read(sc, ARC_RD_OUTB_DOORBELL);
    2307           0 :                 break;
    2308             :         }
    2309             : /*      if (reg)
    2310             :                 return (EBUSY); */
    2311             : 
    2312           0 :         wlen = sizeof(struct arc_fw_bufhdr) + wbuflen + 1; /* 1 for cksum */
    2313           0 :         wbuf = malloc(wlen, M_TEMP, M_WAITOK);
    2314             : 
    2315           0 :         rlen = sizeof(struct arc_fw_bufhdr) + rbuflen + 1; /* 1 for cksum */
    2316           0 :         rbuf = malloc(rlen, M_TEMP, M_WAITOK);
    2317             : 
    2318             :         DNPRINTF(ARC_D_DB, "%s: arc_msgbuf wlen: %d rlen: %d\n", DEVNAME(sc),
    2319             :             wlen, rlen);
    2320             : 
    2321           0 :         bufhdr = (struct arc_fw_bufhdr *)wbuf;
    2322           0 :         bufhdr->hdr = arc_fw_hdr;
    2323           0 :         bufhdr->len = htole16(wbuflen);
    2324           0 :         bcopy(wptr, wbuf + sizeof(struct arc_fw_bufhdr), wbuflen);
    2325           0 :         wbuf[wlen - 1] = arc_msg_cksum(wptr, wbuflen);
    2326             : 
    2327             : /*      reg = ARC_RA_OUTB_DOORBELL_READ_OK; */
    2328             :         read_ok = 1;
    2329           0 :         do {
    2330           0 :                 if ((read_ok) && wdone < wlen) {
    2331           0 :                         bzero(rwbuf, sizeof(rwbuf));
    2332           0 :                         rwlen = (wlen - wdone) % sizeof(rwbuf);
    2333           0 :                         bcopy(&wbuf[wdone], rwbuf, rwlen);
    2334             : 
    2335             : #ifdef ARC_DEBUG
    2336             :                         if (arcdebug & ARC_D_DB) {
    2337             :                                 printf("%s: write %d:", DEVNAME(sc), rwlen);
    2338             :                                 for (i = 0; i < rwlen; i++)
    2339             :                                         printf(" 0x%02x", rwbuf[i]);
    2340             :                                 printf("\n");
    2341             :                         }
    2342             : #endif
    2343             : 
    2344           0 :                         switch(sc->sc_adp_type) {
    2345             :                         case ARC_HBA_TYPE_A:
    2346             :                                 /* copy the chunk to the hw */
    2347           0 :                                 arc_write(sc, ARC_RA_IOC_WBUF_LEN, rwlen);
    2348           0 :                                 arc_write_region(sc, ARC_RA_IOC_WBUF, rwbuf,
    2349             :                                 sizeof(rwbuf));
    2350             : 
    2351             :                                 /* say we have a buffer for the hw */
    2352           0 :                                 arc_write(sc, ARC_RA_INB_DOORBELL,
    2353             :                                 ARC_RA_INB_DOORBELL_WRITE_OK);
    2354           0 :                                 break;
    2355             :                         case ARC_HBA_TYPE_C:
    2356             :                                 /* copy the chunk to the hw */
    2357           0 :                                 arc_write(sc, ARC_RC_MSG_WBUF_LEN, rwlen);
    2358           0 :                                 arc_write_region(sc, ARC_RC_MSG_WBUF, rwbuf,
    2359             :                                 sizeof(rwbuf));
    2360             : 
    2361             :                                 /* say we have a buffer for the hw */
    2362           0 :                                 arc_write(sc, ARC_RC_INB_DOORBELL,
    2363             :                                 ARC_RC_D2I_DATA_WRITE_OK);
    2364           0 :                                 break;
    2365             :                         case ARC_HBA_TYPE_D:
    2366             :                                 /* copy the chunk to the hw */
    2367           0 :                                 arc_write(sc, ARC_RD_MSG_WBUF_LEN, rwlen);
    2368           0 :                                 arc_write_region(sc, ARC_RD_MSG_WBUF, rwbuf,
    2369             :                                 sizeof(rwbuf));
    2370             : 
    2371             :                                 /* say we have a buffer for the hw */
    2372           0 :                                 arc_write(sc, ARC_RD_INB_DOORBELL,
    2373             :                                 ARC_RD_D2I_DATA_WRITE_OK);
    2374           0 :                                 break;
    2375             :                         }
    2376           0 :                         wdone += rwlen;
    2377           0 :                 }
    2378             : 
    2379           0 :                 if (rptr == NULL)
    2380             :                         goto out;
    2381             : 
    2382           0 :                 switch(sc->sc_adp_type) {
    2383             :                 case ARC_HBA_TYPE_A:
    2384           0 :                         while ((reg = arc_read(sc, ARC_RA_OUTB_DOORBELL)) == 0)
    2385           0 :                                 arc_wait(sc);
    2386           0 :                         arc_write(sc, ARC_RA_OUTB_DOORBELL, reg);
    2387           0 :                         write_ok = reg & ARC_RA_OUTB_DOORBELL_WRITE_OK;
    2388           0 :                         read_ok = reg & ARC_RA_OUTB_DOORBELL_READ_OK;
    2389           0 :                         break;
    2390             :                 case ARC_HBA_TYPE_C:
    2391           0 :                         while ((reg = arc_read(sc, ARC_RC_OUTB_DOORBELL)) == 0)
    2392           0 :                                 arc_wait(sc);
    2393           0 :                         arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, reg);
    2394           0 :                         write_ok = reg & ARC_RC_I2D_DATA_WRITE_OK;
    2395           0 :                         read_ok = reg & ARC_RC_I2D_DATA_READ_OK;
    2396           0 :                         break;
    2397             :                 case ARC_HBA_TYPE_D:
    2398           0 :                         while ((reg = arc_read(sc, ARC_RD_OUTB_DOORBELL)) == 0)
    2399           0 :                                 arc_wait(sc);
    2400           0 :                         arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR, reg);
    2401           0 :                         write_ok = reg & ARC_RD_I2D_DATA_WRITE_OK;
    2402           0 :                         read_ok = reg & ARC_RD_I2D_DATA_READ_OK;
    2403           0 :                         break;
    2404             :                 }
    2405             :                 DNPRINTF(ARC_D_DB, "%s: reg: 0x%08x\n", DEVNAME(sc), reg);
    2406             : 
    2407           0 :                 if ((write_ok) && rdone < rlen) {
    2408           0 :                         switch(sc->sc_adp_type) {
    2409             :                         case ARC_HBA_TYPE_A:
    2410           0 :                                 rwlen = arc_read(sc, ARC_RA_IOC_RBUF_LEN);
    2411           0 :                                 break;
    2412             :                         case ARC_HBA_TYPE_C:
    2413           0 :                                 rwlen = arc_read(sc, ARC_RC_MSG_RBUF_LEN);
    2414           0 :                                 break;
    2415             :                         case ARC_HBA_TYPE_D:
    2416           0 :                                 rwlen = arc_read(sc, ARC_RD_MSG_RBUF_LEN);
    2417           0 :                                 break;
    2418             :                         }
    2419           0 :                         if (rwlen > sizeof(rwbuf)) {
    2420             :                                 DNPRINTF(ARC_D_DB, "%s:  rwlen too big\n",
    2421             :                                     DEVNAME(sc));
    2422             :                                 error = EIO;
    2423           0 :                                 goto out;
    2424             :                         }
    2425             : 
    2426           0 :                         switch(sc->sc_adp_type) {
    2427             :                         case ARC_HBA_TYPE_A:
    2428           0 :                                 arc_read_region(sc, ARC_RA_IOC_RBUF, rwbuf,
    2429             :                                 sizeof(rwbuf));
    2430           0 :                                 arc_write(sc, ARC_RA_INB_DOORBELL,
    2431             :                                 ARC_RA_INB_DOORBELL_READ_OK);
    2432           0 :                                 break;
    2433             :                         case ARC_HBA_TYPE_C:
    2434           0 :                                 arc_read_region(sc, ARC_RC_MSG_RBUF, rwbuf,
    2435             :                                 sizeof(rwbuf));
    2436           0 :                                 arc_write(sc, ARC_RC_INB_DOORBELL,
    2437             :                                 ARC_RC_I2D_DATA_READ_OK);
    2438           0 :                                 break;
    2439             :                         case ARC_HBA_TYPE_D:
    2440           0 :                                 arc_read_region(sc, ARC_RD_MSG_RBUF, rwbuf,
    2441             :                                 sizeof(rwbuf));
    2442           0 :                                 arc_write(sc, ARC_RD_INB_DOORBELL,
    2443             :                                 ARC_RD_I2D_DATA_READ_OK);
    2444           0 :                                 break;
    2445             :                         }
    2446           0 :                         if ((rlen > 3) && (rdone == 3)) {
    2447           0 :                                 rlen = *(u_int16_t *)rwbuf;
    2448           0 :                                 rlen = sizeof(struct arc_fw_bufhdr) + rlen + 1;
    2449           0 :                         }
    2450             : #ifdef ARC_DEBUG
    2451             :                         printf("%s:  len: %d+%d=%d/%d\n", DEVNAME(sc),
    2452             :                             rwlen, rdone, rwlen + rdone, rlen);
    2453             :                         if (arcdebug & ARC_D_DB) {
    2454             :                                 printf("%s: read:", DEVNAME(sc));
    2455             :                                 for (i = 0; i < rwlen; i++)
    2456             :                                         printf(" 0x%02x", rwbuf[i]);
    2457             :                                 printf("\n");
    2458             :                         }
    2459             : #endif
    2460             : 
    2461           0 :                         if ((rdone + rwlen) > rlen) {
    2462             :                                 DNPRINTF(ARC_D_DB, "%s:  rwbuf too big\n",
    2463             :                                     DEVNAME(sc));
    2464             :                                 error = EIO;
    2465           0 :                                 goto out;
    2466             :                         }
    2467             : 
    2468           0 :                         bcopy(rwbuf, &rbuf[rdone], rwlen);
    2469             :                         rdone += rwlen;
    2470             : 
    2471             :                         /*
    2472             :                          * Allow for short reads, by reading the length
    2473             :                          * value from the response header and shrinking our
    2474             :                          * idea of size, if required.
    2475             :                          * This deals with the growth of diskinfo struct from
    2476             :                          * 128 to 132 bytes.
    2477             :                          */ 
    2478           0 :                         if (sreadok && rdone >= sizeof(struct arc_fw_bufhdr) &&
    2479           0 :                             rlenhdr == 0) {
    2480           0 :                                 bufhdr = (struct arc_fw_bufhdr *)rbuf;
    2481           0 :                                 rlenhdr = letoh16(bufhdr->len);
    2482           0 :                                 if (rlenhdr < rbuflen) {
    2483             :                                         rbuflen = rlenhdr;
    2484           0 :                                         rlen = sizeof(struct arc_fw_bufhdr) +
    2485           0 :                                             rbuflen + 1; /* 1 for cksum */
    2486           0 :                                 }
    2487             :                         }
    2488             :                 }
    2489           0 :         } while (rdone != rlen);
    2490             : 
    2491           0 :         bufhdr = (struct arc_fw_bufhdr *)rbuf;
    2492           0 :         if (memcmp(&bufhdr->hdr, &arc_fw_hdr, sizeof(bufhdr->hdr)) != 0) {
    2493             :                 DNPRINTF(ARC_D_DB, "%s:  rbuf hdr is wrong\n", DEVNAME(sc));
    2494             :                 error = EIO;
    2495           0 :                 goto out;
    2496             :         }
    2497             : 
    2498           0 :         if (bufhdr->len != htole16(rbuflen)) {
    2499             :                 DNPRINTF(ARC_D_DB, "%s:  get_len: 0x%x, req_len: 0x%x\n",
    2500             :                         DEVNAME(sc), bufhdr->len, rbuflen);
    2501             :         }
    2502             :         
    2503           0 :         bcopy(rbuf + sizeof(struct arc_fw_bufhdr), rptr, bufhdr->len);
    2504           0 :         cksum = arc_msg_cksum(rptr, bufhdr->len);
    2505           0 :         if (rbuf[rlen - 1] != cksum) {
    2506             :                 DNPRINTF(ARC_D_DB, "%s:  invalid cksum, got :0x%x, calculated:"
    2507             :                         " 0x%x\n", DEVNAME(sc), rbuf[rlen-1], cksum);
    2508             :                 error = EIO;
    2509           0 :                 goto out;
    2510             :         }
    2511             : 
    2512             : out:
    2513           0 :         free(wbuf, M_TEMP, 0);
    2514           0 :         free(rbuf, M_TEMP, 0);
    2515             : 
    2516           0 :         return (error);
    2517           0 : }
    2518             : 
    2519             : void
    2520           0 : arc_lock(struct arc_softc *sc)
    2521             : {
    2522             :         int                             s;
    2523             :         u_int32_t int_mask;
    2524             : 
    2525           0 :         rw_enter_write(&sc->sc_lock);
    2526           0 :         s = splbio();
    2527           0 :         switch(sc->sc_adp_type) {
    2528             :         case ARC_HBA_TYPE_A:
    2529           0 :                 int_mask = arc_read(sc, ARC_RA_INTRMASK) | ARC_RA_INTRMASK_DOORBELL;
    2530           0 :                 arc_write(sc, ARC_RA_INTRMASK, int_mask);
    2531           0 :                 break;
    2532             :         case ARC_HBA_TYPE_C:
    2533           0 :                 int_mask = arc_read(sc, ARC_RC_INTR_MASK) | ARC_RC_INTR_MASK_DOORBELL;
    2534           0 :                 arc_write(sc, ARC_RC_INTR_MASK, int_mask);
    2535           0 :                 break;
    2536             :         case ARC_HBA_TYPE_D:
    2537           0 :                 int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) & ~ARC_RD_INTR_ENABLE_DOORBELL;
    2538           0 :                 arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
    2539           0 :                 break;
    2540             :         }
    2541           0 :         sc->sc_talking = 1;
    2542           0 :         splx(s);
    2543           0 : }
    2544             : 
    2545             : void
    2546           0 : arc_unlock(struct arc_softc *sc)
    2547             : {
    2548             :         int                             s;
    2549             :         u_int32_t int_mask;
    2550             : 
    2551           0 :         s = splbio();
    2552           0 :         sc->sc_talking = 0;
    2553           0 :         switch(sc->sc_adp_type) {
    2554             :         case ARC_HBA_TYPE_A:
    2555           0 :                 int_mask = arc_read(sc, ARC_RA_INTRMASK) & ~ARC_RA_INTRMASK_DOORBELL;
    2556           0 :                 arc_write(sc, ARC_RA_INTRMASK, int_mask);
    2557           0 :                 break;
    2558             :         case ARC_HBA_TYPE_C:
    2559           0 :                 int_mask = arc_read(sc, ARC_RC_INTR_MASK) & ~ARC_RC_INTR_MASK_DOORBELL;
    2560           0 :                 arc_write(sc, ARC_RC_INTR_MASK, int_mask);
    2561           0 :                 break;
    2562             :         case ARC_HBA_TYPE_D:
    2563           0 :                 int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) | ARC_RD_INTR_ENABLE_DOORBELL;
    2564           0 :                 arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
    2565           0 :                 break;
    2566             :         }
    2567           0 :         splx(s);
    2568           0 :         rw_exit_write(&sc->sc_lock);
    2569           0 : }
    2570             : 
    2571             : void
    2572           0 : arc_wait(struct arc_softc *sc)
    2573             : {
    2574             :         int                             s;
    2575             :         u_int32_t int_mask;
    2576             : 
    2577           0 :         s = splbio();
    2578           0 :         switch(sc->sc_adp_type) {
    2579             :         case ARC_HBA_TYPE_A:
    2580           0 :                 int_mask = arc_read(sc, ARC_RA_INTRMASK) & ~ARC_RA_INTRMASK_DOORBELL;
    2581           0 :                 arc_write(sc, ARC_RA_INTRMASK, int_mask);
    2582           0 :                 if (tsleep(sc, PWAIT, "arcdb", hz) == EWOULDBLOCK) {
    2583           0 :                         int_mask = arc_read(sc, ARC_RA_INTRMASK) | ARC_RA_INTRMASK_DOORBELL;
    2584           0 :                         arc_write(sc, ARC_RA_INTRMASK, int_mask);
    2585           0 :                 }
    2586             :                 break;
    2587             :         case ARC_HBA_TYPE_C:
    2588           0 :                 int_mask = arc_read(sc, ARC_RC_INTR_MASK) & ~ARC_RC_INTR_MASK_DOORBELL;
    2589           0 :                 arc_write(sc, ARC_RC_INTR_MASK, int_mask);
    2590           0 :                 if (tsleep(sc, PWAIT, "arcdb", hz) == EWOULDBLOCK) {
    2591           0 :                         int_mask = arc_read(sc, ARC_RC_INTR_MASK) | ARC_RC_INTR_MASK_DOORBELL;
    2592           0 :                         arc_write(sc, ARC_RC_INTR_MASK, int_mask);
    2593           0 :                 }
    2594             :                 break;
    2595             :         case ARC_HBA_TYPE_D:
    2596           0 :                 int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) | ARC_RD_INTR_ENABLE_DOORBELL;
    2597           0 :                 arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
    2598           0 :                 if (tsleep(sc, PWAIT, "arcdb", hz) == EWOULDBLOCK) {
    2599           0 :                         int_mask = arc_read(sc, ARC_RD_INTR_ENABLE) & ~ARC_RD_INTR_ENABLE_DOORBELL;
    2600           0 :                         arc_write(sc, ARC_RD_INTR_ENABLE, int_mask);
    2601           0 :                 }
    2602             :                 break;
    2603             :         }
    2604           0 :         splx(s);
    2605           0 : }
    2606             : 
    2607             : #ifndef SMALL_KERNEL
    2608             : void
    2609           0 : arc_create_sensors(void *xat)
    2610             : {
    2611           0 :         struct arc_task         *at = xat;
    2612           0 :         struct arc_softc        *sc = at->sc;
    2613           0 :         struct bioc_inq         bi;
    2614           0 :         struct bioc_vol         bv;
    2615             :         int                     i;
    2616             : 
    2617           0 :         free(at, M_TEMP, sizeof(*at));
    2618             : 
    2619             :         DPRINTF("%s: arc_create_sensors\n", DEVNAME(sc));
    2620             :         /*
    2621             :          * XXX * this is bollocks. the firmware has garbage coming out of it
    2622             :          * so we have to wait a bit for it to finish spewing.
    2623             :          */
    2624           0 :         tsleep(sc, PWAIT, "arcspew", 2 * hz);
    2625             : 
    2626           0 :         bzero(&bi, sizeof(bi));
    2627           0 :         if (arc_bio_inq(sc, &bi) != 0) {
    2628           0 :                 printf("%s: unable to query firmware for sensor info\n",
    2629           0 :                     DEVNAME(sc));
    2630           0 :                 return;
    2631             :         }
    2632           0 :         sc->sc_nsensors = bi.bi_novol;
    2633             : 
    2634           0 :         sc->sc_sensors = mallocarray(sc->sc_nsensors, sizeof(struct ksensor),
    2635             :             M_DEVBUF, M_WAITOK | M_ZERO);
    2636             : 
    2637           0 :         strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
    2638             :             sizeof(sc->sc_sensordev.xname));
    2639             : 
    2640           0 :         for (i = 0; i < sc->sc_nsensors; i++) {
    2641           0 :                 bzero(&bv, sizeof(bv));
    2642           0 :                 bv.bv_volid = i;
    2643           0 :                 if (arc_bio_vol(sc, &bv) != 0) {
    2644             :                         DPRINTF("%s: arc_bio_vol failed!\n", DEVNAME(sc));
    2645             :                         goto bad;
    2646             :                 }
    2647             : 
    2648           0 :                 sc->sc_sensors[i].type = SENSOR_DRIVE;
    2649           0 :                 sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
    2650             : 
    2651           0 :                 strlcpy(sc->sc_sensors[i].desc, bv.bv_dev,
    2652             :                     sizeof(sc->sc_sensors[i].desc));
    2653             : 
    2654           0 :                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
    2655             :         }
    2656             : 
    2657           0 :         if (sensor_task_register(sc, arc_refresh_sensors, 120) == NULL) {
    2658             :                 DPRINTF("%s: sensor_task_register failed!\n", DEVNAME(sc));
    2659             :                 goto bad;
    2660             :         }
    2661             : 
    2662           0 :         sensordev_install(&sc->sc_sensordev);
    2663             : 
    2664           0 :         return;
    2665             : 
    2666             : bad:
    2667           0 :         free(sc->sc_sensors, M_DEVBUF,
    2668           0 :             sc->sc_nsensors * sizeof(struct ksensor));
    2669           0 : }
    2670             : 
    2671             : void
    2672           0 : arc_refresh_sensors(void *arg)
    2673             : {
    2674           0 :         struct arc_softc        *sc = arg;
    2675           0 :         struct bioc_vol         bv;
    2676             :         int                     i;
    2677             : 
    2678           0 :         for (i = 0; i < sc->sc_nsensors; i++) {
    2679           0 :                 bzero(&bv, sizeof(bv));
    2680           0 :                 bv.bv_volid = i;
    2681           0 :                 if (arc_bio_vol(sc, &bv)) {
    2682           0 :                         sc->sc_sensors[i].flags = SENSOR_FINVALID;
    2683           0 :                         return;
    2684             :                 }
    2685             : 
    2686           0 :                 switch(bv.bv_status) {
    2687             :                 case BIOC_SVOFFLINE:
    2688           0 :                         sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
    2689           0 :                         sc->sc_sensors[i].status = SENSOR_S_CRIT;
    2690           0 :                         break;
    2691             : 
    2692             :                 case BIOC_SVDEGRADED:
    2693           0 :                         sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
    2694           0 :                         sc->sc_sensors[i].status = SENSOR_S_WARN;
    2695           0 :                         break;
    2696             : 
    2697             :                 case BIOC_SVSCRUB:
    2698             :                 case BIOC_SVONLINE:
    2699           0 :                         sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
    2700           0 :                         sc->sc_sensors[i].status = SENSOR_S_OK;
    2701           0 :                         break;
    2702             : 
    2703             :                 case BIOC_SVINVALID:
    2704             :                         /* FALLTRHOUGH */
    2705             :                 default:
    2706           0 :                         sc->sc_sensors[i].value = 0; /* unknown */
    2707           0 :                         sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
    2708           0 :                 }
    2709             : 
    2710             :         }
    2711           0 : }
    2712             : #endif /* SMALL_KERNEL */
    2713             : #endif /* NBIO > 0 */
    2714             : 
    2715             : u_int32_t
    2716           0 : arc_read(struct arc_softc *sc, bus_size_t r)
    2717             : {
    2718             :         u_int32_t                       v;
    2719             : 
    2720           0 :         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
    2721             :             BUS_SPACE_BARRIER_READ);
    2722           0 :         v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
    2723             : 
    2724             :         DNPRINTF(ARC_D_RW, "%s: arc_read 0x%x 0x%08x\n", DEVNAME(sc), r, v);
    2725             : 
    2726           0 :         return (v);
    2727             : }
    2728             : 
    2729             : void
    2730           0 : arc_read_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
    2731             : {
    2732           0 :         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
    2733             :             BUS_SPACE_BARRIER_READ);
    2734           0 :         bus_space_read_raw_region_4(sc->sc_iot, sc->sc_ioh, r, buf, len);
    2735           0 : }
    2736             : 
    2737             : void
    2738           0 : arc_write(struct arc_softc *sc, bus_size_t r, u_int32_t v)
    2739             : {
    2740             :         DNPRINTF(ARC_D_RW, "%s: arc_write 0x%x 0x%08x\n", DEVNAME(sc), r, v);
    2741             : 
    2742           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
    2743           0 :         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
    2744             :             BUS_SPACE_BARRIER_WRITE);
    2745           0 : }
    2746             : 
    2747             : void
    2748           0 : arc_write_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
    2749             : {
    2750           0 :         bus_space_write_raw_region_4(sc->sc_iot, sc->sc_ioh, r, buf, len);
    2751           0 :         bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
    2752             :             BUS_SPACE_BARRIER_WRITE);
    2753           0 : }
    2754             : 
    2755             : int
    2756           0 : arc_wait_eq(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
    2757             :     u_int32_t target)
    2758             : {
    2759             :         int                             i;
    2760             : 
    2761             :         DNPRINTF(ARC_D_RW, "%s: arc_wait_eq 0x%x 0x%08x 0x%08x\n",
    2762             :             DEVNAME(sc), r, mask, target);
    2763             : 
    2764           0 :         for (i = 0; i < 10000; i++) {
    2765           0 :                 if ((arc_read(sc, r) & mask) == target)
    2766           0 :                         return (0);
    2767           0 :                 delay(1000);
    2768             :         }
    2769             : 
    2770           0 :         return (1);
    2771           0 : }
    2772             : 
    2773             : int
    2774           0 : arc_wait_ne(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
    2775             :     u_int32_t target)
    2776             : {
    2777             :         int                             i;
    2778             : 
    2779             :         DNPRINTF(ARC_D_RW, "%s: arc_wait_ne 0x%x 0x%08x 0x%08x\n",
    2780             :             DEVNAME(sc), r, mask, target);
    2781             : 
    2782           0 :         for (i = 0; i < 10000; i++) {
    2783           0 :                 if ((arc_read(sc, r) & mask) != target)
    2784           0 :                         return (0);
    2785           0 :                 delay(1000);
    2786             :         }
    2787             : 
    2788           0 :         return (1);
    2789           0 : }
    2790             : 
    2791             : int
    2792           0 : arc_msg0(struct arc_softc *sc, u_int32_t m)
    2793             : {
    2794           0 :         switch(sc->sc_adp_type) {
    2795             :                 case ARC_HBA_TYPE_A:
    2796             :                 /* post message */
    2797           0 :                 arc_write(sc, ARC_RA_INB_MSG0, m);
    2798             :                 /* wait for the fw to do it */
    2799           0 :                 if (arc_wait_eq(sc, ARC_RA_INTRSTAT, ARC_RA_INTRSTAT_MSG0,
    2800           0 :                 ARC_RA_INTRSTAT_MSG0) != 0)
    2801           0 :                         return (1);
    2802             : 
    2803             :                 /* ack it */
    2804           0 :                 arc_write(sc, ARC_RA_INTRSTAT, ARC_RA_INTRSTAT_MSG0);
    2805           0 :                 break;
    2806             : 
    2807             :                 case ARC_HBA_TYPE_C:
    2808             :                 /* post message */
    2809           0 :                 arc_write(sc, ARC_RC_INB_MSGADDR0, m);
    2810           0 :                 arc_write(sc, ARC_RC_INB_DOORBELL, ARC_RC_D2I_MSG_CMD_DONE);
    2811             :                 /* wait for the fw to do it */
    2812           0 :                 if (arc_wait_eq(sc, ARC_RC_OUTB_DOORBELL, ARC_RC_I2D_MSG_CMD_DONE,
    2813           0 :                 ARC_RC_I2D_MSG_CMD_DONE) != 0)
    2814           0 :                         return (1);
    2815             : 
    2816             :                 /* ack it */
    2817           0 :                 arc_write(sc, ARC_RC_OUTB_DOORBELL_CLR, ARC_RC_I2D_MSG_CMD_DONE_CLR);
    2818           0 :                 break;
    2819             : 
    2820             :                 case ARC_HBA_TYPE_D:
    2821             :                 /* post message */
    2822           0 :                 arc_write(sc, ARC_RD_INB_MSGADDR0, m);
    2823             :                 /* wait for the fw to do it */
    2824           0 :                 if (arc_wait_eq(sc, ARC_RD_OUTB_DOORBELL, ARC_RD_I2D_MSG_CMD_DONE,
    2825           0 :                 ARC_RD_I2D_MSG_CMD_DONE) != 0)
    2826           0 :                         return (1);
    2827             : 
    2828             :                 /* ack it */
    2829           0 :                 arc_write(sc, ARC_RD_OUTB_DOORBELL_CLR, ARC_RD_I2D_MSG_CMD_DONE_CLR);
    2830           0 :                 break;
    2831             :         }
    2832           0 :         return (0);
    2833           0 : }
    2834             : 
    2835             : struct arc_dmamem *
    2836           0 : arc_dmamem_alloc(struct arc_softc *sc, size_t size)
    2837             : {
    2838             :         struct arc_dmamem               *adm;
    2839           0 :         int                             nsegs;
    2840             : 
    2841           0 :         adm = malloc(sizeof(*adm), M_DEVBUF, M_NOWAIT | M_ZERO);
    2842           0 :         if (adm == NULL)
    2843           0 :                 return (NULL);
    2844             : 
    2845           0 :         adm->adm_size = size;
    2846             : 
    2847           0 :         if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
    2848           0 :             BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &adm->adm_map) != 0)
    2849             :                 goto admfree;
    2850             : 
    2851           0 :         if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &adm->adm_seg,
    2852           0 :             1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
    2853             :                 goto destroy;
    2854             : 
    2855           0 :         if (bus_dmamem_map(sc->sc_dmat, &adm->adm_seg, nsegs, size,
    2856           0 :             &adm->adm_kva, BUS_DMA_NOWAIT) != 0)
    2857             :                 goto free;
    2858             : 
    2859           0 :         if (bus_dmamap_load(sc->sc_dmat, adm->adm_map, adm->adm_kva, size,
    2860           0 :             NULL, BUS_DMA_NOWAIT) != 0)
    2861             :                 goto unmap;
    2862             : 
    2863           0 :         return (adm);
    2864             : 
    2865             : unmap:
    2866           0 :         bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, size);
    2867             : free:
    2868           0 :         bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
    2869             : destroy:
    2870           0 :         bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
    2871             : admfree:
    2872           0 :         free(adm, M_DEVBUF, sizeof *adm);
    2873             : 
    2874           0 :         return (NULL);
    2875           0 : }
    2876             : 
    2877             : void
    2878           0 : arc_dmamem_free(struct arc_softc *sc, struct arc_dmamem *adm)
    2879             : {
    2880           0 :         bus_dmamap_unload(sc->sc_dmat, adm->adm_map);
    2881           0 :         bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, adm->adm_size);
    2882           0 :         bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
    2883           0 :         bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
    2884           0 :         free(adm, M_DEVBUF, sizeof *adm);
    2885           0 : }
    2886             : 
    2887             : int
    2888           0 : arc_alloc_ccbs(struct arc_softc *sc)
    2889             : {
    2890             :         struct arc_ccb          *ccb;
    2891             :         u_int8_t                        *cmd;
    2892             :         u_int32_t                       i, size, len;
    2893             : 
    2894           0 :         SLIST_INIT(&sc->sc_ccb_free);
    2895           0 :         mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
    2896             : 
    2897             :         size = sizeof(struct arc_ccb) * ARCMSR_MAX_CCB_COUNT;
    2898           0 :         sc->sc_ccbs = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
    2899             : 
    2900             :         len = ARC_IO_CMD_LEN;
    2901             :         size = ARCMSR_MAX_CCB_COUNT * len;
    2902           0 :         if(sc->sc_adp_type == ARC_HBA_TYPE_D)
    2903           0 :                 size += sizeof(struct arc_HBD_Msgu);
    2904           0 :         sc->sc_requests = arc_dmamem_alloc(sc, size);
    2905           0 :         if (sc->sc_requests == NULL) {
    2906           0 :                 printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
    2907           0 :                 goto free_ccbs;
    2908             :         }
    2909           0 :         cmd = ARC_DMA_KVA(sc->sc_requests);
    2910             : 
    2911           0 :         for (i = 0; i < ARCMSR_MAX_CCB_COUNT; i++) {
    2912           0 :                 ccb = &sc->sc_ccbs[i];
    2913             : 
    2914           0 :                 if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, ARC_SGL_MAXLEN,
    2915           0 :                     MAXPHYS, 0, 0, &ccb->ccb_dmamap) != 0) {
    2916           0 :                         printf("%s: unable to create dmamap for ccb %d\n",
    2917           0 :                             DEVNAME(sc), i);
    2918             :                         goto free_maps;
    2919             :                 }
    2920             : 
    2921           0 :                 ccb->ccb_sc = sc;
    2922           0 :                 ccb->cmd_dma_offset = len * i;
    2923             : 
    2924           0 :                 ccb->ccb_cmd = (struct arc_io_cmd *)&cmd[ccb->cmd_dma_offset];
    2925           0 :                 ccb->ccb_cmd_post = (ARC_DMA_DVA(sc->sc_requests) + 
    2926           0 :                     ccb->cmd_dma_offset);
    2927           0 :                 if ((sc->sc_adp_type != ARC_HBA_TYPE_C) &&
    2928           0 :                     (sc->sc_adp_type != ARC_HBA_TYPE_D))
    2929           0 :                         ccb->ccb_cmd_post = ccb->ccb_cmd_post >> 
    2930             :                                 ARC_RA_POST_QUEUE_ADDR_SHIFT;
    2931           0 :                 arc_put_ccb(sc, ccb);
    2932             :         }
    2933           0 :         sc->sc_ccb_phys_hi = (u_int64_t)ARC_DMA_DVA(sc->sc_requests) >> 32;
    2934           0 :         if(sc->sc_adp_type == ARC_HBA_TYPE_D) {
    2935           0 :                 sc->postQ_buffer = ARC_DMA_DVA(sc->sc_requests) +
    2936             :                     (ARCMSR_MAX_CCB_COUNT * len);
    2937           0 :                 sc->doneQ_buffer = sc->postQ_buffer + (sizeof(struct InBound_SRB) *
    2938             :                     ARCMSR_MAX_HBD_POSTQUEUE);
    2939           0 :                 sc->pmu = (struct arc_HBD_Msgu *)&cmd[ARCMSR_MAX_CCB_COUNT * len];
    2940           0 :                 sc->cmdQ_ptr_offset = ARCMSR_MAX_CCB_COUNT * len;
    2941           0 :         }
    2942           0 :         scsi_iopool_init(&sc->sc_iopool, sc,
    2943             :             (void *(*)(void *))arc_get_ccb,
    2944             :             (void (*)(void *, void *))arc_put_ccb);
    2945             : 
    2946           0 :         return (0);
    2947             : 
    2948             : free_maps:
    2949           0 :         while ((ccb = arc_get_ccb(sc)) != NULL)
    2950           0 :             bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
    2951           0 :         arc_dmamem_free(sc, sc->sc_requests);
    2952             : 
    2953             : free_ccbs:
    2954           0 :         free(sc->sc_ccbs, M_DEVBUF, sizeof(struct arc_ccb) * ARCMSR_MAX_CCB_COUNT);
    2955             : 
    2956           0 :         return (1);
    2957           0 : }
    2958             : 
    2959             : void
    2960           0 : arc_free_ccb_src(struct arc_softc *sc)
    2961             : {
    2962             :         struct arc_ccb                  *ccb;
    2963             : 
    2964           0 :         while ((ccb = arc_get_ccb(sc)) != NULL)
    2965           0 :             bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
    2966           0 :         arc_dmamem_free(sc, sc->sc_requests);
    2967           0 :         free(sc->sc_ccbs, M_DEVBUF, 0);
    2968           0 : }
    2969             : 
    2970             : struct arc_ccb *
    2971           0 : arc_get_ccb(struct arc_softc *sc)
    2972             : {
    2973             :         struct arc_ccb                  *ccb;
    2974             : 
    2975           0 :         mtx_enter(&sc->sc_ccb_mtx);
    2976           0 :         ccb = SLIST_FIRST(&sc->sc_ccb_free);
    2977           0 :         if (ccb != NULL)
    2978           0 :                 SLIST_REMOVE_HEAD(&sc->sc_ccb_free, ccb_link);
    2979           0 :         mtx_leave(&sc->sc_ccb_mtx);
    2980             : 
    2981           0 :         return (ccb);
    2982             : }
    2983             : 
    2984             : void
    2985           0 : arc_put_ccb(struct arc_softc *sc, struct arc_ccb *ccb)
    2986             : {
    2987           0 :         ccb->ccb_xs = NULL;
    2988           0 :         bzero(ccb->ccb_cmd, ARC_IO_CMD_LEN);
    2989           0 :         mtx_enter(&sc->sc_ccb_mtx);
    2990           0 :         SLIST_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_link);
    2991           0 :         mtx_leave(&sc->sc_ccb_mtx);
    2992           0 : }

Generated by: LCOV version 1.13