151974Smsmith/*- 265245Smsmith * Copyright (c) 1999,2000 Michael Smith 365245Smsmith * Copyright (c) 2000 BSDi 451974Smsmith * All rights reserved. 551974Smsmith * 651974Smsmith * Redistribution and use in source and binary forms, with or without 751974Smsmith * modification, are permitted provided that the following conditions 851974Smsmith * are met: 951974Smsmith * 1. Redistributions of source code must retain the above copyright 1051974Smsmith * notice, this list of conditions and the following disclaimer. 1151974Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1251974Smsmith * notice, this list of conditions and the following disclaimer in the 1351974Smsmith * documentation and/or other materials provided with the distribution. 1451974Smsmith * 1551974Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1651974Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1751974Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1851974Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1951974Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2051974Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2151974Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2251974Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2351974Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2451974Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2551974Smsmith * SUCH DAMAGE. 2651974Smsmith * 27106225Semoore * Copyright (c) 2002 Eric Moore 28106225Semoore * Copyright (c) 2002 LSI Logic Corporation 29106225Semoore * All rights reserved. 30106225Semoore * 31106225Semoore * Redistribution and use in source and binary forms, with or without 32106225Semoore * modification, are permitted provided that the following conditions 33106225Semoore * are met: 34106225Semoore * 1. Redistributions of source code must retain the above copyright 35106225Semoore * notice, this list of conditions and the following disclaimer. 36106225Semoore * 2. Redistributions in binary form must reproduce the above copyright 37106225Semoore * notice, this list of conditions and the following disclaimer in the 38106225Semoore * documentation and/or other materials provided with the distribution. 39105419Semoore * 3. The party using or redistributing the source code and binary forms 40106225Semoore * agrees to the disclaimer below and the terms and conditions set forth 41105419Semoore * herein. 42105419Semoore * 43106225Semoore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 44106225Semoore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45106225Semoore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46106225Semoore * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 47106225Semoore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48106225Semoore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49106225Semoore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50106225Semoore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51106225Semoore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52106225Semoore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53106225Semoore * SUCH DAMAGE. 54105419Semoore * 55106225Semoore * 5651974Smsmith * $FreeBSD$ 5751974Smsmith */ 5851974Smsmith 59148841Sscottl#include <geom/geom_disk.h> 60148841Sscottl#include <sys/lock.h> 61148841Sscottl#include <sys/mutex.h> 6251974Smsmith 63153409Sscottl#define LSI_DESC_PCI "LSILogic MegaRAID 1.53" 64140688Sscottl 6565245Smsmith#ifdef AMR_DEBUG 6687599Sobrien# define debug(level, fmt, args...) do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0) 6787599Sobrien# define debug_called(level) do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0) 6865245Smsmith#else 69210570Smdf# define debug(level, fmt, args...) do {} while (0) 70210570Smdf# define debug_called(level) do {} while (0) 7165245Smsmith#endif 7287599Sobrien#define xdebug(fmt, args...) printf("%s: " fmt "\n", __func__ , ##args) 7351974Smsmith 7451974Smsmith/* 7551974Smsmith * Per-logical-drive datastructure 7651974Smsmith */ 7751974Smsmithstruct amr_logdrive 7851974Smsmith{ 7951974Smsmith u_int32_t al_size; 8051974Smsmith int al_state; 8151974Smsmith int al_properties; 8251974Smsmith 8351974Smsmith /* synthetic geometry */ 8451974Smsmith int al_cylinders; 8551974Smsmith int al_heads; 8651974Smsmith int al_sectors; 8751974Smsmith 8851974Smsmith /* driver */ 8951974Smsmith device_t al_disk; 9051974Smsmith}; 9151974Smsmith 9265245Smsmith/* 9365245Smsmith * Due to the difficulty of using the zone allocator to create a new 9465245Smsmith * zone from within a module, we use our own clustering to reduce 9565245Smsmith * memory wastage due to allocating lots of these small structures. 9665245Smsmith * 9765245Smsmith * 16k gives us a little under 200 command structures, which should 9865245Smsmith * normally be plenty. We will grab more if we need them. 9965245Smsmith */ 10051974Smsmith 10165245Smsmith#define AMR_CMD_CLUSTERSIZE (16 * 1024) 10265245Smsmith 103175622Sscottltypedef STAILQ_HEAD(, amr_command) ac_qhead_t; 104175622Sscottltypedef STAILQ_ENTRY(amr_command) ac_link_t; 105175622Sscottl 106174544Sscottlunion amr_ccb { 107174544Sscottl struct amr_passthrough ccb_pthru; 108174544Sscottl struct amr_ext_passthrough ccb_epthru; 109174544Sscottl uint8_t bytes[128]; 110174544Sscottl}; 111174544Sscottl 11251974Smsmith/* 11351974Smsmith * Per-command control structure. 11451974Smsmith */ 11551974Smsmithstruct amr_command 11651974Smsmith{ 117175622Sscottl ac_link_t ac_link; 11851974Smsmith 11951974Smsmith struct amr_softc *ac_sc; 12051974Smsmith u_int8_t ac_slot; 12165245Smsmith int ac_status; /* command completion status */ 122153409Sscottl union { 123153409Sscottl struct amr_sgentry *sg32; 124153409Sscottl struct amr_sg64entry *sg64; 125153409Sscottl } ac_sg; 126153409Sscottl u_int32_t ac_sgbusaddr; 127153409Sscottl u_int32_t ac_sg64_lo; 128153409Sscottl u_int32_t ac_sg64_hi; 12951974Smsmith struct amr_mailbox ac_mailbox; 13051974Smsmith int ac_flags; 13151974Smsmith#define AMR_CMD_DATAIN (1<<0) 13251974Smsmith#define AMR_CMD_DATAOUT (1<<1) 133174544Sscottl#define AMR_CMD_CCB (1<<2) 13465245Smsmith#define AMR_CMD_PRIORITY (1<<4) 13565245Smsmith#define AMR_CMD_MAPPED (1<<5) 13665245Smsmith#define AMR_CMD_SLEEP (1<<6) 13765245Smsmith#define AMR_CMD_BUSY (1<<7) 138153409Sscottl#define AMR_CMD_SG64 (1<<8) 139153409Sscottl#define AC_IS_SG64(ac) ((ac)->ac_flags & AMR_CMD_SG64) 140175622Sscottl u_int ac_retries; 14151974Smsmith 14265245Smsmith struct bio *ac_bio; 143153409Sscottl void (* ac_complete)(struct amr_command *ac); 144153409Sscottl void *ac_private; 14565245Smsmith 14651974Smsmith void *ac_data; 14751974Smsmith size_t ac_length; 14851974Smsmith bus_dmamap_t ac_dmamap; 149153409Sscottl bus_dmamap_t ac_dma64map; 15051974Smsmith 151174544Sscottl bus_dma_tag_t ac_tag; 152174544Sscottl bus_dmamap_t ac_datamap; 153174544Sscottl int ac_nsegments; 154174544Sscottl uint32_t ac_mb_physaddr; 15565245Smsmith 156174544Sscottl union amr_ccb *ac_ccb; 157174544Sscottl uint32_t ac_ccb_busaddr; 15851974Smsmith}; 15951974Smsmith 16065245Smsmithstruct amr_command_cluster 16165245Smsmith{ 16265245Smsmith TAILQ_ENTRY(amr_command_cluster) acc_link; 16365245Smsmith struct amr_command acc_command[0]; 16465245Smsmith}; 16565245Smsmith 16665245Smsmith#define AMR_CMD_CLUSTERCOUNT ((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) / \ 16765245Smsmith sizeof(struct amr_command)) 16865245Smsmith 16965245Smsmith/* 17065245Smsmith * Per-controller-instance data 17165245Smsmith */ 17251974Smsmithstruct amr_softc 17351974Smsmith{ 17451974Smsmith /* bus attachments */ 17551974Smsmith device_t amr_dev; 17651974Smsmith struct resource *amr_reg; /* control registers */ 17751974Smsmith bus_space_handle_t amr_bhandle; 17851974Smsmith bus_space_tag_t amr_btag; 17951974Smsmith bus_dma_tag_t amr_parent_dmat; /* parent DMA tag */ 18051974Smsmith bus_dma_tag_t amr_buffer_dmat; /* data buffer DMA tag */ 181153409Sscottl bus_dma_tag_t amr_buffer64_dmat; 18251974Smsmith struct resource *amr_irq; /* interrupt */ 18351974Smsmith void *amr_intr; 18451974Smsmith 18551974Smsmith /* mailbox */ 18658496Smsmith volatile struct amr_mailbox *amr_mailbox; 18758496Smsmith volatile struct amr_mailbox64 *amr_mailbox64; 18851974Smsmith u_int32_t amr_mailboxphys; 18951974Smsmith bus_dma_tag_t amr_mailbox_dmat; 19051974Smsmith bus_dmamap_t amr_mailbox_dmamap; 19151974Smsmith 19251974Smsmith /* scatter/gather lists and their controller-visible mappings */ 19351974Smsmith struct amr_sgentry *amr_sgtable; /* s/g lists */ 194153409Sscottl struct amr_sg64entry *amr_sg64table; /* 64bit s/g lists */ 19551974Smsmith u_int32_t amr_sgbusaddr; /* s/g table base address in bus space */ 19651974Smsmith bus_dma_tag_t amr_sg_dmat; /* s/g buffer DMA tag */ 19751974Smsmith bus_dmamap_t amr_sg_dmamap; /* map for s/g buffers */ 19851974Smsmith 199174544Sscottl union amr_ccb *amr_ccb; 200174544Sscottl uint32_t amr_ccb_busaddr; 201174544Sscottl bus_dma_tag_t amr_ccb_dmat; 202174544Sscottl bus_dmamap_t amr_ccb_dmamap; 203174544Sscottl 20451974Smsmith /* controller limits and features */ 205140340Sscottl int amr_nextslot; /* Next slot to use for newly allocated commands */ 20651974Smsmith int amr_maxio; /* maximum number of I/O transactions */ 20751974Smsmith int amr_maxdrives; /* max number of logical drives */ 20865245Smsmith int amr_maxchan; /* count of SCSI channels */ 20951974Smsmith 21051974Smsmith /* connected logical drives */ 21151974Smsmith struct amr_logdrive amr_drive[AMR_MAXLD]; 21251974Smsmith 21365245Smsmith /* controller state */ 21451974Smsmith int amr_state; 21551974Smsmith#define AMR_STATE_OPEN (1<<0) 21651974Smsmith#define AMR_STATE_SUSPEND (1<<1) 21751974Smsmith#define AMR_STATE_INTEN (1<<2) 21851974Smsmith#define AMR_STATE_SHUTDOWN (1<<3) 219131394Sps#define AMR_STATE_CRASHDUMP (1<<4) 220138422Sscottl#define AMR_STATE_QUEUE_FRZN (1<<5) 221153409Sscottl#define AMR_STATE_LD_DELETE (1<<6) 222153409Sscottl#define AMR_STATE_REMAP_LD (1<<7) 22351974Smsmith 22451974Smsmith /* per-controller queues */ 22565245Smsmith struct bio_queue_head amr_bioq; /* pending I/O with no commands */ 226175622Sscottl ac_qhead_t amr_ready; /* commands ready to be submitted */ 22751974Smsmith struct amr_command *amr_busycmd[AMR_MAXCMD]; 22865245Smsmith int amr_busyslots; 229175622Sscottl ac_qhead_t amr_freecmds; 23065245Smsmith TAILQ_HEAD(,amr_command_cluster) amr_cmd_clusters; 23151974Smsmith 23265245Smsmith /* CAM attachments for passthrough */ 23365245Smsmith struct cam_sim *amr_cam_sim[AMR_MAX_CHANNELS]; 23465245Smsmith TAILQ_HEAD(, ccb_hdr) amr_cam_ccbq; 235139952Sdwhite struct cam_devq *amr_cam_devq; 23658883Smsmith 23765245Smsmith /* control device */ 238153409Sscottl struct cdev *amr_dev_t; 239153409Sscottl struct mtx amr_list_lock; 24065245Smsmith 24151974Smsmith /* controller type-specific support */ 24251974Smsmith int amr_type; 24365245Smsmith#define AMR_TYPE_QUARTZ (1<<0) 24465245Smsmith#define AMR_IS_QUARTZ(sc) ((sc)->amr_type & AMR_TYPE_QUARTZ) 24565245Smsmith#define AMR_TYPE_40LD (1<<1) 24665245Smsmith#define AMR_IS_40LD(sc) ((sc)->amr_type & AMR_TYPE_40LD) 247153409Sscottl#define AMR_TYPE_SG64 (1<<2) 248153409Sscottl#define AMR_IS_SG64(sc) ((sc)->amr_type & AMR_TYPE_SG64) 249155222Sps int (* amr_submit_command)(struct amr_command *ac); 25051974Smsmith int (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave); 251107756Semoore int (*amr_poll_command)(struct amr_command *ac); 252138422Sscottl int (*amr_poll_command1)(struct amr_softc *sc, struct amr_command *ac); 253107756Semoore int support_ext_cdb; /* greater than 10 byte cdb support */ 25465245Smsmith 25565245Smsmith /* misc glue */ 256184573Sscottl device_t amr_pass; 257184573Sscottl int (*amr_cam_command)(struct amr_softc *sc, struct amr_command **acp); 25865245Smsmith struct intr_config_hook amr_ich; /* wait-for-interrupts probe hook */ 259153409Sscottl int amr_allow_vol_config; 260153409Sscottl int amr_linux_no_adapters; 261153409Sscottl int amr_ld_del_supported; 262153409Sscottl struct mtx amr_hw_lock; 26351974Smsmith}; 26451974Smsmith 26551974Smsmith/* 26665245Smsmith * Interface between bus connections and driver core. 26758883Smsmith */ 26865245Smsmithextern int amr_attach(struct amr_softc *sc); 26965245Smsmithextern void amr_free(struct amr_softc *sc); 27065245Smsmithextern int amr_flush(struct amr_softc *sc); 27165245Smsmithextern int amr_done(struct amr_softc *sc); 27265245Smsmithextern void amr_startio(struct amr_softc *sc); 27358883Smsmith 27458883Smsmith/* 27565245Smsmith * Command buffer allocation. 27651974Smsmith */ 27765245Smsmithextern struct amr_command *amr_alloccmd(struct amr_softc *sc); 27865245Smsmithextern void amr_releasecmd(struct amr_command *ac); 27951974Smsmith 28051974Smsmith/* 28151974Smsmith * MegaRAID logical disk driver 28251974Smsmith */ 28351974Smsmithstruct amrd_softc 28451974Smsmith{ 28551974Smsmith device_t amrd_dev; 28651974Smsmith struct amr_softc *amrd_controller; 28751974Smsmith struct amr_logdrive *amrd_drive; 288125975Sphk struct disk *amrd_disk; 28951974Smsmith int amrd_unit; 29051974Smsmith}; 29151974Smsmith 29251974Smsmith/* 29351974Smsmith * Interface between driver core and disk driver (should be using a bus?) 29451974Smsmith */ 29565245Smsmithextern int amr_submit_bio(struct amr_softc *sc, struct bio *bio); 296120988Spsextern int amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks); 29751974Smsmithextern void amrd_intr(void *data); 29851974Smsmith 29965245Smsmith/******************************************************************************** 30065245Smsmith * Enqueue/dequeue functions 30165245Smsmith */ 30265245Smsmithstatic __inline void 30365245Smsmithamr_enqueue_bio(struct amr_softc *sc, struct bio *bio) 30465245Smsmith{ 30565245Smsmith 30665245Smsmith bioq_insert_tail(&sc->amr_bioq, bio); 30765245Smsmith} 30865245Smsmith 30965245Smsmithstatic __inline struct bio * 31065245Smsmithamr_dequeue_bio(struct amr_softc *sc) 31165245Smsmith{ 31265245Smsmith struct bio *bio; 31365245Smsmith 31465245Smsmith if ((bio = bioq_first(&sc->amr_bioq)) != NULL) 31565245Smsmith bioq_remove(&sc->amr_bioq, bio); 31665245Smsmith return(bio); 31765245Smsmith} 31865245Smsmith 31965245Smsmithstatic __inline void 320175622Sscottlamr_init_qhead(ac_qhead_t *head) 321175622Sscottl{ 322175622Sscottl 323175622Sscottl STAILQ_INIT(head); 324175622Sscottl} 325175622Sscottl 326175622Sscottlstatic __inline void 32765245Smsmithamr_enqueue_ready(struct amr_command *ac) 32865245Smsmith{ 32965245Smsmith 330175622Sscottl STAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link); 33165245Smsmith} 33265245Smsmith 33365245Smsmithstatic __inline void 33465245Smsmithamr_requeue_ready(struct amr_command *ac) 33565245Smsmith{ 33665245Smsmith 337175622Sscottl STAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link); 33865245Smsmith} 33965245Smsmith 34065245Smsmithstatic __inline struct amr_command * 34165245Smsmithamr_dequeue_ready(struct amr_softc *sc) 34265245Smsmith{ 34365245Smsmith struct amr_command *ac; 34465245Smsmith 345175622Sscottl if ((ac = STAILQ_FIRST(&sc->amr_ready)) != NULL) 346175622Sscottl STAILQ_REMOVE_HEAD(&sc->amr_ready, ac_link); 34765245Smsmith return(ac); 34865245Smsmith} 34965245Smsmith 35065245Smsmithstatic __inline void 351175622Sscottlamr_enqueue_completed(struct amr_command *ac, ac_qhead_t *head) 35265245Smsmith{ 35365245Smsmith 354175622Sscottl STAILQ_INSERT_TAIL(head, ac, ac_link); 35565245Smsmith} 35665245Smsmith 35765245Smsmithstatic __inline struct amr_command * 358175622Sscottlamr_dequeue_completed(struct amr_softc *sc, ac_qhead_t *head) 35965245Smsmith{ 36065245Smsmith struct amr_command *ac; 36165245Smsmith 362175622Sscottl if ((ac = STAILQ_FIRST(head)) != NULL) 363175622Sscottl STAILQ_REMOVE_HEAD(head, ac_link); 36465245Smsmith return(ac); 36565245Smsmith} 36665245Smsmith 36765245Smsmithstatic __inline void 36865245Smsmithamr_enqueue_free(struct amr_command *ac) 36965245Smsmith{ 37065245Smsmith 371175622Sscottl STAILQ_INSERT_HEAD(&ac->ac_sc->amr_freecmds, ac, ac_link); 37265245Smsmith} 37365245Smsmith 37465245Smsmithstatic __inline struct amr_command * 37565245Smsmithamr_dequeue_free(struct amr_softc *sc) 37665245Smsmith{ 37765245Smsmith struct amr_command *ac; 37865245Smsmith 379175622Sscottl if ((ac = STAILQ_FIRST(&sc->amr_freecmds)) != NULL) 380175622Sscottl STAILQ_REMOVE_HEAD(&sc->amr_freecmds, ac_link); 38165245Smsmith return(ac); 38265245Smsmith} 383