1 /*        $NetBSD: icpvar.h,v 1.13 2012/10/27 17:18:20 chs Exp $      */
2 
3 /*-
4  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Andrew Doran, and by Jason R. Thorpe of Wasabi Systems, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef _IC_ICPVAR_H_
33 #define _IC_ICPVAR_H_
34 
35 #include <sys/mutex.h>
36 
37 #include <dev/ic/icp_ioctl.h>
38 
39 /*
40  * Miscellaneous constants.
41  */
42 #define ICP_RETRIES           6
43 #define   ICP_WATCHDOG_FREQ   5
44 #define   ICP_BUSY_WAIT_MS    2500
45 #define   ICP_MAX_XFER                  65536
46 #define   ICP_UCMD_SCRATCH_SIZE         4096
47 #define ICP_SCRATCH_SIZE      (8192 + ICP_UCMD_SCRATCH_SIZE)
48 #define   ICP_SCRATCH_SENSE \
49     (ICP_SCRATCH_SIZE - sizeof(struct scsi_sense_data) * (ICP_NCCBS + ICP_NCCB_RESERVE))
50 #define   ICP_SCRATCH_UCMD    (ICP_SCRATCH_SENSE - ICP_UCMD_SCRATCH_SIZE)
51 
52 #define   ICP_NCCBS           ICP_MAX_CMDS
53 #define   ICP_NCCB_RESERVE    4
54 
55 /*
56  * Context structure for interrupt service.
57  */
58 struct icp_intr_ctx {
59           u_int32_t info;
60           u_int32_t info2;
61           u_int16_t cmd_status;
62           u_int16_t service;
63           u_int8_t  istatus;
64 };
65 
66 /*
67  * Command control block.
68  */
69 struct icp_ccb {
70           SIMPLEQ_ENTRY(icp_ccb) ic_chain;
71           u_int               ic_service;
72           u_int               ic_flags;
73           u_int               ic_status;
74           u_int               ic_ident;
75           u_int               ic_nsgent;
76           u_int               ic_cmdlen;
77           u_int               ic_xfer_size;
78           bus_dmamap_t        ic_xfer_map;
79           struct icp_sg       *ic_sg;
80           device_t  ic_dv;
81           void                *ic_context;
82           void                (*ic_intr)(struct icp_ccb *);
83           struct icp_cmd      ic_cmd;
84 };
85 #define   IC_XFER_IN          0x01      /* Map describes inbound xfer */
86 #define   IC_XFER_OUT         0x02      /* Map describes outbound xfer */
87 #define   IC_WAITING          0x04      /* We have waiters */
88 #define   IC_COMPLETE         0x08      /* Command completed */
89 #define   IC_ALLOCED          0x10      /* CCB allocated */
90 #define   IC_UCMD             0x20      /* user ioctl */
91 
92 /*
93  * Logical drive information.
94  */
95 struct icp_cachedrv {
96           u_int               cd_size;
97           u_int               cd_type;
98 };
99 
100 /*
101  * Call-backs into the service back-ends (ld for cache service,
102  * icpsp for raw service).
103  */
104 struct icp_servicecb {
105           void      (*iscb_openings)(device_t, int);
106 };
107 
108 /*
109  * Per-controller context.
110  */
111 struct icp_softc {
112           device_t            icp_dv;
113           void                          *icp_ih;
114           bus_dma_tag_t                 icp_dmat;
115           bus_space_tag_t               icp_dpmemt;
116           bus_space_handle_t  icp_dpmemh;
117           bus_addr_t                    icp_dpmembase;
118           bus_space_tag_t               icp_iot;
119           bus_space_handle_t  icp_ioh;
120           bus_addr_t                    icp_iobase;
121 
122           int                           icp_class;
123           u_int16_t           icp_fw_vers;
124           u_int16_t           icp_ic_all_size;
125           u_int8_t            icp_bus_cnt;
126           u_int8_t            icp_bus_id[ICP_MAXBUS];
127           struct icp_cachedrv icp_cdr[ICP_MAX_HDRIVES];
128           const struct icp_servicecb *icp_servicecb[ICP_MAX_HDRIVES + ICP_MAXBUS];
129           device_t            icp_children[ICP_MAX_HDRIVES + ICP_MAXBUS];
130           int                           icp_ndevs;
131           int                           icp_openings;
132           int                           icp_features;
133           int                           icp_nchan;
134 
135           u_int32_t           icp_info;
136           u_int32_t           icp_info2;
137           u_int16_t           icp_status;
138           u_int16_t           icp_service;
139 
140           bus_dmamap_t                  icp_scr_dmamap;
141           bus_dma_segment_t   icp_scr_seg[1];
142           void *                        icp_scr;
143 
144           struct icp_ccb                *icp_ccbs;
145           u_int                         icp_nccbs;
146           u_int                         icp_flags;
147           u_int                         icp_qfreeze;
148           u_int                         icp_running;
149           SIMPLEQ_HEAD(,icp_ccb)        icp_ccb_freelist;
150           SIMPLEQ_HEAD(,icp_ccb)        icp_ccb_queue;
151           SIMPLEQ_HEAD(,icp_ccb)        icp_ucmd_queue;
152           struct callout                icp_wdog_callout;
153 
154           struct icp_ccb                *icp_ucmd_ccb;
155 
156           /* Temporary buffer for event data. */
157           gdt_evt_data                  icp_evt;
158 
159           void                (*icp_copy_cmd)(struct icp_softc *, struct icp_ccb *);
160           u_int8_t  (*icp_get_status)(struct icp_softc *);
161           void                (*icp_intr)(struct icp_softc *, struct icp_intr_ctx *);
162           void                (*icp_release_event)(struct icp_softc *,
163                                                        struct icp_ccb *);
164           void                (*icp_set_sema0)(struct icp_softc *);
165           int                 (*icp_test_busy)(struct icp_softc *);
166 
167           /*
168            * This info is needed by the user ioctl interface needed to
169            * support the ICP configuration tools.
170            */
171           int                           icp_pci_bus;
172           int                           icp_pci_device;
173           int                           icp_pci_device_id;
174           int                           icp_pci_subdevice_id;
175 };
176 
177 /* icp_features */
178 #define   ICP_FEAT_CACHESERVICE         0x01      /* cache service usable */
179 #define   ICP_FEAT_RAWSERVICE 0x02      /* raw service usable */
180 
181 /* icp_flags */
182 #define   ICP_F_WAIT_CCB                0x01      /* someone waiting for CCBs */
183 #define   ICP_F_WAIT_FREEZE   0x02      /* someone waiting for qfreeze */
184 
185 #define   ICP_HAS_WORK(icp)                                                     \
186           (! SIMPLEQ_EMPTY(&(icp)->icp_ccb_queue) ||                            \
187            ! SIMPLEQ_EMPTY(&(icp)->icp_ucmd_queue))
188 
189 #define   ICP_STAT_INCR(icp, x)                                                           \
190 do {                                                                                      \
191           /* XXX Globals, for now. XXX */                                                 \
192           icp_stats. ## x ## _act++;                                            \
193           if (icp_stats. ## x ## _act > icp_stats. ## x ## _max)                \
194                     icp_stats. ## x ## _max = icp_stats. ## x ## _act;          \
195 } while (/*CONSTCOND*/0)
196 
197 #define   ICP_STAT_SET(icp, x, v)                                                         \
198 do {                                                                                      \
199           /* XXX Globals, for now. XXX */                                                 \
200           icp_stats. ## x ## _act = (v);                                                  \
201           if (icp_stats. ## x ## _act > icp_stats. ## x ## _max)                \
202                     icp_stats. ## x ## _max = icp_stats. ## x ## _act;          \
203 } while (/*CONSTCOND*/0)
204 
205 #define   ICP_STAT_DECR(icp, x)                                                           \
206 do {                                                                                      \
207           /* XXX Globals, for now. XXX */                                                 \
208           icp_stats. ## x ## _act--;                                            \
209 } while (/*CONSTCOND*/0)
210 
211 #define ICP_ISA               0x01
212 #define ICP_EISA    0x02
213 #define ICP_PCI               0x03
214 #define ICP_PCINEW  0x04
215 #define ICP_MPR               0x05
216 #define ICP_CLASS_MASK        0x07
217 #define ICP_FC                0x10
218 #define ICP_CLASS(icp)        ((icp)->icp_class & ICP_CLASS_MASK)
219 
220 int       icp_init(struct icp_softc *, const char *);
221 int       icp_intr(void *);
222 
223 extern int icp_count;
224 extern gdt_statist_t icp_stats;
225 
226 /*
227  * Consumer interface.
228  */
229 struct icp_attach_args {
230           int                 icpa_unit;
231 };
232 
233 #define   ICPA_UNIT_SCSI      100
234 
235 struct icp_ccb      *icp_ccb_alloc(struct icp_softc *);
236 struct icp_ccb      *icp_ccb_alloc_wait(struct icp_softc *);
237 void      icp_ccb_enqueue(struct icp_softc *, struct icp_ccb *);
238 void      icp_ccb_free(struct icp_softc *, struct icp_ccb *);
239 int       icp_ccb_map(struct icp_softc *, struct icp_ccb *, void *, int, int);
240 int       icp_ccb_poll(struct icp_softc *, struct icp_ccb *, int);
241 void      icp_ccb_unmap(struct icp_softc *, struct icp_ccb *);
242 int       icp_ccb_wait(struct icp_softc *, struct icp_ccb *, int);
243 int       icp_ccb_wait_user(struct icp_softc *, struct icp_ccb *, int);
244 int       icp_cmd(struct icp_softc *, u_int8_t, u_int16_t, u_int32_t, u_int32_t,
245                     u_int32_t);
246 int       icp_ucmd(struct icp_softc *, gdt_ucmd_t *);
247 int       icp_freeze(struct icp_softc *);
248 void      icp_unfreeze(struct icp_softc *);
249 
250 void      icp_rescan(struct icp_softc *, int);
251 void      icp_rescan_all(struct icp_softc *);
252 
253 void      icp_register_servicecb(struct icp_softc *, int,
254               const struct icp_servicecb *);
255 
256 gdt_evt_str *icp_store_event(struct icp_softc *, u_int16_t, u_int16_t,
257               gdt_evt_data *);
258 int       icp_read_event(struct icp_softc *, int, gdt_evt_str *);
259 void      icp_readapp_event(struct icp_softc *, u_int8_t, gdt_evt_str *);
260 void      icp_clear_events(struct icp_softc *);
261 
262 extern kmutex_t icp_ioctl_mutex;
263 
264 #endif    /* !_IC_ICPVAR_H_ */
265