xref: /dragonfly/sys/dev/raid/twe/twevar.h (revision 7078f92bf00cafccd0c0191c7aa92b0bb784f70e)
1 /*-
2  * Copyright (c) 2000 Michael Smith
3  * Copyright (c) 2000 BSDi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *        $FreeBSD: src/sys/dev/twe/twevar.h,v 1.19 2012/11/17 01:52:19 svnexp Exp $
28  */
29 
30 #define TWE_DRIVER_VERSION_STRING       "1.50.01.002"
31 
32 #ifdef TWE_DEBUG
33 #define debug(level, fmt, args...)                                                                  \
34           do {                                                                                                \
35               if (level <= TWE_DEBUG) kprintf("%s: " fmt "\n", __func__ , ##args);        \
36           } while(0)
37 #define debug_called(level)                                                     \
38           do {                                                                            \
39               if (level <= TWE_DEBUG) kprintf("%s: called\n", __func__);        \
40           } while(0)
41 #else
42 #define debug(level, fmt, args...)
43 #define debug_called(level)
44 #endif
45 
46 /*
47  * Structure describing a logical unit as attached to the controller
48  */
49 struct twe_drive
50 {
51     /* unit properties */
52     u_int32_t                 td_size;
53     int                       td_cylinders;
54     int                       td_heads;
55     int                       td_sectors;
56     int                       td_sys_unit; /* device unit number */
57     int                       td_twe_unit; /* index into sc->twe_drive[] */
58 
59     /* unit state and type */
60     u_int8_t                  td_state;
61     u_int8_t                  td_type;
62 
63     /* handle for attached driver */
64     device_t                  td_disk;
65 };
66 
67 /*
68  * Disk device softc
69  */
70 struct twed_softc
71 {
72     device_t                  twed_dev;
73     cdev_t                    twed_dev_t;
74     struct twe_softc          *twed_controller;   /* parent device softc */
75     struct twe_drive          *twed_drive;                  /* drive data in parent softc */
76     struct disk               twed_disk;                    /* generic disk handle */
77     struct devstat  twed_stats;                   /* accounting */
78     int                       twed_flags;
79 #define TWED_OPEN   (1<<0)                        /* drive is open (can't shut down) */
80 };
81 
82 /*
83  * Per-command control structure.
84  *
85  * Note that due to alignment constraints on the tc_command field, this *must* be 64-byte aligned.
86  * We achieve this by placing the command at the beginning of the structure, and using malloc()
87  * to allocate each structure.
88  */
89 struct twe_request
90 {
91     int                                 tr_tag;
92     /* command payload */
93     void                      *tr_data; /* data buffer */
94     void                      *tr_realdata;       /* copy of real data buffer pointer for alignment fixup */
95     size_t                              tr_length;
96 
97     TAILQ_ENTRY(twe_request)  tr_link;  /* list linkage */
98     struct twe_softc                    *tr_sc;             /* controller that owns us */
99     int                                 tr_status;          /* command status */
100 #define TWE_CMD_SETUP                   0         /* being assembled */
101 #define TWE_CMD_BUSY                    1         /* submitted to controller */
102 #define TWE_CMD_COMPLETE      2         /* completed by controller (maybe with error) */
103 #define TWE_CMD_ERROR                   3         /* encountered error, even before submission to controller */
104     int                                 tr_flags;
105 #define TWE_CMD_DATAIN                  (1<<0)
106 #define TWE_CMD_DATAOUT                 (1<<1)
107 #define TWE_CMD_ALIGNBUF      (1<<2)    /* data in bio is misaligned, have to copy to/from private buffer */
108 #define TWE_CMD_SLEEPER                 (1<<3)    /* owner is sleeping on this command */
109 #define TWE_CMD_IMMEDIATE     (1<<4)    /* immediate request */
110 #define TWE_CMD_MAPPED                  (1<<5)
111 #define TWE_CMD_IN_PROGRESS   (1<<6)    /* bus_dmamap_load returned EINPROGRESS */
112     void                      (* tr_complete)(struct twe_request *tr);          /* completion handler */
113     void                      *tr_private;        /* submitter-private data or wait channel */
114 
115     TWE_PLATFORM_REQUEST      /* platform-specific request elements */
116 };
117 
118 #define TWE_FIND_COMMAND(tr)                                          \
119           (TWE_Command *)((u_int8_t *)(tr)->tr_sc->twe_cmd +          \
120                               ((tr)->tr_tag * sizeof(TWE_Command)))
121 #define TWE_FIND_COMMANDPHYS(tr)        ((tr)->tr_sc->twe_cmdphys +   \
122                                                    ((tr)->tr_tag * sizeof(TWE_Command)))
123 
124 /*
125  * Per-controller state.
126  */
127 struct twe_softc
128 {
129     /* controller queues and arrays */
130     TAILQ_HEAD(, twe_request) twe_free;                     /* command structures available for reuse */
131     struct bio_queue_head     twe_bioq;                     /* outstanding I/O operations */
132     TAILQ_HEAD(, twe_request) twe_ready;                              /* requests ready for the controller */
133     TAILQ_HEAD(, twe_request) twe_busy;                     /* requests busy in the controller */
134     TAILQ_HEAD(, twe_request) twe_complete;                           /* active commands (busy or waiting for completion) */
135     struct twe_request                  *twe_lookup[TWE_Q_LENGTH];    /* commands indexed by request ID */
136     struct twe_drive          twe_drive[TWE_MAX_UNITS];               /* attached drives */
137 
138     /* asynchronous event handling */
139     u_int16_t                 twe_aen_queue[TWE_Q_LENGTH];  /* AENs queued for userland tool(s) */
140     int                       twe_aen_head, twe_aen_tail;   /* ringbuffer pointers for AEN queue */
141     int                       twe_wait_aen;                 /* wait-for-aen notification */
142     char            twe_aen_buf[80];              /* AEN format buffer */
143 
144     /* controller status */
145     int                       twe_state;
146 #define TWE_STATE_INTEN                 (1<<0)    /* interrupts have been enabled */
147 #define TWE_STATE_SHUTDOWN    (1<<1)    /* controller is shut down */
148 #define TWE_STATE_OPEN                  (1<<2)    /* control device is open */
149 #define TWE_STATE_SUSPEND     (1<<3)    /* controller is suspended */
150 #define TWE_STATE_FRZN                  (1<<4)    /* got EINPROGRESS */
151 #define TWE_STATE_CTLR_BUSY   (1<<5)    /* controller cmd queue full */
152 #define   TWE_STATE_DETACHING (1<<6)    /* controller is being shut down */
153     int                       twe_host_id;
154     struct twe_qstat          twe_qstat[TWEQ_COUNT];        /* queue statistics */
155 
156     TWE_PLATFORM_SOFTC                  /* platform-specific softc elements */
157 };
158 
159 /*
160  * Interface betwen driver core and platform-dependant code.
161  */
162 extern int          twe_setup(struct twe_softc *sc);                  /* do early driver/controller setup */
163 extern void         twe_init(struct twe_softc *sc);                             /* init controller */
164 extern void         twe_deinit(struct twe_softc *sc);                 /* stop controller */
165 extern void         twe_intr(struct twe_softc *sc);                             /* hardware interrupt signalled */
166 extern void         twe_startio(struct twe_softc *sc);
167 extern int          twe_start(struct twe_request *tr);
168 extern int          twe_dump_blocks(struct twe_softc *sc, int unit,   /* crashdump block write */
169                                         u_int64_t lba, void *data, int nblks);
170 extern int          twe_ioctl(struct twe_softc *sc, u_long cmd,
171                                           void *addr);                          /* handle user request */
172 extern void         twe_describe_controller(struct twe_softc *sc);    /* print controller info */
173 extern void         twe_print_controller(struct twe_softc *sc);
174 extern void         twe_enable_interrupts(struct twe_softc *sc);      /* enable controller interrupts */
175 extern void         twe_disable_interrupts(struct twe_softc *sc);     /* disable controller interrupts */
176 
177 extern int          twe_attach_drive(struct twe_softc *sc,
178                                                    struct twe_drive *dr); /* attach drive when found in twe_init */
179 extern int          twe_detach_drive(struct twe_softc *sc,
180                                                    int unit);                   /* detach drive */
181 extern void         twe_clear_pci_parity_error(struct twe_softc *sc);
182 extern void         twe_clear_pci_abort(struct twe_softc *sc);
183 extern void         twed_intr(struct bio *bp);                                  /* return bio from core */
184 extern struct twe_request *twe_allocate_request(struct twe_softc *sc, int tag); /* allocate request structure */
185 extern void         twe_free_request(struct twe_request *tr);         /* free request structure */
186 extern int          twe_map_request(struct twe_request *tr);          /* make request visible to controller, do s/g */
187 extern void         twe_unmap_request(struct twe_request *tr);        /* cleanup after transfer, unmap */
188 
189 /********************************************************************************
190  * Queue primitives
191  */
192 #define TWEQ_ADD(sc, qname)                                           \
193           do {                                                                  \
194               struct twe_qstat *qs = &(sc)->twe_qstat[qname];         \
195                                                                                 \
196               qs->q_length++;                                         \
197               if (qs->q_length > qs->q_max)                           \
198                     qs->q_max = qs->q_length;                         \
199           } while(0)
200 
201 #define TWEQ_REMOVE(sc, qname)                                                  \
202           do {                                                                  \
203               struct twe_qstat *qs = &(sc)->twe_qstat[qname];         \
204                                                                                 \
205               qs->q_length--;                                         \
206               if (qs->q_length < qs->q_min)                           \
207                     qs->q_min = qs->q_length;                         \
208           } while(0)
209 
210 #define TWEQ_INIT(sc, qname)                                          \
211           do {                                                                  \
212               sc->twe_qstat[qname].q_length = 0;                      \
213               sc->twe_qstat[qname].q_max = 0;                         \
214               sc->twe_qstat[qname].q_min = 0xFFFFFFFF;                \
215           } while(0)
216 
217 
218 #define TWEQ_REQUEST_QUEUE(name, index)                                         \
219 static __inline void                                                                      \
220 twe_initq_ ## name (struct twe_softc *sc)                                       \
221 {                                                                                         \
222     TAILQ_INIT(&sc->twe_ ## name);                                              \
223     TWEQ_INIT(sc, index);                                                       \
224 }                                                                                         \
225 static __inline void                                                                      \
226 twe_enqueue_ ## name (struct twe_request *tr)                                   \
227 {                                                                                         \
228     TAILQ_INSERT_TAIL(&tr->tr_sc->twe_ ## name, tr, tr_link);                   \
229     TWEQ_ADD(tr->tr_sc, index);                                                           \
230 }                                                                                         \
231 static __inline void                                                                      \
232 twe_requeue_ ## name (struct twe_request *tr)                                   \
233 {                                                                                         \
234     TAILQ_INSERT_HEAD(&tr->tr_sc->twe_ ## name, tr, tr_link);                   \
235     TWEQ_ADD(tr->tr_sc, index);                                                           \
236 }                                                                                         \
237 static __inline struct twe_request *                                            \
238 twe_dequeue_ ## name (struct twe_softc *sc)                                     \
239 {                                                                                         \
240     struct twe_request        *tr;                                                        \
241                                                                                           \
242     if ((tr = TAILQ_FIRST(&sc->twe_ ## name)) != NULL) {              \
243           TAILQ_REMOVE(&sc->twe_ ## name, tr, tr_link);                         \
244           TWEQ_REMOVE(sc, index);                                                         \
245     }                                                                                     \
246     return(tr);                                                                           \
247 }                                                                                         \
248 static __inline void                                                                      \
249 twe_remove_ ## name (struct twe_request *tr)                                    \
250 {                                                                                         \
251     TAILQ_REMOVE(&tr->tr_sc->twe_ ## name, tr, tr_link);              \
252     TWEQ_REMOVE(tr->tr_sc, index);                                              \
253 }
254 
TWEQ_REQUEST_QUEUE(free,TWEQ_FREE)255 TWEQ_REQUEST_QUEUE(free, TWEQ_FREE)
256 TWEQ_REQUEST_QUEUE(ready, TWEQ_READY)
257 TWEQ_REQUEST_QUEUE(busy, TWEQ_BUSY)
258 TWEQ_REQUEST_QUEUE(complete, TWEQ_COMPLETE)
259 
260 /*
261  * outstanding bio queue
262  */
263 static __inline void
264 twe_initq_bio(struct twe_softc *sc)
265 {
266     bioq_init(&sc->twe_bioq);
267     TWEQ_INIT(sc, TWEQ_BIO);
268 }
269 
270 static __inline void
twe_enqueue_bio(struct twe_softc * sc,struct bio * bio)271 twe_enqueue_bio(struct twe_softc *sc, struct bio *bio)
272 {
273     bioqdisksort(&sc->twe_bioq, bio);
274     /* bioq_insert_tail(&sc->twe_bioq, bio); */
275     TWEQ_ADD(sc, TWEQ_BIO);
276 }
277 
278 static __inline
279 struct bio *
twe_dequeue_bio(struct twe_softc * sc)280 twe_dequeue_bio(struct twe_softc *sc)
281 {
282     struct bio *bio;
283 
284     if ((bio = bioq_first(&sc->twe_bioq)) != NULL) {
285           bioq_remove(&sc->twe_bioq, bio);
286           TWEQ_REMOVE(sc, TWEQ_BIO);
287     }
288     return(bio);
289 }
290