1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#ifndef _AIC94XX_HWI_H_
28#define _AIC94XX_HWI_H_
29
30#include <linux/interrupt.h>
31#include <linux/pci.h>
32#include <linux/dma-mapping.h>
33
34#include <scsi/libsas.h>
35
36#include "aic94xx.h"
37#include "aic94xx_sas.h"
38
39
40#define ASD_MAX_PHYS 8
41#define ASD_PCBA_SN_SIZE 12
42
43struct asd_ha_addrspace {
44 void __iomem *addr;
45 unsigned long start;
46 unsigned long len;
47 unsigned long flags;
48
49
50 u32 swa_base;
51 u32 swb_base;
52 u32 swc_base;
53};
54
55struct bios_struct {
56 int present;
57 u8 maj;
58 u8 min;
59 u32 bld;
60};
61
62struct unit_element_struct {
63 u16 num;
64 u16 size;
65 void *area;
66};
67
68struct flash_struct {
69 u32 bar;
70 int present;
71 int wide;
72 u8 manuf;
73 u8 dev_id;
74 u8 sec_prot;
75 u8 method;
76
77 u32 dir_offs;
78};
79
80struct asd_phy_desc {
81
82 u8 sas_addr[SAS_ADDR_SIZE];
83 u8 max_sas_lrate;
84 u8 min_sas_lrate;
85 u8 max_sata_lrate;
86 u8 min_sata_lrate;
87 u8 flags;
88#define ASD_CRC_DIS 1
89#define ASD_SATA_SPINUP_HOLD 2
90
91 u8 phy_control_0;
92 u8 phy_control_1;
93 u8 phy_control_2;
94 u8 phy_control_3;
95};
96
97struct asd_dma_tok {
98 void *vaddr;
99 dma_addr_t dma_handle;
100 size_t size;
101};
102
103struct hw_profile {
104 struct bios_struct bios;
105 struct unit_element_struct ue;
106 struct flash_struct flash;
107
108 u8 sas_addr[SAS_ADDR_SIZE];
109 char pcba_sn[ASD_PCBA_SN_SIZE+1];
110
111 u8 enabled_phys;
112 struct asd_phy_desc phy_desc[ASD_MAX_PHYS];
113 u32 max_scbs;
114 struct asd_dma_tok *scb_ext;
115 u32 max_ddbs;
116 struct asd_dma_tok *ddb_ext;
117
118 spinlock_t ddb_lock;
119 void *ddb_bitmap;
120
121 int num_phys;
122 int max_phys;
123
124 unsigned addr_range;
125 unsigned port_name_base;
126 unsigned dev_name_base;
127 unsigned sata_name_base;
128};
129
130struct asd_ascb {
131 struct list_head list;
132 struct asd_ha_struct *ha;
133
134 struct scb *scb;
135 struct asd_dma_tok dma_scb;
136 struct asd_dma_tok *sg_arr;
137
138 void (*tasklet_complete)(struct asd_ascb *, struct done_list_struct *);
139 u8 uldd_timer:1;
140
141
142 struct timer_list timer;
143 struct completion *completion;
144 u8 tag_valid:1;
145 __be16 tag;
146
147
148 int edb_index;
149
150
151 int tc_index;
152
153 void *uldd_task;
154};
155
156#define ASD_DL_SIZE_BITS 0x8
157#define ASD_DL_SIZE (1<<(2+ASD_DL_SIZE_BITS))
158#define ASD_DEF_DL_TOGGLE 0x01
159
160struct asd_seq_data {
161 spinlock_t pend_q_lock;
162 u16 scbpro;
163 int pending;
164 struct list_head pend_q;
165 int can_queue;
166 struct asd_dma_tok next_scb;
167
168 spinlock_t tc_index_lock;
169 void **tc_index_array;
170 void *tc_index_bitmap;
171 int tc_index_bitmap_bits;
172
173 struct tasklet_struct dl_tasklet;
174 struct done_list_struct *dl;
175 struct asd_dma_tok *actual_dl;
176 int dl_toggle;
177 int dl_next;
178
179 int num_edbs;
180 struct asd_dma_tok **edb_arr;
181 int num_escbs;
182 struct asd_ascb **escb_arr;
183};
184
185
186
187
188struct asd_port {
189 u8 sas_addr[SAS_ADDR_SIZE];
190 u8 attached_sas_addr[SAS_ADDR_SIZE];
191 u32 phy_mask;
192 int num_phys;
193};
194
195
196
197
198struct asd_ha_struct {
199 struct pci_dev *pcidev;
200 const char *name;
201
202 struct sas_ha_struct sas_ha;
203
204 u8 revision_id;
205
206 int iospace;
207 spinlock_t iolock;
208 struct asd_ha_addrspace io_handle[2];
209
210 struct hw_profile hw_prof;
211
212 struct asd_phy phys[ASD_MAX_PHYS];
213 spinlock_t asd_ports_lock;
214 struct asd_port asd_ports[ASD_MAX_PHYS];
215 struct asd_sas_port ports[ASD_MAX_PHYS];
216
217 struct dma_pool *scb_pool;
218
219 struct asd_seq_data seq;
220 u32 bios_status;
221 const struct firmware *bios_image;
222};
223
224
225
226#define ASD_BUSADDR_LO(__dma_handle) ((u32)(__dma_handle))
227#define ASD_BUSADDR_HI(__dma_handle) (((sizeof(dma_addr_t))==8) \
228 ? ((u32)((__dma_handle) >> 32)) \
229 : ((u32)0))
230
231#define dev_to_asd_ha(__dev) pci_get_drvdata(to_pci_dev(__dev))
232#define SCB_SITE_VALID(__site_no) (((__site_no) & 0xF0FF) != 0x00FF \
233 && ((__site_no) & 0xF0FF) > 0x001F)
234
235
236
237
238#define for_each_sequencer(__lseq_mask, __mc, __lseq) \
239 for ((__mc)=(__lseq_mask),(__lseq)=0;(__mc)!=0;(__lseq++),(__mc)>>=1)\
240 if (((__mc) & 1))
241#define for_each_phy(__lseq_mask, __mc, __lseq) \
242 for ((__mc)=(__lseq_mask),(__lseq)=0;(__mc)!=0;(__lseq++),(__mc)>>=1)\
243 if (((__mc) & 1))
244
245#define PHY_ENABLED(_HA, _I) ((_HA)->hw_prof.enabled_phys & (1<<(_I)))
246
247
248
249static inline struct asd_dma_tok *asd_dmatok_alloc(gfp_t flags)
250{
251 return kmem_cache_alloc(asd_dma_token_cache, flags);
252}
253
254static inline void asd_dmatok_free(struct asd_dma_tok *token)
255{
256 kmem_cache_free(asd_dma_token_cache, token);
257}
258
259static inline struct asd_dma_tok *asd_alloc_coherent(struct asd_ha_struct *
260 asd_ha, size_t size,
261 gfp_t flags)
262{
263 struct asd_dma_tok *token = asd_dmatok_alloc(flags);
264 if (token) {
265 token->size = size;
266 token->vaddr = dma_alloc_coherent(&asd_ha->pcidev->dev,
267 token->size,
268 &token->dma_handle,
269 flags);
270 if (!token->vaddr) {
271 asd_dmatok_free(token);
272 token = NULL;
273 }
274 }
275 return token;
276}
277
278static inline void asd_free_coherent(struct asd_ha_struct *asd_ha,
279 struct asd_dma_tok *token)
280{
281 if (token) {
282 dma_free_coherent(&asd_ha->pcidev->dev, token->size,
283 token->vaddr, token->dma_handle);
284 asd_dmatok_free(token);
285 }
286}
287
288static inline void asd_init_ascb(struct asd_ha_struct *asd_ha,
289 struct asd_ascb *ascb)
290{
291 INIT_LIST_HEAD(&ascb->list);
292 ascb->scb = ascb->dma_scb.vaddr;
293 ascb->ha = asd_ha;
294 timer_setup(&ascb->timer, NULL, 0);
295 ascb->tc_index = -1;
296}
297
298
299
300static inline void asd_tc_index_release(struct asd_seq_data *seq, int index)
301{
302 seq->tc_index_array[index] = NULL;
303 clear_bit(index, seq->tc_index_bitmap);
304}
305
306
307
308static inline int asd_tc_index_get(struct asd_seq_data *seq, void *ptr)
309{
310 int index;
311
312 index = find_first_zero_bit(seq->tc_index_bitmap,
313 seq->tc_index_bitmap_bits);
314 if (index == seq->tc_index_bitmap_bits)
315 return -1;
316
317 seq->tc_index_array[index] = ptr;
318 set_bit(index, seq->tc_index_bitmap);
319
320 return index;
321}
322
323
324
325static inline void *asd_tc_index_find(struct asd_seq_data *seq, int index)
326{
327 return seq->tc_index_array[index];
328}
329
330
331
332
333
334
335
336
337static inline void asd_ascb_free(struct asd_ascb *ascb)
338{
339 if (ascb) {
340 struct asd_ha_struct *asd_ha = ascb->ha;
341 unsigned long flags;
342
343 BUG_ON(!list_empty(&ascb->list));
344 spin_lock_irqsave(&ascb->ha->seq.tc_index_lock, flags);
345 asd_tc_index_release(&ascb->ha->seq, ascb->tc_index);
346 spin_unlock_irqrestore(&ascb->ha->seq.tc_index_lock, flags);
347 dma_pool_free(asd_ha->scb_pool, ascb->dma_scb.vaddr,
348 ascb->dma_scb.dma_handle);
349 kmem_cache_free(asd_ascb_cache, ascb);
350 }
351}
352
353
354
355
356
357
358
359
360
361static inline void asd_ascb_free_list(struct asd_ascb *ascb_list)
362{
363 LIST_HEAD(list);
364 struct list_head *n, *pos;
365
366 __list_add(&list, ascb_list->list.prev, &ascb_list->list);
367 list_for_each_safe(pos, n, &list) {
368 list_del_init(pos);
369 asd_ascb_free(list_entry(pos, struct asd_ascb, list));
370 }
371}
372
373
374
375int asd_init_hw(struct asd_ha_struct *asd_ha);
376irqreturn_t asd_hw_isr(int irq, void *dev_id);
377
378
379struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
380 *asd_ha, int *num,
381 gfp_t gfp_mask);
382
383int asd_post_ascb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
384 int num);
385int asd_post_escb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
386 int num);
387
388int asd_init_post_escbs(struct asd_ha_struct *asd_ha);
389void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc);
390void asd_control_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
391void asd_turn_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
392int asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask);
393
394void asd_ascb_timedout(struct timer_list *t);
395int asd_chip_hardrst(struct asd_ha_struct *asd_ha);
396
397#endif
398