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 | |