amrvar.h revision 111250
1133359Sobrien/*- 2133359Sobrien * Copyright (c) 1999,2000 Michael Smith 3133359Sobrien * Copyright (c) 2000 BSDi 4133359Sobrien * All rights reserved. 5133359Sobrien * 6133359Sobrien * Redistribution and use in source and binary forms, with or without 7133359Sobrien * modification, are permitted provided that the following conditions 8133359Sobrien * are met: 9133359Sobrien * 1. Redistributions of source code must retain the above copyright 10133359Sobrien * notice, this list of conditions and the following disclaimer. 11133359Sobrien * 2. Redistributions in binary form must reproduce the above copyright 12133359Sobrien * notice, this list of conditions and the following disclaimer in the 13133359Sobrien * documentation and/or other materials provided with the distribution. 14133359Sobrien * 15133359Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16133359Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17133359Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18133359Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19133359Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20133359Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21133359Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22133359Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23133359Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24133359Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25133359Sobrien * SUCH DAMAGE. 26133359Sobrien * 2768349Sobrien * Copyright (c) 2002 Eric Moore 2868349Sobrien * Copyright (c) 2002 LSI Logic Corporation 2968349Sobrien * All rights reserved. 3068349Sobrien * 3168349Sobrien * Redistribution and use in source and binary forms, with or without 3268349Sobrien * modification, are permitted provided that the following conditions 3368349Sobrien * are met: 3468349Sobrien * 1. Redistributions of source code must retain the above copyright 3568349Sobrien * notice, this list of conditions and the following disclaimer. 3668349Sobrien * 2. Redistributions in binary form must reproduce the above copyright 3768349Sobrien * notice, this list of conditions and the following disclaimer in the 38186690Sobrien * documentation and/or other materials provided with the distribution. 3968349Sobrien * 3. The party using or redistributing the source code and binary forms 4068349Sobrien * agrees to the disclaimer below and the terms and conditions set forth 41186690Sobrien * herein. 4268349Sobrien * 4368349Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 4468349Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45169942Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46169942Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4768349Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48169942Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49186690Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50186690Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51186690Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52186690Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53159764Sobrien * SUCH DAMAGE. 5468349Sobrien * 55133359Sobrien * 5668349Sobrien * $FreeBSD: head/sys/dev/amr/amrvar.h 111250 2003-02-22 10:10:12Z phk $ 57159764Sobrien */ 58159764Sobrien 59133359Sobrien#if __FreeBSD_version >= 500005 60133359Sobrien# include <sys/taskqueue.h> 61133359Sobrien#endif 62133359Sobrien 63133359Sobrien#ifdef AMR_DEBUG 64103373Sobrien# define debug(level, fmt, args...) do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0) 6568349Sobrien# define debug_called(level) do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0) 6668349Sobrien#else 6768349Sobrien# define debug(level, fmt, args...) 6868349Sobrien# define debug_called(level) 6968349Sobrien#endif 7068349Sobrien#define xdebug(fmt, args...) printf("%s: " fmt "\n", __func__ , ##args) 7168349Sobrien 7268349Sobrien/* 7368349Sobrien * Per-logical-drive datastructure 7468349Sobrien */ 7568349Sobrienstruct amr_logdrive 7668349Sobrien{ 7768349Sobrien u_int32_t al_size; 7868349Sobrien int al_state; 7968349Sobrien int al_properties; 8068349Sobrien 8168349Sobrien /* synthetic geometry */ 82133359Sobrien int al_cylinders; 83103373Sobrien int al_heads; 8468349Sobrien int al_sectors; 8568349Sobrien 8668349Sobrien /* driver */ 8768349Sobrien device_t al_disk; 8868349Sobrien}; 8968349Sobrien 9068349Sobrien/* 9168349Sobrien * Due to the difficulty of using the zone allocator to create a new 9268349Sobrien * zone from within a module, we use our own clustering to reduce 9368349Sobrien * memory wastage due to allocating lots of these small structures. 9468349Sobrien * 9568349Sobrien * 16k gives us a little under 200 command structures, which should 9668349Sobrien * normally be plenty. We will grab more if we need them. 9768349Sobrien */ 9868349Sobrien 9968349Sobrien#define AMR_CMD_CLUSTERSIZE (16 * 1024) 10068349Sobrien 10168349Sobrien/* 10268349Sobrien * Per-command control structure. 103133359Sobrien */ 104103373Sobrienstruct amr_command 10568349Sobrien{ 10668349Sobrien TAILQ_ENTRY(amr_command) ac_link; 10768349Sobrien 10868349Sobrien struct amr_softc *ac_sc; 10968349Sobrien u_int8_t ac_slot; 11068349Sobrien int ac_status; /* command completion status */ 11168349Sobrien struct amr_mailbox ac_mailbox; 11268349Sobrien int ac_flags; 11368349Sobrien#define AMR_CMD_DATAIN (1<<0) 11468349Sobrien#define AMR_CMD_DATAOUT (1<<1) 11568349Sobrien#define AMR_CMD_CCB_DATAIN (1<<2) 11668349Sobrien#define AMR_CMD_CCB_DATAOUT (1<<3) 11768349Sobrien#define AMR_CMD_PRIORITY (1<<4) 11868349Sobrien#define AMR_CMD_MAPPED (1<<5) 11968349Sobrien#define AMR_CMD_SLEEP (1<<6) 12068349Sobrien#define AMR_CMD_BUSY (1<<7) 12168349Sobrien 12268349Sobrien struct bio *ac_bio; 12368349Sobrien 12468349Sobrien void *ac_data; 12568349Sobrien size_t ac_length; 12668349Sobrien bus_dmamap_t ac_dmamap; 12768349Sobrien u_int32_t ac_dataphys; 128186690Sobrien 129186690Sobrien void *ac_ccb_data; 130159764Sobrien size_t ac_ccb_length; 131159764Sobrien bus_dmamap_t ac_ccb_dmamap; 132186690Sobrien u_int32_t ac_ccb_dataphys; 133186690Sobrien 134159764Sobrien void (* ac_complete)(struct amr_command *ac); 135159764Sobrien void *ac_private; 136159764Sobrien}; 137159764Sobrien 138186690Sobrienstruct amr_command_cluster 139186690Sobrien{ 14068349Sobrien TAILQ_ENTRY(amr_command_cluster) acc_link; 141186690Sobrien struct amr_command acc_command[0]; 142186690Sobrien}; 143111658Sobrien 144186690Sobrien#define AMR_CMD_CLUSTERCOUNT ((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) / \ 145186690Sobrien sizeof(struct amr_command)) 146186690Sobrien 147186690Sobrien/* 148186690Sobrien * Per-controller-instance data 149186690Sobrien */ 150186690Sobrienstruct amr_softc 151186690Sobrien{ 152186690Sobrien /* bus attachments */ 153186690Sobrien device_t amr_dev; 154186690Sobrien struct resource *amr_reg; /* control registers */ 15568349Sobrien bus_space_handle_t amr_bhandle; 156186690Sobrien bus_space_tag_t amr_btag; 157186690Sobrien bus_dma_tag_t amr_parent_dmat; /* parent DMA tag */ 158111658Sobrien bus_dma_tag_t amr_buffer_dmat; /* data buffer DMA tag */ 159186690Sobrien struct resource *amr_irq; /* interrupt */ 160186690Sobrien void *amr_intr; 161186690Sobrien 162186690Sobrien /* mailbox */ 163186690Sobrien volatile struct amr_mailbox *amr_mailbox; 164186690Sobrien volatile struct amr_mailbox64 *amr_mailbox64; 165186690Sobrien u_int32_t amr_mailboxphys; 166186690Sobrien bus_dma_tag_t amr_mailbox_dmat; 167186690Sobrien bus_dmamap_t amr_mailbox_dmamap; 168186690Sobrien 169186690Sobrien /* scatter/gather lists and their controller-visible mappings */ 170186690Sobrien struct amr_sgentry *amr_sgtable; /* s/g lists */ 171186690Sobrien u_int32_t amr_sgbusaddr; /* s/g table base address in bus space */ 172186690Sobrien bus_dma_tag_t amr_sg_dmat; /* s/g buffer DMA tag */ 173186690Sobrien bus_dmamap_t amr_sg_dmamap; /* map for s/g buffers */ 174186690Sobrien 175159764Sobrien /* controller limits and features */ 176186690Sobrien int amr_maxio; /* maximum number of I/O transactions */ 177186690Sobrien int amr_maxdrives; /* max number of logical drives */ 178186690Sobrien int amr_maxchan; /* count of SCSI channels */ 179186690Sobrien 180186690Sobrien /* connected logical drives */ 181133359Sobrien struct amr_logdrive amr_drive[AMR_MAXLD]; 182186690Sobrien 183186690Sobrien /* controller state */ 184186690Sobrien int amr_state; 185186690Sobrien#define AMR_STATE_OPEN (1<<0) 186186690Sobrien#define AMR_STATE_SUSPEND (1<<1) 187186690Sobrien#define AMR_STATE_INTEN (1<<2) 188186690Sobrien#define AMR_STATE_SHUTDOWN (1<<3) 189186690Sobrien 190186690Sobrien /* per-controller queues */ 191186690Sobrien struct bio_queue_head amr_bioq; /* pending I/O with no commands */ 192186690Sobrien TAILQ_HEAD(,amr_command) amr_ready; /* commands ready to be submitted */ 19368349Sobrien struct amr_command *amr_busycmd[AMR_MAXCMD]; 194186690Sobrien int amr_busyslots; 195186690Sobrien TAILQ_HEAD(,amr_command) amr_completed; 196186690Sobrien TAILQ_HEAD(,amr_command) amr_freecmds; 197186690Sobrien TAILQ_HEAD(,amr_command_cluster) amr_cmd_clusters; 198186690Sobrien 199186690Sobrien /* CAM attachments for passthrough */ 200186690Sobrien struct cam_sim *amr_cam_sim[AMR_MAX_CHANNELS]; 201186690Sobrien TAILQ_HEAD(, ccb_hdr) amr_cam_ccbq; 202186690Sobrien 203186690Sobrien /* control device */ 204186690Sobrien dev_t amr_dev_t; 205186690Sobrien 20668349Sobrien /* controller type-specific support */ 20768349Sobrien int amr_type; 208186690Sobrien#define AMR_TYPE_QUARTZ (1<<0) 209186690Sobrien#define AMR_IS_QUARTZ(sc) ((sc)->amr_type & AMR_TYPE_QUARTZ) 210186690Sobrien#define AMR_TYPE_40LD (1<<1) 211186690Sobrien#define AMR_IS_40LD(sc) ((sc)->amr_type & AMR_TYPE_40LD) 212186690Sobrien int (* amr_submit_command)(struct amr_softc *sc); 213186690Sobrien int (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave); 214186690Sobrien int (*amr_poll_command)(struct amr_command *ac); 215186690Sobrien int support_ext_cdb; /* greater than 10 byte cdb support */ 216186690Sobrien 217186690Sobrien /* misc glue */ 218186690Sobrien struct intr_config_hook amr_ich; /* wait-for-interrupts probe hook */ 219186690Sobrien struct callout_handle amr_timeout; /* periodic status check */ 220186690Sobrien#if __FreeBSD_version >= 500005 221186690Sobrien struct task amr_task_complete; /* deferred-completion task */ 222186690Sobrien#endif 223186690Sobrien}; 22468349Sobrien 22568349Sobrien/* 22668349Sobrien * Interface between bus connections and driver core. 227186690Sobrien */ 228186690Sobrienextern int amr_attach(struct amr_softc *sc); 229186690Sobrienextern void amr_free(struct amr_softc *sc); 230186690Sobrienextern int amr_flush(struct amr_softc *sc); 231186690Sobrienextern int amr_done(struct amr_softc *sc); 232186690Sobrienextern void amr_startio(struct amr_softc *sc); 233186690Sobrien 234186690Sobrien/* 235186690Sobrien * Command buffer allocation. 236186690Sobrien */ 237186690Sobrienextern struct amr_command *amr_alloccmd(struct amr_softc *sc); 238186690Sobrienextern void amr_releasecmd(struct amr_command *ac); 239159764Sobrien 24068349Sobrien/* 24168349Sobrien * CAM interface 24268349Sobrien */ 24368349Sobrienextern int amr_cam_attach(struct amr_softc *sc); 24468349Sobrienextern void amr_cam_detach(struct amr_softc *sc); 245186690Sobrienextern int amr_cam_command(struct amr_softc *sc, struct amr_command **acp); 24668349Sobrien 24768349Sobrien/* 24868349Sobrien * MegaRAID logical disk driver 24968349Sobrien */ 25068349Sobrienstruct amrd_softc 25168349Sobrien{ 25268349Sobrien device_t amrd_dev; 25368349Sobrien dev_t amrd_dev_t; 25468349Sobrien struct amr_softc *amrd_controller; 25568349Sobrien struct amr_logdrive *amrd_drive; 25668349Sobrien struct disk amrd_disk; 25768349Sobrien struct devstat amrd_stats; 25868349Sobrien int amrd_unit; 259186690Sobrien}; 260186690Sobrien 261186690Sobrien/* 262186690Sobrien * Interface between driver core and disk driver (should be using a bus?) 263186690Sobrien */ 264186690Sobrienextern int amr_submit_bio(struct amr_softc *sc, struct bio *bio); 265186690Sobrienextern void amrd_intr(void *data); 266186690Sobrien 26768349Sobrien/******************************************************************************** 26868349Sobrien * Enqueue/dequeue functions 26968349Sobrien */ 27068349Sobrienstatic __inline void 27168349Sobrienamr_enqueue_bio(struct amr_softc *sc, struct bio *bio) 27268349Sobrien{ 27368349Sobrien int s; 27468349Sobrien 275103373Sobrien s = splbio(); 276103373Sobrien bioq_insert_tail(&sc->amr_bioq, bio); 277103373Sobrien splx(s); 278103373Sobrien} 279103373Sobrien 280186690Sobrienstatic __inline struct bio * 281103373Sobrienamr_dequeue_bio(struct amr_softc *sc) 282103373Sobrien{ 283103373Sobrien struct bio *bio; 284103373Sobrien int s; 285103373Sobrien 286159764Sobrien s = splbio(); 287169942Sobrien if ((bio = bioq_first(&sc->amr_bioq)) != NULL) 288175296Sobrien bioq_remove(&sc->amr_bioq, bio); 289159764Sobrien splx(s); 290133359Sobrien return(bio); 291186690Sobrien} 292169942Sobrien 29368349Sobrienstatic __inline void 29468349Sobrienamr_enqueue_ready(struct amr_command *ac) 29568349Sobrien{ 296133359Sobrien int s; 297133359Sobrien 298133359Sobrien s = splbio(); 299169942Sobrien TAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link); 300169942Sobrien splx(s); 30168349Sobrien} 302169942Sobrien 303169942Sobrienstatic __inline void 304169942Sobrienamr_requeue_ready(struct amr_command *ac) 305169942Sobrien{ 306169942Sobrien int s; 307159764Sobrien 308133359Sobrien s = splbio(); 309133359Sobrien TAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link); 310133359Sobrien splx(s); 311133359Sobrien} 312159764Sobrien 31368349Sobrienstatic __inline struct amr_command * 31468349Sobrienamr_dequeue_ready(struct amr_softc *sc) 31568349Sobrien{ 31668349Sobrien struct amr_command *ac; 317169942Sobrien int s; 318133359Sobrien 319133359Sobrien s = splbio(); 320133359Sobrien if ((ac = TAILQ_FIRST(&sc->amr_ready)) != NULL) 321159764Sobrien TAILQ_REMOVE(&sc->amr_ready, ac, ac_link); 322133359Sobrien splx(s); 323133359Sobrien return(ac); 324133359Sobrien} 325169942Sobrien 326169942Sobrienstatic __inline void 327169942Sobrienamr_enqueue_completed(struct amr_command *ac) 328169942Sobrien{ 329169942Sobrien int s; 330169942Sobrien 331169942Sobrien s = splbio(); 332169942Sobrien TAILQ_INSERT_TAIL(&ac->ac_sc->amr_completed, ac, ac_link); 33368349Sobrien splx(s); 334159764Sobrien} 33568349Sobrien 33668349Sobrienstatic __inline struct amr_command * 33768349Sobrienamr_dequeue_completed(struct amr_softc *sc) 33868349Sobrien{ 33968349Sobrien struct amr_command *ac; 34068349Sobrien int s; 341169962Sobrien 342133359Sobrien s = splbio(); 343133359Sobrien if ((ac = TAILQ_FIRST(&sc->amr_completed)) != NULL) 344133359Sobrien TAILQ_REMOVE(&sc->amr_completed, ac, ac_link); 345139368Sobrien splx(s); 346159764Sobrien return(ac); 347133359Sobrien} 348133359Sobrien 349133359Sobrienstatic __inline void 350133359Sobrienamr_enqueue_free(struct amr_command *ac) 35168349Sobrien{ 35268349Sobrien int s; 353133359Sobrien 35468349Sobrien s = splbio(); 355133359Sobrien TAILQ_INSERT_TAIL(&ac->ac_sc->amr_freecmds, ac, ac_link); 356186690Sobrien splx(s); 357133359Sobrien} 358133359Sobrien 35968349Sobrienstatic __inline struct amr_command * 360133359Sobrienamr_dequeue_free(struct amr_softc *sc) 361133359Sobrien{ 362133359Sobrien struct amr_command *ac; 363133359Sobrien int s; 364133359Sobrien 365133359Sobrien s = splbio(); 366133359Sobrien if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL) 367186690Sobrien TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link); 368186690Sobrien splx(s); 369133359Sobrien return(ac); 370133359Sobrien} 371133359Sobrien