[BACK]Return to arc.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/arc.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: arc.c,v 1.65 2007/07/11 19:01:30 otto 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: #include "bio.h"
                     20:
                     21: #include <sys/param.h>
                     22: #include <sys/systm.h>
                     23: #include <sys/buf.h>
                     24: #include <sys/kernel.h>
                     25: #include <sys/malloc.h>
                     26: #include <sys/device.h>
                     27: #include <sys/proc.h>
                     28: #include <sys/rwlock.h>
                     29:
                     30: #include <machine/bus.h>
                     31:
                     32: #include <dev/pci/pcireg.h>
                     33: #include <dev/pci/pcivar.h>
                     34: #include <dev/pci/pcidevs.h>
                     35:
                     36: #include <scsi/scsi_all.h>
                     37: #include <scsi/scsiconf.h>
                     38:
                     39: #include <sys/sensors.h>
                     40: #if NBIO > 0
                     41: #include <sys/ioctl.h>
                     42: #include <dev/biovar.h>
                     43: #endif
                     44:
                     45: #ifdef ARC_DEBUG
                     46: #define ARC_D_INIT     (1<<0)
                     47: #define ARC_D_RW       (1<<1)
                     48: #define ARC_D_DB       (1<<2)
                     49:
                     50: int arcdebug = 0;
                     51:
                     52: #define DPRINTF(p...)          do { if (arcdebug) printf(p); } while (0)
                     53: #define DNPRINTF(n, p...)      do { if ((n) & arcdebug) printf(p); } while (0)
                     54:
                     55: #else
                     56: #define DPRINTF(p...)          /* p */
                     57: #define DNPRINTF(n, p...)      /* n, p */
                     58: #endif
                     59:
                     60: static const struct pci_matchid arc_devices[] = {
                     61:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1110 },
                     62:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1120 },
                     63:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1130 },
                     64:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1160 },
                     65:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1170 },
                     66:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1210 },
                     67:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1220 },
                     68:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1230 },
                     69:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1260 },
                     70:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1270 },
                     71:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1280 },
                     72:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1380 },
                     73:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1381 },
                     74:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1680 },
                     75:        { PCI_VENDOR_ARECA,     PCI_PRODUCT_ARECA_ARC1681 }
                     76: };
                     77:
                     78: #define ARC_PCI_BAR                    PCI_MAPREG_START
                     79:
                     80: #define ARC_REG_INB_MSG0               0x0010
                     81: #define  ARC_REG_INB_MSG0_NOP                  (0x00000000)
                     82: #define  ARC_REG_INB_MSG0_GET_CONFIG           (0x00000001)
                     83: #define  ARC_REG_INB_MSG0_SET_CONFIG           (0x00000002)
                     84: #define  ARC_REG_INB_MSG0_ABORT_CMD            (0x00000003)
                     85: #define  ARC_REG_INB_MSG0_STOP_BGRB            (0x00000004)
                     86: #define  ARC_REG_INB_MSG0_FLUSH_CACHE          (0x00000005)
                     87: #define  ARC_REG_INB_MSG0_START_BGRB           (0x00000006)
                     88: #define  ARC_REG_INB_MSG0_CHK331PENDING                (0x00000007)
                     89: #define  ARC_REG_INB_MSG0_SYNC_TIMER           (0x00000008)
                     90: #define ARC_REG_INB_MSG1               0x0014
                     91: #define ARC_REG_OUTB_ADDR0             0x0018
                     92: #define ARC_REG_OUTB_ADDR1             0x001c
                     93: #define  ARC_REG_OUTB_ADDR1_FIRMWARE_OK                (1<<31)
                     94: #define ARC_REG_INB_DOORBELL           0x0020
                     95: #define  ARC_REG_INB_DOORBELL_WRITE_OK         (1<<0)
                     96: #define  ARC_REG_INB_DOORBELL_READ_OK          (1<<1)
                     97: #define ARC_REG_OUTB_DOORBELL          0x002c
                     98: #define  ARC_REG_OUTB_DOORBELL_WRITE_OK                (1<<0)
                     99: #define  ARC_REG_OUTB_DOORBELL_READ_OK         (1<<1)
                    100: #define ARC_REG_INTRSTAT               0x0030
                    101: #define  ARC_REG_INTRSTAT_MSG0                 (1<<0)
                    102: #define  ARC_REG_INTRSTAT_MSG1                 (1<<1)
                    103: #define  ARC_REG_INTRSTAT_DOORBELL             (1<<2)
                    104: #define  ARC_REG_INTRSTAT_POSTQUEUE            (1<<3)
                    105: #define  ARC_REG_INTRSTAT_PCI                  (1<<4)
                    106: #define ARC_REG_INTRMASK               0x0034
                    107: #define  ARC_REG_INTRMASK_MSG0                 (1<<0)
                    108: #define  ARC_REG_INTRMASK_MSG1                 (1<<1)
                    109: #define  ARC_REG_INTRMASK_DOORBELL             (1<<2)
                    110: #define  ARC_REG_INTRMASK_POSTQUEUE            (1<<3)
                    111: #define  ARC_REG_INTRMASK_PCI                  (1<<4)
                    112: #define ARC_REG_POST_QUEUE             0x0040
                    113: #define  ARC_REG_POST_QUEUE_ADDR_SHIFT         5
                    114: #define  ARC_REG_POST_QUEUE_IAMBIOS            (1<<30)
                    115: #define  ARC_REG_POST_QUEUE_BIGFRAME           (1<<31)
                    116: #define ARC_REG_REPLY_QUEUE            0x0044
                    117: #define  ARC_REG_REPLY_QUEUE_ADDR_SHIFT                5
                    118: #define  ARC_REG_REPLY_QUEUE_ERR               (1<<28)
                    119: #define  ARC_REG_REPLY_QUEUE_IAMBIOS           (1<<30)
                    120: #define ARC_REG_MSGBUF                 0x0a00
                    121: #define  ARC_REG_MSGBUF_LEN            1024
                    122: #define ARC_REG_IOC_WBUF_LEN           0x0e00
                    123: #define ARC_REG_IOC_WBUF               0x0e04
                    124: #define ARC_REG_IOC_RBUF_LEN           0x0f00
                    125: #define ARC_REG_IOC_RBUF               0x0f04
                    126: #define  ARC_REG_IOC_RWBUF_MAXLEN      124 /* for both RBUF and WBUF */
                    127:
                    128: struct arc_msg_firmware_info {
                    129:        u_int32_t               signature;
                    130: #define ARC_FWINFO_SIGNATURE_GET_CONFIG                (0x87974060)
                    131:        u_int32_t               request_len;
                    132:        u_int32_t               queue_len;
                    133:        u_int32_t               sdram_size;
                    134:        u_int32_t               sata_ports;
                    135:        u_int8_t                vendor[40];
                    136:        u_int8_t                model[8];
                    137:        u_int8_t                fw_version[16];
                    138:        u_int8_t                device_map[16];
                    139: } __packed;
                    140:
                    141: struct arc_msg_scsicmd {
                    142:        u_int8_t                bus;
                    143:        u_int8_t                target;
                    144:        u_int8_t                lun;
                    145:        u_int8_t                function;
                    146:
                    147:        u_int8_t                cdb_len;
                    148:        u_int8_t                sgl_len;
                    149:        u_int8_t                flags;
                    150: #define ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512     (1<<0)
                    151: #define ARC_MSG_SCSICMD_FLAG_FROM_BIOS         (1<<1)
                    152: #define ARC_MSG_SCSICMD_FLAG_WRITE             (1<<2)
                    153: #define ARC_MSG_SCSICMD_FLAG_SIMPLEQ           (0x00)
                    154: #define ARC_MSG_SCSICMD_FLAG_HEADQ             (0x08)
                    155: #define ARC_MSG_SCSICMD_FLAG_ORDERQ            (0x10)
                    156:        u_int8_t                reserved;
                    157:
                    158:        u_int32_t               context;
                    159:        u_int32_t               data_len;
                    160:
                    161: #define ARC_MSG_CDBLEN                         16
                    162:        u_int8_t                cdb[ARC_MSG_CDBLEN];
                    163:
                    164:        u_int8_t                status;
                    165: #define ARC_MSG_STATUS_SELTIMEOUT              0xf0
                    166: #define ARC_MSG_STATUS_ABORTED                 0xf1
                    167: #define ARC_MSG_STATUS_INIT_FAIL               0xf2
                    168: #define ARC_MSG_SENSELEN                       15
                    169:        u_int8_t                sense_data[ARC_MSG_SENSELEN];
                    170:
                    171:        /* followed by an sgl */
                    172: } __packed;
                    173:
                    174: struct arc_sge {
                    175:        u_int32_t               sg_hdr;
                    176: #define ARC_SGE_64BIT                          (1<<24)
                    177:        u_int32_t               sg_lo_addr;
                    178:        u_int32_t               sg_hi_addr;
                    179: } __packed;
                    180:
                    181: #define ARC_MAX_TARGET         16
                    182: #define ARC_MAX_LUN            8
                    183: #define ARC_MAX_IOCMDLEN       512
                    184: #define ARC_BLOCKSIZE          512
                    185:
                    186: /* the firmware deals with up to 256 or 512 byte command frames. */
                    187: /* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 38) == 508 */
                    188: #define ARC_SGL_MAXLEN         38
                    189: /* sizeof(struct arc_msg_scsicmd) + (sizeof(struct arc_sge) * 17) == 252 */
                    190: #define ARC_SGL_256LEN         17
                    191:
                    192: struct arc_io_cmd {
                    193:        struct arc_msg_scsicmd  cmd;
                    194:        struct arc_sge          sgl[ARC_SGL_MAXLEN];
                    195: } __packed;
                    196:
                    197: /* definitions of the firmware commands sent via the doorbells */
                    198:
                    199: struct arc_fw_hdr {
                    200:        u_int8_t                byte1;
                    201:        u_int8_t                byte2;
                    202:        u_int8_t                byte3;
                    203: } __packed;
                    204:
                    205: /* the fw header must always equal this */
                    206: struct arc_fw_hdr arc_fw_hdr = { 0x5e, 0x01, 0x61 };
                    207:
                    208: struct arc_fw_bufhdr {
                    209:        struct arc_fw_hdr       hdr;
                    210:        u_int16_t               len;
                    211: } __packed;
                    212:
                    213: #define ARC_FW_RAIDINFO                0x20    /* opcode + raid# */
                    214: #define ARC_FW_VOLINFO         0x21    /* opcode + vol# */
                    215: #define ARC_FW_DISKINFO                0x22    /* opcode + physdisk# */
                    216: #define ARC_FW_SYSINFO         0x23    /* opcode. reply is fw_sysinfo */
                    217: #define ARC_FW_MUTE_ALARM      0x30    /* opcode only */
                    218: #define ARC_FW_SET_ALARM       0x31    /* opcode + 1 byte for setting */
                    219: #define  ARC_FW_SET_ALARM_DISABLE              0x00
                    220: #define  ARC_FW_SET_ALARM_ENABLE               0x01
                    221: #define ARC_FW_NOP             0x38    /* opcode only */
                    222:
                    223: #define ARC_FW_CMD_OK          0x41
                    224:
                    225: struct arc_fw_comminfo {
                    226:        u_int8_t                baud_rate;
                    227:        u_int8_t                data_bits;
                    228:        u_int8_t                stop_bits;
                    229:        u_int8_t                parity;
                    230:        u_int8_t                flow_control;
                    231: } __packed;
                    232:
                    233: struct arc_fw_scsiattr {
                    234:        u_int8_t                channel;// channel for SCSI target (0/1)
                    235:        u_int8_t                target;
                    236:        u_int8_t                lun;
                    237:        u_int8_t                tagged;
                    238:        u_int8_t                cache;
                    239:        u_int8_t                speed;
                    240: } __packed;
                    241:
                    242: struct arc_fw_raidinfo {
                    243:        u_int8_t                set_name[16];
                    244:        u_int32_t               capacity;
                    245:        u_int32_t               capacity2;
                    246:        u_int32_t               fail_mask;
                    247:        u_int8_t                device_array[32];
                    248:        u_int8_t                member_devices;
                    249:        u_int8_t                new_member_devices;
                    250:        u_int8_t                raid_state;
                    251:        u_int8_t                volumes;
                    252:        u_int8_t                volume_list[16];
                    253:        u_int8_t                reserved1[3];
                    254:        u_int8_t                free_segments;
                    255:        u_int32_t               raw_stripes[8];
                    256:        u_int8_t                reserved2[12];
                    257: } __packed;
                    258:
                    259: struct arc_fw_volinfo {
                    260:        u_int8_t                set_name[16];
                    261:        u_int32_t               capacity;
                    262:        u_int32_t               capacity2;
                    263:        u_int32_t               fail_mask;
                    264:        u_int32_t               stripe_size; /* in blocks */
                    265:        u_int32_t               new_fail_mask;
                    266:        u_int32_t               new_stripe_size;
                    267:        u_int32_t               volume_status;
                    268: #define ARC_FW_VOL_STATUS_NORMAL       0x00
                    269: #define ARC_FW_VOL_STATUS_INITTING     (1<<0)
                    270: #define ARC_FW_VOL_STATUS_FAILED       (1<<1)
                    271: #define ARC_FW_VOL_STATUS_MIGRATING    (1<<2)
                    272: #define ARC_FW_VOL_STATUS_REBUILDING   (1<<3)
                    273: #define ARC_FW_VOL_STATUS_NEED_INIT    (1<<4)
                    274: #define ARC_FW_VOL_STATUS_NEED_MIGRATE (1<<5)
                    275: #define ARC_FW_VOL_STATUS_INIT_FLAG    (1<<6)
                    276: #define ARC_FW_VOL_STATUS_NEED_REGEN   (1<<7)
                    277: #define ARC_FW_VOL_STATUS_CHECKING     (1<<8)
                    278: #define ARC_FW_VOL_STATUS_NEED_CHECK   (1<<9)
                    279:        u_int32_t               progress;
                    280:        struct arc_fw_scsiattr  scsi_attr;
                    281:        u_int8_t                member_disks;
                    282:        u_int8_t                raid_level;
                    283: #define ARC_FW_VOL_RAIDLEVEL_0         0x00
                    284: #define ARC_FW_VOL_RAIDLEVEL_1         0x01
                    285: #define ARC_FW_VOL_RAIDLEVEL_3         0x02
                    286: #define ARC_FW_VOL_RAIDLEVEL_5         0x03
                    287: #define ARC_FW_VOL_RAIDLEVEL_6         0x04
                    288: #define ARC_FW_VOL_RAIDLEVEL_PASSTHRU  0x05
                    289:        u_int8_t                new_member_disks;
                    290:        u_int8_t                new_raid_level;
                    291:        u_int8_t                raid_set_number;
                    292:        u_int8_t                reserved[5];
                    293: } __packed;
                    294:
                    295: struct arc_fw_diskinfo {
                    296:        u_int8_t                model[40];
                    297:        u_int8_t                serial[20];
                    298:        u_int8_t                firmware_rev[8];
                    299:        u_int32_t               capacity;
                    300:        u_int32_t               capacity2;
                    301:        u_int8_t                device_state;
                    302:        u_int8_t                pio_mode;
                    303:        u_int8_t                current_udma_mode;
                    304:        u_int8_t                udma_mode;
                    305:        u_int8_t                drive_select;
                    306:        u_int8_t                raid_number; // 0xff unowned
                    307:        struct arc_fw_scsiattr  scsi_attr;
                    308:        u_int8_t                reserved[40];
                    309: } __packed;
                    310:
                    311: struct arc_fw_sysinfo {
                    312:        u_int8_t                vendor_name[40];
                    313:        u_int8_t                serial_number[16];
                    314:        u_int8_t                firmware_version[16];
                    315:        u_int8_t                boot_version[16];
                    316:        u_int8_t                mb_version[16];
                    317:        u_int8_t                model_name[8];
                    318:
                    319:        u_int8_t                local_ip[4];
                    320:        u_int8_t                current_ip[4];
                    321:
                    322:        u_int32_t               time_tick;
                    323:        u_int32_t               cpu_speed;
                    324:        u_int32_t               icache;
                    325:        u_int32_t               dcache;
                    326:        u_int32_t               scache;
                    327:        u_int32_t               memory_size;
                    328:        u_int32_t               memory_speed;
                    329:        u_int32_t               events;
                    330:
                    331:        u_int8_t                gsiMacAddress[6];
                    332:        u_int8_t                gsiDhcp;
                    333:
                    334:        u_int8_t                alarm;
                    335:        u_int8_t                channel_usage;
                    336:        u_int8_t                max_ata_mode;
                    337:        u_int8_t                sdram_ecc;
                    338:        u_int8_t                rebuild_priority;
                    339:        struct arc_fw_comminfo  comm_a;
                    340:        struct arc_fw_comminfo  comm_b;
                    341:        u_int8_t                ide_channels;
                    342:        u_int8_t                scsi_host_channels;
                    343:        u_int8_t                ide_host_channels;
                    344:        u_int8_t                max_volume_set;
                    345:        u_int8_t                max_raid_set;
                    346:        u_int8_t                ether_port;
                    347:        u_int8_t                raid6_engine;
                    348:        u_int8_t                reserved[75];
                    349: } __packed;
                    350:
                    351: int                    arc_match(struct device *, void *, void *);
                    352: void                   arc_attach(struct device *, struct device *, void *);
                    353: int                    arc_detach(struct device *, int);
                    354: void                   arc_shutdown(void *);
                    355: int                    arc_intr(void *);
                    356:
                    357: struct arc_ccb;
                    358: TAILQ_HEAD(arc_ccb_list, arc_ccb);
                    359:
                    360: struct arc_softc {
                    361:        struct device           sc_dev;
                    362:        struct scsi_link        sc_link;
                    363:
                    364:        pci_chipset_tag_t       sc_pc;
                    365:        pcitag_t                sc_tag;
                    366:
                    367:        bus_space_tag_t         sc_iot;
                    368:        bus_space_handle_t      sc_ioh;
                    369:        bus_size_t              sc_ios;
                    370:        bus_dma_tag_t           sc_dmat;
                    371:
                    372:        void                    *sc_ih;
                    373:
                    374:        void                    *sc_shutdownhook;
                    375:
                    376:        int                     sc_req_count;
                    377:
                    378:        struct arc_dmamem       *sc_requests;
                    379:        struct arc_ccb          *sc_ccbs;
                    380:        struct arc_ccb_list     sc_ccb_free;
                    381:
                    382:        struct scsibus_softc    *sc_scsibus;
                    383:
                    384:        struct rwlock           sc_lock;
                    385:        volatile int            sc_talking;
                    386:
                    387:        struct ksensor          *sc_sensors;
                    388:        struct ksensordev       sc_sensordev;
                    389:        int                     sc_nsensors;
                    390: };
                    391: #define DEVNAME(_s)            ((_s)->sc_dev.dv_xname)
                    392:
                    393: struct cfattach arc_ca = {
                    394:        sizeof(struct arc_softc), arc_match, arc_attach, arc_detach
                    395: };
                    396:
                    397: struct cfdriver arc_cd = {
                    398:        NULL, "arc", DV_DULL
                    399: };
                    400:
                    401: /* interface for scsi midlayer to talk to */
                    402: int                    arc_scsi_cmd(struct scsi_xfer *);
                    403: void                   arc_minphys(struct buf *);
                    404:
                    405: struct scsi_adapter arc_switch = {
                    406:        arc_scsi_cmd, arc_minphys, NULL, NULL, NULL
                    407: };
                    408:
                    409: struct scsi_device arc_dev = {
                    410:        NULL, NULL, NULL, NULL
                    411: };
                    412:
                    413: /* code to deal with getting bits in and out of the bus space */
                    414: u_int32_t              arc_read(struct arc_softc *, bus_size_t);
                    415: void                   arc_read_region(struct arc_softc *, bus_size_t,
                    416:                            void *, size_t);
                    417: void                   arc_write(struct arc_softc *, bus_size_t, u_int32_t);
                    418: void                   arc_write_region(struct arc_softc *, bus_size_t,
                    419:                            void *, size_t);
                    420: int                    arc_wait_eq(struct arc_softc *, bus_size_t,
                    421:                            u_int32_t, u_int32_t);
                    422: int                    arc_wait_ne(struct arc_softc *, bus_size_t,
                    423:                            u_int32_t, u_int32_t);
                    424: int                    arc_msg0(struct arc_softc *, u_int32_t);
                    425:
                    426: #define arc_push(_s, _r)       arc_write((_s), ARC_REG_POST_QUEUE, (_r))
                    427: #define arc_pop(_s)            arc_read((_s), ARC_REG_REPLY_QUEUE)
                    428:
                    429: /* wrap up the bus_dma api */
                    430: struct arc_dmamem {
                    431:        bus_dmamap_t            adm_map;
                    432:        bus_dma_segment_t       adm_seg;
                    433:        size_t                  adm_size;
                    434:        caddr_t                 adm_kva;
                    435: };
                    436: #define ARC_DMA_MAP(_adm)      ((_adm)->adm_map)
                    437: #define ARC_DMA_DVA(_adm)      ((_adm)->adm_map->dm_segs[0].ds_addr)
                    438: #define ARC_DMA_KVA(_adm)      ((void *)(_adm)->adm_kva)
                    439:
                    440: struct arc_dmamem      *arc_dmamem_alloc(struct arc_softc *, size_t);
                    441: void                   arc_dmamem_free(struct arc_softc *,
                    442:                            struct arc_dmamem *);
                    443:
                    444: /* stuff to manage a scsi command */
                    445: struct arc_ccb {
                    446:        struct arc_softc        *ccb_sc;
                    447:        int                     ccb_id;
                    448:
                    449:        struct scsi_xfer        *ccb_xs;
                    450:
                    451:        bus_dmamap_t            ccb_dmamap;
                    452:        bus_addr_t              ccb_offset;
                    453:        struct arc_io_cmd       *ccb_cmd;
                    454:        u_int32_t               ccb_cmd_post;
                    455:
                    456:        TAILQ_ENTRY(arc_ccb)    ccb_link;
                    457: };
                    458:
                    459: int                    arc_alloc_ccbs(struct arc_softc *);
                    460: struct arc_ccb         *arc_get_ccb(struct arc_softc *);
                    461: void                   arc_put_ccb(struct arc_softc *, struct arc_ccb *);
                    462: int                    arc_load_xs(struct arc_ccb *);
                    463: int                    arc_complete(struct arc_softc *, struct arc_ccb *,
                    464:                            int);
                    465: void                   arc_scsi_cmd_done(struct arc_softc *, struct arc_ccb *,
                    466:                            u_int32_t);
                    467:
                    468: /* real stuff for dealing with the hardware */
                    469: int                    arc_map_pci_resources(struct arc_softc *,
                    470:                            struct pci_attach_args *);
                    471: int                    arc_query_firmware(struct arc_softc *);
                    472:
                    473:
                    474: #if NBIO > 0
                    475: /* stuff to do messaging via the doorbells */
                    476: void                   arc_lock(struct arc_softc *);
                    477: void                   arc_unlock(struct arc_softc *);
                    478: void                   arc_wait(struct arc_softc *);
                    479: u_int8_t               arc_msg_cksum(void *, u_int16_t);
                    480: int                    arc_msgbuf(struct arc_softc *, void *, size_t,
                    481:                            void *, size_t);
                    482:
                    483: /* bioctl */
                    484: int                    arc_bioctl(struct device *, u_long, caddr_t);
                    485: int                    arc_bio_inq(struct arc_softc *, struct bioc_inq *);
                    486: int                    arc_bio_vol(struct arc_softc *, struct bioc_vol *);
                    487: int                    arc_bio_disk(struct arc_softc *, struct bioc_disk *);
                    488: int                    arc_bio_alarm(struct arc_softc *, struct bioc_alarm *);
                    489: int                    arc_bio_alarm_state(struct arc_softc *,
                    490:                            struct bioc_alarm *);
                    491:
                    492: int                    arc_bio_getvol(struct arc_softc *, int,
                    493:                            struct arc_fw_volinfo *);
                    494:
                    495: #ifndef SMALL_KERNEL
                    496: /* sensors */
                    497: void                   arc_create_sensors(void *, void *);
                    498: void                   arc_refresh_sensors(void *);
                    499: #endif /* SMALL_KERNEL */
                    500: #endif
                    501:
                    502: int
                    503: arc_match(struct device *parent, void *match, void *aux)
                    504: {
                    505:        return (pci_matchbyid((struct pci_attach_args *)aux, arc_devices,
                    506:            sizeof(arc_devices) / sizeof(arc_devices[0])));
                    507: }
                    508:
                    509: void
                    510: arc_attach(struct device *parent, struct device *self, void *aux)
                    511: {
                    512:        struct arc_softc                *sc = (struct arc_softc *)self;
                    513:        struct pci_attach_args          *pa = aux;
                    514:        struct scsibus_attach_args      saa;
                    515:        struct device                   *child;
                    516:
                    517:        sc->sc_talking = 0;
                    518:        rw_init(&sc->sc_lock, "arcmsg");
                    519:
                    520:        if (arc_map_pci_resources(sc, pa) != 0) {
                    521:                /* error message printed by arc_map_pci_resources */
                    522:                return;
                    523:        }
                    524:
                    525:        if (arc_query_firmware(sc) != 0) {
                    526:                /* error message printed by arc_query_firmware */
                    527:                return;
                    528:        }
                    529:
                    530:        if (arc_alloc_ccbs(sc) != 0) {
                    531:                /* error message printed by arc_alloc_ccbs */
                    532:                return;
                    533:        }
                    534:
                    535:        sc->sc_shutdownhook = shutdownhook_establish(arc_shutdown, sc);
                    536:        if (sc->sc_shutdownhook == NULL)
                    537:                panic("unable to establish arc powerhook");
                    538:
                    539:        sc->sc_link.device = &arc_dev;
                    540:        sc->sc_link.adapter = &arc_switch;
                    541:        sc->sc_link.adapter_softc = sc;
                    542:        sc->sc_link.adapter_target = ARC_MAX_TARGET;
                    543:        sc->sc_link.adapter_buswidth = ARC_MAX_TARGET;
                    544:        sc->sc_link.openings = sc->sc_req_count / ARC_MAX_TARGET;
                    545:
                    546:        bzero(&saa, sizeof(saa));
                    547:        saa.saa_sc_link = &sc->sc_link;
                    548:
                    549:        child = config_found(self, &saa, scsiprint);
                    550:        sc->sc_scsibus = (struct scsibus_softc *)child;
                    551:
                    552:        /* enable interrupts */
                    553:        arc_write(sc, ARC_REG_INTRMASK,
                    554:            ~(ARC_REG_INTRMASK_POSTQUEUE|ARC_REG_INTRSTAT_DOORBELL));
                    555:
                    556: #if NBIO > 0
                    557:        if (bio_register(self, arc_bioctl) != 0)
                    558:                panic("%s: bioctl registration failed\n", DEVNAME(sc));
                    559:
                    560: #ifndef SMALL_KERNEL
                    561:        /*
                    562:         * you need to talk to the firmware to get volume info. our firmware
                    563:         * interface relies on being able to sleep, so we need to use a thread
                    564:         * to do the work.
                    565:         */
                    566:        if (scsi_task(arc_create_sensors, sc, NULL, 1) != 0)
                    567:                printf("%s: unable to schedule arc_create_sensors as a "
                    568:                    "scsi task", DEVNAME(sc));
                    569: #endif
                    570: #endif
                    571:
                    572:        return;
                    573: }
                    574:
                    575: int
                    576: arc_detach(struct device *self, int flags)
                    577: {
                    578:        struct arc_softc                *sc = (struct arc_softc *)self;
                    579:
                    580:        shutdownhook_disestablish(sc->sc_shutdownhook);
                    581:
                    582:        if (arc_msg0(sc, ARC_REG_INB_MSG0_STOP_BGRB) != 0)
                    583:                printf("%s: timeout waiting to stop bg rebuild\n", DEVNAME(sc));
                    584:
                    585:        if (arc_msg0(sc, ARC_REG_INB_MSG0_FLUSH_CACHE) != 0)
                    586:                printf("%s: timeout waiting to flush cache\n", DEVNAME(sc));
                    587:
                    588:        return (0);
                    589: }
                    590:
                    591: void
                    592: arc_shutdown(void *xsc)
                    593: {
                    594:        struct arc_softc                *sc = xsc;
                    595:
                    596:        if (arc_msg0(sc, ARC_REG_INB_MSG0_STOP_BGRB) != 0)
                    597:                printf("%s: timeout waiting to stop bg rebuild\n", DEVNAME(sc));
                    598:
                    599:        if (arc_msg0(sc, ARC_REG_INB_MSG0_FLUSH_CACHE) != 0)
                    600:                printf("%s: timeout waiting to flush cache\n", DEVNAME(sc));
                    601: }
                    602:
                    603: int
                    604: arc_intr(void *arg)
                    605: {
                    606:        struct arc_softc                *sc = arg;
                    607:        struct arc_ccb                  *ccb = NULL;
                    608:        char                            *kva = ARC_DMA_KVA(sc->sc_requests);
                    609:        struct arc_io_cmd               *cmd;
                    610:        u_int32_t                       reg, intrstat;
                    611:
                    612:        intrstat = arc_read(sc, ARC_REG_INTRSTAT);
                    613:        if (intrstat == 0x0)
                    614:                return (0);
                    615:        intrstat &= ARC_REG_INTRSTAT_POSTQUEUE | ARC_REG_INTRSTAT_DOORBELL;
                    616:        arc_write(sc, ARC_REG_INTRSTAT, intrstat);
                    617:
                    618:        if (intrstat & ARC_REG_INTRSTAT_DOORBELL) {
                    619:                if (sc->sc_talking) {
                    620:                        /* if an ioctl is talking, wake it up */
                    621:                        arc_write(sc, ARC_REG_INTRMASK,
                    622:                            ~ARC_REG_INTRMASK_POSTQUEUE);
                    623:                        wakeup(sc);
                    624:                } else {
                    625:                        /* otherwise drop it */
                    626:                        reg = arc_read(sc, ARC_REG_OUTB_DOORBELL);
                    627:                        arc_write(sc, ARC_REG_OUTB_DOORBELL, reg);
                    628:                        if (reg & ARC_REG_OUTB_DOORBELL_WRITE_OK)
                    629:                                arc_write(sc, ARC_REG_INB_DOORBELL,
                    630:                                    ARC_REG_INB_DOORBELL_READ_OK);
                    631:                }
                    632:        }
                    633:
                    634:        while ((reg = arc_pop(sc)) != 0xffffffff) {
                    635:                cmd = (struct arc_io_cmd *)(kva +
                    636:                    ((reg << ARC_REG_REPLY_QUEUE_ADDR_SHIFT) -
                    637:                    (u_int32_t)ARC_DMA_DVA(sc->sc_requests)));
                    638:                ccb = &sc->sc_ccbs[letoh32(cmd->cmd.context)];
                    639:
                    640:                bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
                    641:                    ccb->ccb_offset, ARC_MAX_IOCMDLEN,
                    642:                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    643:
                    644:                arc_scsi_cmd_done(sc, ccb, reg);
                    645:        }
                    646:
                    647:        return (1);
                    648: }
                    649:
                    650: int
                    651: arc_scsi_cmd(struct scsi_xfer *xs)
                    652: {
                    653:        struct scsi_link                *link = xs->sc_link;
                    654:        struct arc_softc                *sc = link->adapter_softc;
                    655:        struct arc_ccb                  *ccb;
                    656:        struct arc_msg_scsicmd          *cmd;
                    657:        u_int32_t                       reg;
                    658:        int                             rv = SUCCESSFULLY_QUEUED;
                    659:        int                             s;
                    660:
                    661:        if (xs->cmdlen > ARC_MSG_CDBLEN) {
                    662:                bzero(&xs->sense, sizeof(xs->sense));
                    663:                xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
                    664:                xs->sense.flags = SKEY_ILLEGAL_REQUEST;
                    665:                xs->sense.add_sense_code = 0x20;
                    666:                xs->error = XS_SENSE;
                    667:                s = splbio();
                    668:                scsi_done(xs);
                    669:                splx(s);
                    670:                return (COMPLETE);
                    671:        }
                    672:
                    673:        s = splbio();
                    674:        ccb = arc_get_ccb(sc);
                    675:        splx(s);
                    676:        if (ccb == NULL) {
                    677:                xs->error = XS_DRIVER_STUFFUP;
                    678:                s = splbio();
                    679:                scsi_done(xs);
                    680:                splx(s);
                    681:                return (COMPLETE);
                    682:        }
                    683:
                    684:        ccb->ccb_xs = xs;
                    685:
                    686:        if (arc_load_xs(ccb) != 0) {
                    687:                xs->error = XS_DRIVER_STUFFUP;
                    688:                s = splbio();
                    689:                arc_put_ccb(sc, ccb);
                    690:                scsi_done(xs);
                    691:                splx(s);
                    692:                return (COMPLETE);
                    693:        }
                    694:
                    695:        cmd = &ccb->ccb_cmd->cmd;
                    696:        reg = ccb->ccb_cmd_post;
                    697:
                    698:        /* bus is always 0 */
                    699:        cmd->target = link->target;
                    700:        cmd->lun = link->lun;
                    701:        cmd->function = 1; /* XXX magic number */
                    702:
                    703:        cmd->cdb_len = xs->cmdlen;
                    704:        cmd->sgl_len = ccb->ccb_dmamap->dm_nsegs;
                    705:        if (xs->flags & SCSI_DATA_OUT)
                    706:                cmd->flags = ARC_MSG_SCSICMD_FLAG_WRITE;
                    707:        if (ccb->ccb_dmamap->dm_nsegs > ARC_SGL_256LEN) {
                    708:                cmd->flags |= ARC_MSG_SCSICMD_FLAG_SGL_BSIZE_512;
                    709:                reg |= ARC_REG_POST_QUEUE_BIGFRAME;
                    710:        }
                    711:
                    712:        cmd->context = htole32(ccb->ccb_id);
                    713:        cmd->data_len = htole32(xs->datalen);
                    714:
                    715:        bcopy(xs->cmd, cmd->cdb, xs->cmdlen);
                    716:
                    717:        /* we've built the command, let's put it on the hw */
                    718:        bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
                    719:            ccb->ccb_offset, ARC_MAX_IOCMDLEN,
                    720:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    721:
                    722:        s = splbio();
                    723:        arc_push(sc, reg);
                    724:        if (xs->flags & SCSI_POLL) {
                    725:                rv = COMPLETE;
                    726:                if (arc_complete(sc, ccb, xs->timeout) != 0) {
                    727:                        xs->error = XS_DRIVER_STUFFUP;
                    728:                        scsi_done(xs);
                    729:                }
                    730:        }
                    731:        splx(s);
                    732:
                    733:        return (rv);
                    734: }
                    735:
                    736: int
                    737: arc_load_xs(struct arc_ccb *ccb)
                    738: {
                    739:        struct arc_softc                *sc = ccb->ccb_sc;
                    740:        struct scsi_xfer                *xs = ccb->ccb_xs;
                    741:        bus_dmamap_t                    dmap = ccb->ccb_dmamap;
                    742:        struct arc_sge                  *sgl = ccb->ccb_cmd->sgl, *sge;
                    743:        u_int64_t                       addr;
                    744:        int                             i, error;
                    745:
                    746:        if (xs->datalen == 0)
                    747:                return (0);
                    748:
                    749:        error = bus_dmamap_load(sc->sc_dmat, dmap,
                    750:            xs->data, xs->datalen, NULL,
                    751:            (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
                    752:        if (error != 0) {
                    753:                printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
                    754:                return (1);
                    755:        }
                    756:
                    757:        for (i = 0; i < dmap->dm_nsegs; i++) {
                    758:                sge = &sgl[i];
                    759:
                    760:                sge->sg_hdr = htole32(ARC_SGE_64BIT | dmap->dm_segs[i].ds_len);
                    761:                addr = dmap->dm_segs[i].ds_addr;
                    762:                sge->sg_hi_addr = htole32((u_int32_t)(addr >> 32));
                    763:                sge->sg_lo_addr = htole32((u_int32_t)addr);
                    764:        }
                    765:
                    766:        bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
                    767:            (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
                    768:            BUS_DMASYNC_PREWRITE);
                    769:
                    770:        return (0);
                    771: }
                    772:
                    773: void
                    774: arc_scsi_cmd_done(struct arc_softc *sc, struct arc_ccb *ccb, u_int32_t reg)
                    775: {
                    776:        struct scsi_xfer                *xs = ccb->ccb_xs;
                    777:        struct arc_msg_scsicmd          *cmd;
                    778:
                    779:        if (xs->datalen != 0) {
                    780:                bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
                    781:                    ccb->ccb_dmamap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
                    782:                    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                    783:                bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
                    784:        }
                    785:
                    786:        /* timeout_del */
                    787:        xs->flags |= ITSDONE;
                    788:
                    789:        if (reg & ARC_REG_REPLY_QUEUE_ERR) {
                    790:                cmd = &ccb->ccb_cmd->cmd;
                    791:
                    792:                switch (cmd->status) {
                    793:                case ARC_MSG_STATUS_SELTIMEOUT:
                    794:                case ARC_MSG_STATUS_ABORTED:
                    795:                case ARC_MSG_STATUS_INIT_FAIL:
                    796:                        xs->status = SCSI_OK;
                    797:                        xs->error = XS_SELTIMEOUT;
                    798:                        break;
                    799:
                    800:                case SCSI_CHECK:
                    801:                        bzero(&xs->sense, sizeof(xs->sense));
                    802:                        bcopy(cmd->sense_data, &xs->sense,
                    803:                            min(ARC_MSG_SENSELEN, sizeof(xs->sense)));
                    804:                        xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
                    805:                        xs->status = SCSI_CHECK;
                    806:                        xs->error = XS_SENSE;
                    807:                        xs->resid = 0;
                    808:                        break;
                    809:
                    810:                default:
                    811:                        /* unknown device status */
                    812:                        xs->error = XS_BUSY; /* try again later? */
                    813:                        xs->status = SCSI_BUSY;
                    814:                        break;
                    815:                }
                    816:        } else {
                    817:                xs->status = SCSI_OK;
                    818:                xs->error = XS_NOERROR;
                    819:                xs->resid = 0;
                    820:        }
                    821:
                    822:        arc_put_ccb(sc, ccb);
                    823:        scsi_done(xs);
                    824: }
                    825:
                    826: int
                    827: arc_complete(struct arc_softc *sc, struct arc_ccb *nccb, int timeout)
                    828: {
                    829:        struct arc_ccb                  *ccb = NULL;
                    830:        char                            *kva = ARC_DMA_KVA(sc->sc_requests);
                    831:        struct arc_io_cmd               *cmd;
                    832:        u_int32_t                       reg;
                    833:
                    834:        do {
                    835:                reg = arc_pop(sc);
                    836:                if (reg == 0xffffffff) {
                    837:                        if (timeout-- == 0)
                    838:                                return (1);
                    839:
                    840:                        delay(1000);
                    841:                        continue;
                    842:                }
                    843:
                    844:                cmd = (struct arc_io_cmd *)(kva +
                    845:                    ((reg << ARC_REG_REPLY_QUEUE_ADDR_SHIFT) -
                    846:                    ARC_DMA_DVA(sc->sc_requests)));
                    847:                ccb = &sc->sc_ccbs[letoh32(cmd->cmd.context)];
                    848:
                    849:                bus_dmamap_sync(sc->sc_dmat, ARC_DMA_MAP(sc->sc_requests),
                    850:                    ccb->ccb_offset, ARC_MAX_IOCMDLEN,
                    851:                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    852:
                    853:                arc_scsi_cmd_done(sc, ccb, reg);
                    854:        } while (nccb != ccb);
                    855:
                    856:        return (0);
                    857: }
                    858:
                    859: void
                    860: arc_minphys(struct buf *bp)
                    861: {
                    862:        if (bp->b_bcount > MAXPHYS)
                    863:                bp->b_bcount = MAXPHYS;
                    864:        minphys(bp);
                    865: }
                    866:
                    867: int
                    868: arc_map_pci_resources(struct arc_softc *sc, struct pci_attach_args *pa)
                    869: {
                    870:        pcireg_t                        memtype;
                    871:        pci_intr_handle_t               ih;
                    872:        const char                      *intrstr;
                    873:
                    874:        sc->sc_pc = pa->pa_pc;
                    875:        sc->sc_tag = pa->pa_tag;
                    876:        sc->sc_dmat = pa->pa_dmat;
                    877:
                    878:        memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, ARC_PCI_BAR);
                    879:        if (pci_mapreg_map(pa, ARC_PCI_BAR, memtype, 0, &sc->sc_iot,
                    880:            &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) {
                    881:                printf(": unable to map system interface register\n");
                    882:                return(1);
                    883:        }
                    884:
                    885:        if (pci_intr_map(pa, &ih) != 0) {
                    886:                printf(": unable to map interrupt\n");
                    887:                goto unmap;
                    888:        }
                    889:        intrstr = pci_intr_string(pa->pa_pc, ih);
                    890:        sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
                    891:            arc_intr, sc, DEVNAME(sc));
                    892:        if (sc->sc_ih == NULL) {
                    893:                printf(": unable to map interrupt%s%s\n",
                    894:                    intrstr == NULL ? "" : " at ",
                    895:                    intrstr == NULL ? "" : intrstr);
                    896:                goto unmap;
                    897:        }
                    898:        printf(": %s\n", intrstr);
                    899:
                    900:        return (0);
                    901:
                    902: unmap:
                    903:        bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
                    904:        sc->sc_ios = 0;
                    905:        return (1);
                    906: }
                    907:
                    908: int
                    909: arc_query_firmware(struct arc_softc *sc)
                    910: {
                    911:        struct arc_msg_firmware_info    fwinfo;
                    912:        char                            string[81]; /* sizeof(vendor)*2+1 */
                    913:
                    914:        if (arc_wait_eq(sc, ARC_REG_OUTB_ADDR1, ARC_REG_OUTB_ADDR1_FIRMWARE_OK,
                    915:            ARC_REG_OUTB_ADDR1_FIRMWARE_OK) != 0) {
                    916:                printf("%s: timeout waiting for firmware ok\n", DEVNAME(sc));
                    917:                return (1);
                    918:        }
                    919:
                    920:        if (arc_msg0(sc, ARC_REG_INB_MSG0_GET_CONFIG) != 0) {
                    921:                printf("%s: timeout waiting for get config\n", DEVNAME(sc));
                    922:                return (1);
                    923:        }
                    924:
                    925:        arc_read_region(sc, ARC_REG_MSGBUF, &fwinfo, sizeof(fwinfo));
                    926:
                    927:        DNPRINTF(ARC_D_INIT, "%s: signature: 0x%08x\n", DEVNAME(sc),
                    928:            letoh32(fwinfo.signature));
                    929:
                    930:        if (letoh32(fwinfo.signature) != ARC_FWINFO_SIGNATURE_GET_CONFIG) {
                    931:                printf("%s: invalid firmware info from iop\n", DEVNAME(sc));
                    932:                return (1);
                    933:        }
                    934:
                    935:        DNPRINTF(ARC_D_INIT, "%s: request_len: %d\n", DEVNAME(sc),
                    936:            letoh32(fwinfo.request_len));
                    937:        DNPRINTF(ARC_D_INIT, "%s: queue_len: %d\n", DEVNAME(sc),
                    938:            letoh32(fwinfo.queue_len));
                    939:        DNPRINTF(ARC_D_INIT, "%s: sdram_size: %d\n", DEVNAME(sc),
                    940:            letoh32(fwinfo.sdram_size));
                    941:        DNPRINTF(ARC_D_INIT, "%s: sata_ports: %d\n", DEVNAME(sc),
                    942:            letoh32(fwinfo.sata_ports), letoh32(fwinfo.sata_ports));
                    943:
                    944: #ifdef ARC_DEBUG
                    945:        scsi_strvis(string, fwinfo.vendor, sizeof(fwinfo.vendor));
                    946:        DNPRINTF(ARC_D_INIT, "%s: vendor: \"%s\"\n", DEVNAME(sc), string);
                    947:        scsi_strvis(string, fwinfo.model, sizeof(fwinfo.model));
                    948:        DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
                    949: #endif /* ARC_DEBUG */
                    950:
                    951:        scsi_strvis(string, fwinfo.fw_version, sizeof(fwinfo.fw_version));
                    952:        DNPRINTF(ARC_D_INIT, "%s: model: \"%s\"\n", DEVNAME(sc), string);
                    953:
                    954:        if (letoh32(fwinfo.request_len) != ARC_MAX_IOCMDLEN) {
                    955:                printf("%s: unexpected request frame size (%d != %d)\n",
                    956:                    DEVNAME(sc), letoh32(fwinfo.request_len), ARC_MAX_IOCMDLEN);
                    957:                return (1);
                    958:        }
                    959:
                    960:        sc->sc_req_count = letoh32(fwinfo.queue_len);
                    961:
                    962:        if (arc_msg0(sc, ARC_REG_INB_MSG0_START_BGRB) != 0) {
                    963:                printf("%s: timeout waiting to start bg rebuild\n",
                    964:                    DEVNAME(sc));
                    965:                return (1);
                    966:        }
                    967:
                    968:        printf("%s: %d SATA Ports, %dMB SDRAM, FW Version: %s\n",
                    969:            DEVNAME(sc), letoh32(fwinfo.sata_ports),
                    970:            letoh32(fwinfo.sdram_size), string);
                    971:
                    972:        return (0);
                    973: }
                    974:
                    975: #if NBIO > 0
                    976: int
                    977: arc_bioctl(struct device *self, u_long cmd, caddr_t addr)
                    978: {
                    979:        struct arc_softc                *sc = (struct arc_softc *)self;
                    980:        int                             error = 0;
                    981:
                    982:        switch (cmd) {
                    983:        case BIOCINQ:
                    984:                error = arc_bio_inq(sc, (struct bioc_inq *)addr);
                    985:                break;
                    986:
                    987:        case BIOCVOL:
                    988:                error = arc_bio_vol(sc, (struct bioc_vol *)addr);
                    989:                break;
                    990:
                    991:        case BIOCDISK:
                    992:                error = arc_bio_disk(sc, (struct bioc_disk *)addr);
                    993:                break;
                    994:
                    995:        case BIOCALARM:
                    996:                error = arc_bio_alarm(sc, (struct bioc_alarm *)addr);
                    997:                break;
                    998:
                    999:        default:
                   1000:                error = ENOTTY;
                   1001:                break;
                   1002:        }
                   1003:
                   1004:        return (error);
                   1005: }
                   1006:
                   1007: int
                   1008: arc_bio_alarm(struct arc_softc *sc, struct bioc_alarm *ba)
                   1009: {
                   1010:        u_int8_t                        request[2];
                   1011:        u_int8_t                        reply[1];
                   1012:        size_t                          len;
                   1013:        int                             error = 0;
                   1014:
                   1015:        switch (ba->ba_opcode) {
                   1016:        case BIOC_SAENABLE:
                   1017:        case BIOC_SADISABLE:
                   1018:                request[0] = ARC_FW_SET_ALARM;
                   1019:                request[1] = (ba->ba_opcode == BIOC_SAENABLE) ?
                   1020:                    ARC_FW_SET_ALARM_ENABLE : ARC_FW_SET_ALARM_DISABLE;
                   1021:                len = sizeof(request);
                   1022:
                   1023:                break;
                   1024:
                   1025:        case BIOC_SASILENCE:
                   1026:                request[0] = ARC_FW_MUTE_ALARM;
                   1027:                len = 1;
                   1028:
                   1029:                break;
                   1030:
                   1031:        case BIOC_GASTATUS:
                   1032:                /* system info is too big/ugly to deal with here */
                   1033:                return (arc_bio_alarm_state(sc, ba));
                   1034:
                   1035:        default:
                   1036:                return (EOPNOTSUPP);
                   1037:        }
                   1038:
                   1039:        arc_lock(sc);
                   1040:        error = arc_msgbuf(sc, request, len, reply, sizeof(reply));
                   1041:        arc_unlock(sc);
                   1042:
                   1043:        if (error != 0)
                   1044:                return (error);
                   1045:
                   1046:        if (reply[0] != ARC_FW_CMD_OK)
                   1047:                return (EIO);
                   1048:
                   1049:        return (0);
                   1050: }
                   1051:
                   1052: int
                   1053: arc_bio_alarm_state(struct arc_softc *sc, struct bioc_alarm *ba)
                   1054: {
                   1055:        u_int8_t                        request = ARC_FW_SYSINFO;
                   1056:        struct arc_fw_sysinfo           *sysinfo;
                   1057:        int                             error = 0;
                   1058:
                   1059:        sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
                   1060:
                   1061:        request = ARC_FW_SYSINFO;
                   1062:
                   1063:        arc_lock(sc);
                   1064:        error = arc_msgbuf(sc, &request, sizeof(request),
                   1065:            sysinfo, sizeof(struct arc_fw_sysinfo));
                   1066:        arc_unlock(sc);
                   1067:
                   1068:        if (error != 0)
                   1069:                goto out;
                   1070:
                   1071:        ba->ba_status = sysinfo->alarm;
                   1072:
                   1073: out:
                   1074:        free(sysinfo, M_TEMP);
                   1075:        return (error);
                   1076: }
                   1077:
                   1078:
                   1079: int
                   1080: arc_bio_inq(struct arc_softc *sc, struct bioc_inq *bi)
                   1081: {
                   1082:        u_int8_t                        request[2];
                   1083:        struct arc_fw_sysinfo           *sysinfo;
                   1084:        struct arc_fw_volinfo           *volinfo;
                   1085:        int                             maxvols, nvols = 0, i;
                   1086:        int                             error = 0;
                   1087:
                   1088:        sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
                   1089:        volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
                   1090:
                   1091:        arc_lock(sc);
                   1092:
                   1093:        request[0] = ARC_FW_SYSINFO;
                   1094:        error = arc_msgbuf(sc, request, 1, sysinfo,
                   1095:            sizeof(struct arc_fw_sysinfo));
                   1096:        if (error != 0)
                   1097:                goto out;
                   1098:
                   1099:        maxvols = sysinfo->max_volume_set;
                   1100:
                   1101:        request[0] = ARC_FW_VOLINFO;
                   1102:        for (i = 0; i < maxvols; i++) {
                   1103:                request[1] = i;
                   1104:                error = arc_msgbuf(sc, request, sizeof(request), volinfo,
                   1105:                    sizeof(struct arc_fw_volinfo));
                   1106:                if (error != 0)
                   1107:                        goto out;
                   1108:
                   1109:                /*
                   1110:                 * I can't find an easy way to see if the volume exists or not
                   1111:                 * except to say that if it has no capacity then it isn't there.
                   1112:                 * Ignore passthru volumes, bioc_vol doesn't understand them.
                   1113:                 */
                   1114:                if ((volinfo->capacity != 0 || volinfo->capacity2 != 0) &&
                   1115:                    volinfo->raid_level != ARC_FW_VOL_RAIDLEVEL_PASSTHRU)
                   1116:                        nvols++;
                   1117:        }
                   1118:
                   1119:        strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
                   1120:        bi->bi_novol = nvols;
                   1121: out:
                   1122:        arc_unlock(sc);
                   1123:        free(volinfo, M_TEMP);
                   1124:        free(sysinfo, M_TEMP);
                   1125:        return (error);
                   1126: }
                   1127:
                   1128: int
                   1129: arc_bio_getvol(struct arc_softc *sc, int vol, struct arc_fw_volinfo *volinfo)
                   1130: {
                   1131:        u_int8_t                        request[2];
                   1132:        struct arc_fw_sysinfo           *sysinfo;
                   1133:        int                             error = 0;
                   1134:        int                             maxvols, nvols = 0, i;
                   1135:
                   1136:        sysinfo = malloc(sizeof(struct arc_fw_sysinfo), M_TEMP, M_WAITOK);
                   1137:
                   1138:        request[0] = ARC_FW_SYSINFO;
                   1139:        error = arc_msgbuf(sc, request, 1, sysinfo,
                   1140:            sizeof(struct arc_fw_sysinfo));
                   1141:        if (error != 0)
                   1142:                goto out;
                   1143:
                   1144:        maxvols = sysinfo->max_volume_set;
                   1145:
                   1146:        request[0] = ARC_FW_VOLINFO;
                   1147:        for (i = 0; i < maxvols; i++) {
                   1148:                request[1] = i;
                   1149:                error = arc_msgbuf(sc, request, sizeof(request), volinfo,
                   1150:                    sizeof(struct arc_fw_volinfo));
                   1151:                if (error != 0)
                   1152:                        goto out;
                   1153:
                   1154:                if ((volinfo->capacity == 0 && volinfo->capacity2 == 0) ||
                   1155:                    volinfo->raid_level == ARC_FW_VOL_RAIDLEVEL_PASSTHRU)
                   1156:                        continue;
                   1157:
                   1158:                if (nvols == vol)
                   1159:                        break;
                   1160:
                   1161:                nvols++;
                   1162:        }
                   1163:
                   1164:        if (nvols != vol ||
                   1165:            (volinfo->capacity == 0 && volinfo->capacity2 == 0) ||
                   1166:            volinfo->raid_level == ARC_FW_VOL_RAIDLEVEL_PASSTHRU) {
                   1167:                error = ENODEV;
                   1168:                goto out;
                   1169:        }
                   1170:
                   1171: out:
                   1172:        free(sysinfo, M_TEMP);
                   1173:        return (error);
                   1174: }
                   1175:
                   1176: int
                   1177: arc_bio_vol(struct arc_softc *sc, struct bioc_vol *bv)
                   1178: {
                   1179:        struct arc_fw_volinfo           *volinfo;
                   1180:        struct scsi_link                *sc_link;
                   1181:        struct device                   *dev;
                   1182:        u_int64_t                       blocks;
                   1183:        u_int32_t                       status;
                   1184:        int                             error = 0;
                   1185:
                   1186:        volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
                   1187:
                   1188:        arc_lock(sc);
                   1189:        error = arc_bio_getvol(sc, bv->bv_volid, volinfo);
                   1190:        arc_unlock(sc);
                   1191:
                   1192:        if (error != 0)
                   1193:                goto out;
                   1194:
                   1195:        bv->bv_percent = -1;
                   1196:        bv->bv_seconds = 0;
                   1197:
                   1198:        status = letoh32(volinfo->volume_status);
                   1199:        if (status == 0x0) {
                   1200:                if (letoh32(volinfo->fail_mask) == 0x0)
                   1201:                        bv->bv_status = BIOC_SVONLINE;
                   1202:                else
                   1203:                        bv->bv_status = BIOC_SVDEGRADED;
                   1204:        } else if (status & ARC_FW_VOL_STATUS_NEED_REGEN)
                   1205:                bv->bv_status = BIOC_SVDEGRADED;
                   1206:        else if (status & ARC_FW_VOL_STATUS_FAILED)
                   1207:                bv->bv_status = BIOC_SVOFFLINE;
                   1208:        else if (status & ARC_FW_VOL_STATUS_INITTING) {
                   1209:                bv->bv_status = BIOC_SVBUILDING;
                   1210:                bv->bv_percent = letoh32(volinfo->progress) / 10;
                   1211:        } else if (status & ARC_FW_VOL_STATUS_REBUILDING) {
                   1212:                bv->bv_status = BIOC_SVREBUILD;
                   1213:                bv->bv_percent = letoh32(volinfo->progress) / 10;
                   1214:        }
                   1215:
                   1216:        blocks = (u_int64_t)letoh32(volinfo->capacity2) << 32;
                   1217:        blocks += (u_int64_t)letoh32(volinfo->capacity);
                   1218:        bv->bv_size = blocks * ARC_BLOCKSIZE; /* XXX */
                   1219:
                   1220:        switch (volinfo->raid_level) {
                   1221:        case ARC_FW_VOL_RAIDLEVEL_0:
                   1222:                bv->bv_level = 0;
                   1223:                break;
                   1224:        case ARC_FW_VOL_RAIDLEVEL_1:
                   1225:                bv->bv_level = 1;
                   1226:                break;
                   1227:        case ARC_FW_VOL_RAIDLEVEL_3:
                   1228:                bv->bv_level = 3;
                   1229:                break;
                   1230:        case ARC_FW_VOL_RAIDLEVEL_5:
                   1231:                bv->bv_level = 5;
                   1232:                break;
                   1233:        case ARC_FW_VOL_RAIDLEVEL_6:
                   1234:                bv->bv_level = 6;
                   1235:                break;
                   1236:        case ARC_FW_VOL_RAIDLEVEL_PASSTHRU:
                   1237:        default:
                   1238:                bv->bv_level = -1;
                   1239:                break;
                   1240:        }
                   1241:
                   1242:        bv->bv_nodisk = volinfo->member_disks;
                   1243:        sc_link = sc->sc_scsibus->sc_link[volinfo->scsi_attr.target]
                   1244:            [volinfo->scsi_attr.lun];
                   1245:        if (sc_link != NULL) {
                   1246:                dev = sc_link->device_softc;
                   1247:                strlcpy(bv->bv_dev, dev->dv_xname, sizeof(bv->bv_dev));
                   1248:        }
                   1249:
                   1250: out:
                   1251:        free(volinfo, M_TEMP);
                   1252:        return (error);
                   1253: }
                   1254:
                   1255: int
                   1256: arc_bio_disk(struct arc_softc *sc, struct bioc_disk *bd)
                   1257: {
                   1258:        u_int8_t                        request[2];
                   1259:        struct arc_fw_volinfo           *volinfo;
                   1260:        struct arc_fw_raidinfo          *raidinfo;
                   1261:        struct arc_fw_diskinfo          *diskinfo;
                   1262:        int                             error = 0;
                   1263:        u_int64_t                       blocks;
                   1264:        char                            model[81];
                   1265:        char                            serial[41];
                   1266:        char                            rev[17];
                   1267:
                   1268:        volinfo = malloc(sizeof(struct arc_fw_volinfo), M_TEMP, M_WAITOK);
                   1269:        raidinfo = malloc(sizeof(struct arc_fw_raidinfo), M_TEMP, M_WAITOK);
                   1270:        diskinfo = malloc(sizeof(struct arc_fw_diskinfo), M_TEMP, M_WAITOK);
                   1271:
                   1272:        arc_lock(sc);
                   1273:
                   1274:        error = arc_bio_getvol(sc, bd->bd_volid, volinfo);
                   1275:        if (error != 0)
                   1276:                goto out;
                   1277:
                   1278:        request[0] = ARC_FW_RAIDINFO;
                   1279:        request[1] = volinfo->raid_set_number;
                   1280:        error = arc_msgbuf(sc, request, sizeof(request), raidinfo,
                   1281:            sizeof(struct arc_fw_raidinfo));
                   1282:        if (error != 0)
                   1283:                goto out;
                   1284:
                   1285:        if (bd->bd_diskid > raidinfo->member_devices) {
                   1286:                error = ENODEV;
                   1287:                goto out;
                   1288:        }
                   1289:
                   1290:        if (raidinfo->device_array[bd->bd_diskid] == 0xff) {
                   1291:                /*
                   1292:                 * the disk doesn't exist anymore. bio is too dumb to be
                   1293:                 * able to display that, so put it on another bus
                   1294:                 */
                   1295:                bd->bd_channel = 1;
                   1296:                bd->bd_target = 0;
                   1297:                bd->bd_lun = 0;
                   1298:                bd->bd_status = BIOC_SDOFFLINE;
                   1299:                strlcpy(bd->bd_vendor, "disk missing", sizeof(bd->bd_vendor));
                   1300:                goto out;
                   1301:        }
                   1302:
                   1303:        request[0] = ARC_FW_DISKINFO;
                   1304:        request[1] = raidinfo->device_array[bd->bd_diskid];
                   1305:        error = arc_msgbuf(sc, request, sizeof(request), diskinfo,
                   1306:            sizeof(struct arc_fw_diskinfo));
                   1307:        if (error != 0)
                   1308:                goto out;
                   1309:
                   1310: #if 0
                   1311:        bd->bd_channel = diskinfo->scsi_attr.channel;
                   1312:        bd->bd_target = diskinfo->scsi_attr.target;
                   1313:        bd->bd_lun = diskinfo->scsi_attr.lun;
                   1314: #endif
                   1315:        /*
                   1316:         * the firwmare doesnt seem to fill scsi_attr in, so fake it with
                   1317:         * the diskid.
                   1318:         */
                   1319:        bd->bd_channel = 0;
                   1320:        bd->bd_target = raidinfo->device_array[bd->bd_diskid];
                   1321:        bd->bd_lun = 0;
                   1322:
                   1323:        bd->bd_status = BIOC_SDONLINE;
                   1324:        blocks = (u_int64_t)letoh32(diskinfo->capacity2) << 32;
                   1325:        blocks += (u_int64_t)letoh32(diskinfo->capacity);
                   1326:        bd->bd_size = blocks * ARC_BLOCKSIZE; /* XXX */
                   1327:
                   1328:        scsi_strvis(model, diskinfo->model, sizeof(diskinfo->model));
                   1329:        scsi_strvis(serial, diskinfo->serial, sizeof(diskinfo->serial));
                   1330:        scsi_strvis(rev, diskinfo->firmware_rev,
                   1331:            sizeof(diskinfo->firmware_rev));
                   1332:
                   1333:        snprintf(bd->bd_vendor, sizeof(bd->bd_vendor), "%s %s",
                   1334:            model, rev);
                   1335:        strlcpy(bd->bd_serial, serial, sizeof(bd->bd_serial));
                   1336:
                   1337: out:
                   1338:        arc_unlock(sc);
                   1339:        free(diskinfo, M_TEMP);
                   1340:        free(raidinfo, M_TEMP);
                   1341:        free(volinfo, M_TEMP);
                   1342:        return (error);
                   1343: }
                   1344:
                   1345: u_int8_t
                   1346: arc_msg_cksum(void *cmd, u_int16_t len)
                   1347: {
                   1348:        u_int8_t                        *buf = cmd;
                   1349:        u_int8_t                        cksum;
                   1350:        int                             i;
                   1351:
                   1352:        cksum = (u_int8_t)(len >> 8) + (u_int8_t)len;
                   1353:        for (i = 0; i < len; i++)
                   1354:                cksum += buf[i];
                   1355:
                   1356:        return (cksum);
                   1357: }
                   1358:
                   1359:
                   1360: int
                   1361: arc_msgbuf(struct arc_softc *sc, void *wptr, size_t wbuflen, void *rptr,
                   1362:     size_t rbuflen)
                   1363: {
                   1364:        u_int8_t                        rwbuf[ARC_REG_IOC_RWBUF_MAXLEN];
                   1365:        u_int8_t                        *wbuf, *rbuf;
                   1366:        int                             wlen, wdone = 0, rlen, rdone = 0;
                   1367:        struct arc_fw_bufhdr            *bufhdr;
                   1368:        u_int32_t                       reg, rwlen;
                   1369:        int                             error = 0;
                   1370: #ifdef ARC_DEBUG
                   1371:        int                             i;
                   1372: #endif
                   1373:
                   1374:        DNPRINTF(ARC_D_DB, "%s: arc_msgbuf wbuflen: %d rbuflen: %d\n",
                   1375:            DEVNAME(sc), wbuflen, rbuflen);
                   1376:
                   1377:        if (arc_read(sc, ARC_REG_OUTB_DOORBELL) != 0)
                   1378:                return (EBUSY);
                   1379:
                   1380:        wlen = sizeof(struct arc_fw_bufhdr) + wbuflen + 1; /* 1 for cksum */
                   1381:        wbuf = malloc(wlen, M_TEMP, M_WAITOK);
                   1382:
                   1383:        rlen = sizeof(struct arc_fw_bufhdr) + rbuflen + 1; /* 1 for cksum */
                   1384:        rbuf = malloc(rlen, M_TEMP, M_WAITOK);
                   1385:
                   1386:        DNPRINTF(ARC_D_DB, "%s: arc_msgbuf wlen: %d rlen: %d\n", DEVNAME(sc),
                   1387:            wlen, rlen);
                   1388:
                   1389:        bufhdr = (struct arc_fw_bufhdr *)wbuf;
                   1390:        bufhdr->hdr = arc_fw_hdr;
                   1391:        bufhdr->len = htole16(wbuflen);
                   1392:        bcopy(wptr, wbuf + sizeof(struct arc_fw_bufhdr), wbuflen);
                   1393:        wbuf[wlen - 1] = arc_msg_cksum(wptr, wbuflen);
                   1394:
                   1395:        reg = ARC_REG_OUTB_DOORBELL_READ_OK;
                   1396:
                   1397:        do {
                   1398:                if ((reg & ARC_REG_OUTB_DOORBELL_READ_OK) && wdone < wlen) {
                   1399:                        bzero(rwbuf, sizeof(rwbuf));
                   1400:                        rwlen = (wlen - wdone) % sizeof(rwbuf);
                   1401:                        bcopy(&wbuf[wdone], rwbuf, rwlen);
                   1402:
                   1403: #ifdef ARC_DEBUG
                   1404:                        if (arcdebug & ARC_D_DB) {
                   1405:                                printf("%s: write %d:", DEVNAME(sc), rwlen);
                   1406:                                for (i = 0; i < rwlen; i++)
                   1407:                                        printf(" 0x%02x", rwbuf[i]);
                   1408:                                printf("\n");
                   1409:                        }
                   1410: #endif
                   1411:
                   1412:                        /* copy the chunk to the hw */
                   1413:                        arc_write(sc, ARC_REG_IOC_WBUF_LEN, rwlen);
                   1414:                        arc_write_region(sc, ARC_REG_IOC_WBUF, rwbuf,
                   1415:                            sizeof(rwbuf));
                   1416:
                   1417:                        /* say we have a buffer for the hw */
                   1418:                        arc_write(sc, ARC_REG_INB_DOORBELL,
                   1419:                            ARC_REG_INB_DOORBELL_WRITE_OK);
                   1420:
                   1421:                        wdone += rwlen;
                   1422:                }
                   1423:
                   1424:                while ((reg = arc_read(sc, ARC_REG_OUTB_DOORBELL)) == 0)
                   1425:                        arc_wait(sc);
                   1426:                arc_write(sc, ARC_REG_OUTB_DOORBELL, reg);
                   1427:
                   1428:                DNPRINTF(ARC_D_DB, "%s: reg: 0x%08x\n", DEVNAME(sc), reg);
                   1429:
                   1430:                if ((reg & ARC_REG_OUTB_DOORBELL_WRITE_OK) && rdone < rlen) {
                   1431:                        rwlen = arc_read(sc, ARC_REG_IOC_RBUF_LEN);
                   1432:                        if (rwlen > sizeof(rwbuf)) {
                   1433:                                DNPRINTF(ARC_D_DB, "%s:  rwlen too big\n",
                   1434:                                    DEVNAME(sc));
                   1435:                                error = EIO;
                   1436:                                goto out;
                   1437:                        }
                   1438:
                   1439:                        arc_read_region(sc, ARC_REG_IOC_RBUF, rwbuf,
                   1440:                            sizeof(rwbuf));
                   1441:
                   1442:                        arc_write(sc, ARC_REG_INB_DOORBELL,
                   1443:                            ARC_REG_INB_DOORBELL_READ_OK);
                   1444:
                   1445: #ifdef ARC_DEBUG
                   1446:                        printf("%s:  len: %d+%d=%d/%d\n", DEVNAME(sc),
                   1447:                            rwlen, rdone, rwlen + rdone, rlen);
                   1448:                        if (arcdebug & ARC_D_DB) {
                   1449:                                printf("%s: read:", DEVNAME(sc));
                   1450:                                for (i = 0; i < rwlen; i++)
                   1451:                                        printf(" 0x%02x", rwbuf[i]);
                   1452:                                printf("\n");
                   1453:                        }
                   1454: #endif
                   1455:
                   1456:                        if ((rdone + rwlen) > rlen) {
                   1457:                                DNPRINTF(ARC_D_DB, "%s:  rwbuf too big\n",
                   1458:                                    DEVNAME(sc));
                   1459:                                error = EIO;
                   1460:                                goto out;
                   1461:                        }
                   1462:
                   1463:                        bcopy(rwbuf, &rbuf[rdone], rwlen);
                   1464:                        rdone += rwlen;
                   1465:                }
                   1466:        } while (rdone != rlen);
                   1467:
                   1468:        bufhdr = (struct arc_fw_bufhdr *)rbuf;
                   1469:        if (memcmp(&bufhdr->hdr, &arc_fw_hdr, sizeof(bufhdr->hdr)) != 0 ||
                   1470:            bufhdr->len != htole16(rbuflen)) {
                   1471:                DNPRINTF(ARC_D_DB, "%s:  rbuf hdr is wrong\n", DEVNAME(sc));
                   1472:                error = EIO;
                   1473:                goto out;
                   1474:        }
                   1475:
                   1476:        bcopy(rbuf + sizeof(struct arc_fw_bufhdr), rptr, rbuflen);
                   1477:
                   1478:        if (rbuf[rlen - 1] != arc_msg_cksum(rptr, rbuflen)) {
                   1479:                DNPRINTF(ARC_D_DB, "%s:  invalid cksum\n", DEVNAME(sc));
                   1480:                error = EIO;
                   1481:                goto out;
                   1482:        }
                   1483:
                   1484: out:
                   1485:        free(wbuf, M_TEMP);
                   1486:        free(rbuf, M_TEMP);
                   1487:
                   1488:        return (error);
                   1489: }
                   1490:
                   1491: void
                   1492: arc_lock(struct arc_softc *sc)
                   1493: {
                   1494:        int                             s;
                   1495:
                   1496:        rw_enter_write(&sc->sc_lock);
                   1497:        s = splbio();
                   1498:        arc_write(sc, ARC_REG_INTRMASK, ~ARC_REG_INTRMASK_POSTQUEUE);
                   1499:        sc->sc_talking = 1;
                   1500:        splx(s);
                   1501: }
                   1502:
                   1503: void
                   1504: arc_unlock(struct arc_softc *sc)
                   1505: {
                   1506:        int                             s;
                   1507:
                   1508:        s = splbio();
                   1509:        sc->sc_talking = 0;
                   1510:        arc_write(sc, ARC_REG_INTRMASK,
                   1511:            ~(ARC_REG_INTRMASK_POSTQUEUE|ARC_REG_INTRMASK_DOORBELL));
                   1512:        splx(s);
                   1513:        rw_exit_write(&sc->sc_lock);
                   1514: }
                   1515:
                   1516: void
                   1517: arc_wait(struct arc_softc *sc)
                   1518: {
                   1519:        int                             s;
                   1520:
                   1521:        s = splbio();
                   1522:        arc_write(sc, ARC_REG_INTRMASK,
                   1523:            ~(ARC_REG_INTRMASK_POSTQUEUE|ARC_REG_INTRMASK_DOORBELL));
                   1524:        if (tsleep(sc, PWAIT, "arcdb", hz) == EWOULDBLOCK)
                   1525:                arc_write(sc, ARC_REG_INTRMASK, ~ARC_REG_INTRMASK_POSTQUEUE);
                   1526:        splx(s);
                   1527: }
                   1528:
                   1529: #ifndef SMALL_KERNEL
                   1530: void
                   1531: arc_create_sensors(void *xsc, void *arg)
                   1532: {
                   1533:        struct arc_softc        *sc = xsc;
                   1534:        struct bioc_inq         bi;
                   1535:        struct bioc_vol         bv;
                   1536:        int                     i;
                   1537:
                   1538:        /*
                   1539:         * XXX * this is bollocks. the firmware has garbage coming out of it
                   1540:         * so we have to wait a bit for it to finish spewing.
                   1541:         */
                   1542:        tsleep(sc, PWAIT, "arcspew", 2 * hz);
                   1543:
                   1544:        bzero(&bi, sizeof(bi));
                   1545:        if (arc_bio_inq(sc, &bi) != 0) {
                   1546:                printf("%s: unable to query firmware for sensor info\n",
                   1547:                    DEVNAME(sc));
                   1548:                return;
                   1549:        }
                   1550:        sc->sc_nsensors = bi.bi_novol;
                   1551:
                   1552:        sc->sc_sensors = malloc(sizeof(struct ksensor) * sc->sc_nsensors,
                   1553:            M_DEVBUF, M_WAITOK);
                   1554:        bzero(sc->sc_sensors, sizeof(struct ksensor) * sc->sc_nsensors);
                   1555:
                   1556:        strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
                   1557:            sizeof(sc->sc_sensordev.xname));
                   1558:
                   1559:        for (i = 0; i < sc->sc_nsensors; i++) {
                   1560:                bzero(&bv, sizeof(bv));
                   1561:                bv.bv_volid = i;
                   1562:                if (arc_bio_vol(sc, &bv) != 0)
                   1563:                        goto bad;
                   1564:
                   1565:                sc->sc_sensors[i].type = SENSOR_DRIVE;
                   1566:                sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
                   1567:
                   1568:                strlcpy(sc->sc_sensors[i].desc, bv.bv_dev,
                   1569:                    sizeof(sc->sc_sensors[i].desc));
                   1570:
                   1571:                sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
                   1572:        }
                   1573:
                   1574:        if (sensor_task_register(sc, arc_refresh_sensors, 120) == NULL)
                   1575:                goto bad;
                   1576:
                   1577:        sensordev_install(&sc->sc_sensordev);
                   1578:
                   1579:        return;
                   1580:
                   1581: bad:
                   1582:        free(sc->sc_sensors, M_DEVBUF);
                   1583: }
                   1584:
                   1585: void
                   1586: arc_refresh_sensors(void *arg)
                   1587: {
                   1588:        struct arc_softc        *sc = arg;
                   1589:        struct bioc_vol         bv;
                   1590:        int                     i;
                   1591:
                   1592:        for (i = 0; i < sc->sc_nsensors; i++) {
                   1593:                bzero(&bv, sizeof(bv));
                   1594:                bv.bv_volid = i;
                   1595:                if (arc_bio_vol(sc, &bv)) {
                   1596:                        sc->sc_sensors[i].flags = SENSOR_FINVALID;
                   1597:                        return;
                   1598:                }
                   1599:
                   1600:                switch(bv.bv_status) {
                   1601:                case BIOC_SVOFFLINE:
                   1602:                        sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
                   1603:                        sc->sc_sensors[i].status = SENSOR_S_CRIT;
                   1604:                        break;
                   1605:
                   1606:                case BIOC_SVDEGRADED:
                   1607:                        sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
                   1608:                        sc->sc_sensors[i].status = SENSOR_S_WARN;
                   1609:                        break;
                   1610:
                   1611:                case BIOC_SVSCRUB:
                   1612:                case BIOC_SVONLINE:
                   1613:                        sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
                   1614:                        sc->sc_sensors[i].status = SENSOR_S_OK;
                   1615:                        break;
                   1616:
                   1617:                case BIOC_SVINVALID:
                   1618:                        /* FALLTRHOUGH */
                   1619:                default:
                   1620:                        sc->sc_sensors[i].value = 0; /* unknown */
                   1621:                        sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
                   1622:                }
                   1623:
                   1624:        }
                   1625: }
                   1626: #endif /* SMALL_KERNEL */
                   1627: #endif /* NBIO > 0 */
                   1628:
                   1629: u_int32_t
                   1630: arc_read(struct arc_softc *sc, bus_size_t r)
                   1631: {
                   1632:        u_int32_t                       v;
                   1633:
                   1634:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                   1635:            BUS_SPACE_BARRIER_READ);
                   1636:        v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
                   1637:
                   1638:        DNPRINTF(ARC_D_RW, "%s: arc_read 0x%x 0x%08x\n", DEVNAME(sc), r, v);
                   1639:
                   1640:        return (v);
                   1641: }
                   1642:
                   1643: void
                   1644: arc_read_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
                   1645: {
                   1646:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
                   1647:            BUS_SPACE_BARRIER_READ);
                   1648:        bus_space_read_raw_region_4(sc->sc_iot, sc->sc_ioh, r, buf, len);
                   1649: }
                   1650:
                   1651: void
                   1652: arc_write(struct arc_softc *sc, bus_size_t r, u_int32_t v)
                   1653: {
                   1654:        DNPRINTF(ARC_D_RW, "%s: arc_write 0x%x 0x%08x\n", DEVNAME(sc), r, v);
                   1655:
                   1656:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
                   1657:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
                   1658:            BUS_SPACE_BARRIER_WRITE);
                   1659: }
                   1660:
                   1661: void
                   1662: arc_write_region(struct arc_softc *sc, bus_size_t r, void *buf, size_t len)
                   1663: {
                   1664:        bus_space_write_raw_region_4(sc->sc_iot, sc->sc_ioh, r, buf, len);
                   1665:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, len,
                   1666:            BUS_SPACE_BARRIER_WRITE);
                   1667: }
                   1668:
                   1669: int
                   1670: arc_wait_eq(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
                   1671:     u_int32_t target)
                   1672: {
                   1673:        int                             i;
                   1674:
                   1675:        DNPRINTF(ARC_D_RW, "%s: arc_wait_eq 0x%x 0x%08x 0x%08x\n",
                   1676:            DEVNAME(sc), r, mask, target);
                   1677:
                   1678:        for (i = 0; i < 10000; i++) {
                   1679:                if ((arc_read(sc, r) & mask) == target)
                   1680:                        return (0);
                   1681:                delay(1000);
                   1682:        }
                   1683:
                   1684:        return (1);
                   1685: }
                   1686:
                   1687: int
                   1688: arc_wait_ne(struct arc_softc *sc, bus_size_t r, u_int32_t mask,
                   1689:     u_int32_t target)
                   1690: {
                   1691:        int                             i;
                   1692:
                   1693:        DNPRINTF(ARC_D_RW, "%s: arc_wait_ne 0x%x 0x%08x 0x%08x\n",
                   1694:            DEVNAME(sc), r, mask, target);
                   1695:
                   1696:        for (i = 0; i < 10000; i++) {
                   1697:                if ((arc_read(sc, r) & mask) != target)
                   1698:                        return (0);
                   1699:                delay(1000);
                   1700:        }
                   1701:
                   1702:        return (1);
                   1703: }
                   1704:
                   1705: int
                   1706: arc_msg0(struct arc_softc *sc, u_int32_t m)
                   1707: {
                   1708:        /* post message */
                   1709:        arc_write(sc, ARC_REG_INB_MSG0, m);
                   1710:        /* wait for the fw to do it */
                   1711:        if (arc_wait_eq(sc, ARC_REG_INTRSTAT, ARC_REG_INTRSTAT_MSG0,
                   1712:            ARC_REG_INTRSTAT_MSG0) != 0)
                   1713:                return (1);
                   1714:
                   1715:        /* ack it */
                   1716:        arc_write(sc, ARC_REG_INTRSTAT, ARC_REG_INTRSTAT_MSG0);
                   1717:
                   1718:        return (0);
                   1719: }
                   1720:
                   1721: struct arc_dmamem *
                   1722: arc_dmamem_alloc(struct arc_softc *sc, size_t size)
                   1723: {
                   1724:        struct arc_dmamem               *adm;
                   1725:        int                             nsegs;
                   1726:
                   1727:        adm = malloc(sizeof(struct arc_dmamem), M_DEVBUF, M_NOWAIT);
                   1728:        if (adm == NULL)
                   1729:                return (NULL);
                   1730:
                   1731:        bzero(adm, sizeof(struct arc_dmamem));
                   1732:        adm->adm_size = size;
                   1733:
                   1734:        if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
                   1735:            BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &adm->adm_map) != 0)
                   1736:                goto admfree;
                   1737:
                   1738:        if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &adm->adm_seg,
                   1739:            1, &nsegs, BUS_DMA_NOWAIT) != 0)
                   1740:                goto destroy;
                   1741:
                   1742:        if (bus_dmamem_map(sc->sc_dmat, &adm->adm_seg, nsegs, size,
                   1743:            &adm->adm_kva, BUS_DMA_NOWAIT) != 0)
                   1744:                goto free;
                   1745:
                   1746:        if (bus_dmamap_load(sc->sc_dmat, adm->adm_map, adm->adm_kva, size,
                   1747:            NULL, BUS_DMA_NOWAIT) != 0)
                   1748:                goto unmap;
                   1749:
                   1750:        bzero(adm->adm_kva, size);
                   1751:
                   1752:        return (adm);
                   1753:
                   1754: unmap:
                   1755:        bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, size);
                   1756: free:
                   1757:        bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
                   1758: destroy:
                   1759:        bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
                   1760: admfree:
                   1761:        free(adm, M_DEVBUF);
                   1762:
                   1763:        return (NULL);
                   1764: }
                   1765:
                   1766: void
                   1767: arc_dmamem_free(struct arc_softc *sc, struct arc_dmamem *adm)
                   1768: {
                   1769:        bus_dmamap_unload(sc->sc_dmat, adm->adm_map);
                   1770:        bus_dmamem_unmap(sc->sc_dmat, adm->adm_kva, adm->adm_size);
                   1771:        bus_dmamem_free(sc->sc_dmat, &adm->adm_seg, 1);
                   1772:        bus_dmamap_destroy(sc->sc_dmat, adm->adm_map);
                   1773:        free(adm, M_DEVBUF);
                   1774: }
                   1775:
                   1776: int
                   1777: arc_alloc_ccbs(struct arc_softc *sc)
                   1778: {
                   1779:        struct arc_ccb                  *ccb;
                   1780:        u_int8_t                        *cmd;
                   1781:        int                             i;
                   1782:
                   1783:        TAILQ_INIT(&sc->sc_ccb_free);
                   1784:
                   1785:        sc->sc_ccbs = malloc(sizeof(struct arc_ccb) * sc->sc_req_count,
                   1786:            M_DEVBUF, M_WAITOK);
                   1787:        bzero(sc->sc_ccbs, sizeof(struct arc_ccb) * sc->sc_req_count);
                   1788:
                   1789:        sc->sc_requests = arc_dmamem_alloc(sc,
                   1790:            ARC_MAX_IOCMDLEN * sc->sc_req_count);
                   1791:        if (sc->sc_requests == NULL) {
                   1792:                printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
                   1793:                goto free_ccbs;
                   1794:        }
                   1795:        cmd = ARC_DMA_KVA(sc->sc_requests);
                   1796:
                   1797:        for (i = 0; i < sc->sc_req_count; i++) {
                   1798:                ccb = &sc->sc_ccbs[i];
                   1799:
                   1800:                if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, ARC_SGL_MAXLEN,
                   1801:                    MAXPHYS, 0, 0, &ccb->ccb_dmamap) != 0) {
                   1802:                        printf("%s: unable to create dmamap for ccb %d\n",
                   1803:                            DEVNAME(sc), i);
                   1804:                        goto free_maps;
                   1805:                }
                   1806:
                   1807:                ccb->ccb_sc = sc;
                   1808:                ccb->ccb_id = i;
                   1809:                ccb->ccb_offset = ARC_MAX_IOCMDLEN * i;
                   1810:
                   1811:                ccb->ccb_cmd = (struct arc_io_cmd *)&cmd[ccb->ccb_offset];
                   1812:                ccb->ccb_cmd_post = (ARC_DMA_DVA(sc->sc_requests) +
                   1813:                    ccb->ccb_offset) >> ARC_REG_POST_QUEUE_ADDR_SHIFT;
                   1814:
                   1815:                arc_put_ccb(sc, ccb);
                   1816:        }
                   1817:
                   1818:        return (0);
                   1819:
                   1820: free_maps:
                   1821:        while ((ccb = arc_get_ccb(sc)) != NULL)
                   1822:            bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
                   1823:        arc_dmamem_free(sc, sc->sc_requests);
                   1824:
                   1825: free_ccbs:
                   1826:        free(sc->sc_ccbs, M_DEVBUF);
                   1827:
                   1828:        return (1);
                   1829: }
                   1830:
                   1831: struct arc_ccb *
                   1832: arc_get_ccb(struct arc_softc *sc)
                   1833: {
                   1834:        struct arc_ccb                  *ccb;
                   1835:
                   1836:        ccb = TAILQ_FIRST(&sc->sc_ccb_free);
                   1837:        if (ccb != NULL)
                   1838:                TAILQ_REMOVE(&sc->sc_ccb_free, ccb, ccb_link);
                   1839:
                   1840:        return (ccb);
                   1841: }
                   1842:
                   1843: void
                   1844: arc_put_ccb(struct arc_softc *sc, struct arc_ccb *ccb)
                   1845: {
                   1846:        ccb->ccb_xs = NULL;
                   1847:        bzero(ccb->ccb_cmd, ARC_MAX_IOCMDLEN);
                   1848:        TAILQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_link);
                   1849: }

CVSweb