Linux Audio

Check our new training course

Loading...
  1/*
  2 * Aic94xx SAS/SATA driver hardware interface header file.
  3 *
  4 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
  5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
  6 *
  7 * This file is licensed under GPLv2.
  8 *
  9 * This file is part of the aic94xx driver.
 10 *
 11 * The aic94xx driver is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU General Public License as
 13 * published by the Free Software Foundation; version 2 of the
 14 * License.
 15 *
 16 * The aic94xx driver is distributed in the hope that it will be useful,
 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19 * General Public License for more details.
 20 *
 21 * You should have received a copy of the GNU General Public License
 22 * along with the aic94xx driver; if not, write to the Free Software
 23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 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/* Define ASD_MAX_PHYS to the maximum phys ever. Currently 8. */
 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;       /* pci resource start */
 46	unsigned long  len;         /* pci resource len */
 47	unsigned long  flags;       /* pci resource flags */
 48
 49	/* addresses internal to the host adapter */
 50	u32 swa_base; /* mmspace 1 (MBAR1) uses this only */
 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	/* From CTRL-A settings, then set to what is appropriate */
 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; /* mode 5 reg 0x160 */
 92	u8     phy_control_1; /* mode 5 reg 0x161 */
 93	u8     phy_control_2; /* mode 5 reg 0x162 */
 94	u8     phy_control_3; /* mode 5 reg 0x163 */
 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;	  /* mask of enabled phys */
112	struct asd_phy_desc phy_desc[ASD_MAX_PHYS];
113	u32    max_scbs;	  /* absolute sequencer scb queue size */
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;	  /* ENABLEABLE */
122	int    max_phys;	  /* REPORTED + ENABLEABLE */
123
124	unsigned addr_range;	  /* max # of addrs; max # of possible ports */
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;	  /* equals dma_scb->vaddr */
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	/* internally generated command */
142	struct timer_list timer;
143	struct completion *completion;
144	u8        tag_valid:1;
145	__be16    tag;		  /* error recovery only */
146
147	/* If this is an Empty SCB, index of first edb in seq->edb_arr. */
148	int    edb_index;
149
150	/* Used by the timer timeout function. */
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;	  /* per adapter */
166	struct asd_dma_tok next_scb; /* next scb to be delivered to CSEQ */
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; /* array of done list entries, equals */
175	struct asd_dma_tok *actual_dl; /* actual_dl->vaddr */
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; /* array of pointers to escbs */
183};
184
185/* This is an internal port structure. These are used to get accurate
186 * phy_mask for updating DDB 0.
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/* This is the Host Adapter structure.  It describes the hardware
196 * SAS adapter.
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; /* sequencer related */
220	u32    bios_status;
221	const struct firmware *bios_image;
222};
223
224/* ---------- Common macros ---------- */
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/* For each bit set in __lseq_mask, set __lseq to equal the bit
235 * position of the set bit and execute the statement following.
236 * __mc is the temporary mask, used as a mask "counter".
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/* ---------- DMA allocs ---------- */
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	ascb->timer.function = NULL;
295	init_timer(&ascb->timer);
296	ascb->tc_index = -1;
297}
298
299/* Must be called with the tc_index_lock held!
300 */
301static inline void asd_tc_index_release(struct asd_seq_data *seq, int index)
302{
303	seq->tc_index_array[index] = NULL;
304	clear_bit(index, seq->tc_index_bitmap);
305}
306
307/* Must be called with the tc_index_lock held!
308 */
309static inline int asd_tc_index_get(struct asd_seq_data *seq, void *ptr)
310{
311	int index;
312
313	index = find_first_zero_bit(seq->tc_index_bitmap,
314				    seq->tc_index_bitmap_bits);
315	if (index == seq->tc_index_bitmap_bits)
316		return -1;
317
318	seq->tc_index_array[index] = ptr;
319	set_bit(index, seq->tc_index_bitmap);
320
321	return index;
322}
323
324/* Must be called with the tc_index_lock held!
325 */
326static inline void *asd_tc_index_find(struct asd_seq_data *seq, int index)
327{
328	return seq->tc_index_array[index];
329}
330
331/**
332 * asd_ascb_free -- free a single aSCB after is has completed
333 * @ascb: pointer to the aSCB of interest
334 *
335 * This frees an aSCB after it has been executed/completed by
336 * the sequencer.
337 */
338static inline void asd_ascb_free(struct asd_ascb *ascb)
339{
340	if (ascb) {
341		struct asd_ha_struct *asd_ha = ascb->ha;
342		unsigned long flags;
343
344		BUG_ON(!list_empty(&ascb->list));
345		spin_lock_irqsave(&ascb->ha->seq.tc_index_lock, flags);
346		asd_tc_index_release(&ascb->ha->seq, ascb->tc_index);
347		spin_unlock_irqrestore(&ascb->ha->seq.tc_index_lock, flags);
348		dma_pool_free(asd_ha->scb_pool, ascb->dma_scb.vaddr,
349			      ascb->dma_scb.dma_handle);
350		kmem_cache_free(asd_ascb_cache, ascb);
351	}
352}
353
354/**
355 * asd_ascb_list_free -- free a list of ascbs
356 * @ascb_list: a list of ascbs
357 *
358 * This function will free a list of ascbs allocated by asd_ascb_alloc_list.
359 * It is used when say the scb queueing function returned QUEUE_FULL,
360 * and we do not need the ascbs any more.
361 */
362static inline void asd_ascb_free_list(struct asd_ascb *ascb_list)
363{
364	LIST_HEAD(list);
365	struct list_head *n, *pos;
366
367	__list_add(&list, ascb_list->list.prev, &ascb_list->list);
368	list_for_each_safe(pos, n, &list) {
369		list_del_init(pos);
370		asd_ascb_free(list_entry(pos, struct asd_ascb, list));
371	}
372}
373
374/* ---------- Function declarations ---------- */
375
376int  asd_init_hw(struct asd_ha_struct *asd_ha);
377irqreturn_t asd_hw_isr(int irq, void *dev_id);
378
379
380struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
381				     *asd_ha, int *num,
382				     gfp_t gfp_mask);
383
384int  asd_post_ascb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
385			int num);
386int  asd_post_escb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
387			int num);
388
389int  asd_init_post_escbs(struct asd_ha_struct *asd_ha);
390void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc);
391void asd_control_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
392void asd_turn_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
393int  asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask);
394
395void asd_ascb_timedout(unsigned long data);
396int  asd_chip_hardrst(struct asd_ha_struct *asd_ha);
397
398#endif
  1/* SPDX-License-Identifier: GPL-2.0-only */
  2/*
  3 * Aic94xx SAS/SATA driver hardware interface header file.
  4 *
  5 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
  6 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
  7 */
  8
  9#ifndef _AIC94XX_HWI_H_
 10#define _AIC94XX_HWI_H_
 11
 12#include <linux/interrupt.h>
 13#include <linux/pci.h>
 14#include <linux/dma-mapping.h>
 15
 16#include <scsi/libsas.h>
 17
 18#include "aic94xx.h"
 19#include "aic94xx_sas.h"
 20
 21/* Define ASD_MAX_PHYS to the maximum phys ever. Currently 8. */
 22#define ASD_MAX_PHYS       8
 23#define ASD_PCBA_SN_SIZE   12
 24
 25struct asd_ha_addrspace {
 26	void __iomem  *addr;
 27	unsigned long  start;       /* pci resource start */
 28	unsigned long  len;         /* pci resource len */
 29	unsigned long  flags;       /* pci resource flags */
 30
 31	/* addresses internal to the host adapter */
 32	u32 swa_base; /* mmspace 1 (MBAR1) uses this only */
 33	u32 swb_base;
 34	u32 swc_base;
 35};
 36
 37struct bios_struct {
 38	int    present;
 39	u8     maj;
 40	u8     min;
 41	u32    bld;
 42};
 43
 44struct unit_element_struct {
 45	u16    num;
 46	u16    size;
 47	void   *area;
 48};
 49
 50struct flash_struct {
 51	u32    bar;
 52	int    present;
 53	int    wide;
 54	u8     manuf;
 55	u8     dev_id;
 56	u8     sec_prot;
 57	u8     method;
 58
 59	u32    dir_offs;
 60};
 61
 62struct asd_phy_desc {
 63	/* From CTRL-A settings, then set to what is appropriate */
 64	u8     sas_addr[SAS_ADDR_SIZE];
 65	u8     max_sas_lrate;
 66	u8     min_sas_lrate;
 67	u8     max_sata_lrate;
 68	u8     min_sata_lrate;
 69	u8     flags;
 70#define ASD_CRC_DIS  1
 71#define ASD_SATA_SPINUP_HOLD 2
 72
 73	u8     phy_control_0; /* mode 5 reg 0x160 */
 74	u8     phy_control_1; /* mode 5 reg 0x161 */
 75	u8     phy_control_2; /* mode 5 reg 0x162 */
 76	u8     phy_control_3; /* mode 5 reg 0x163 */
 77};
 78
 79struct asd_dma_tok {
 80	void *vaddr;
 81	dma_addr_t dma_handle;
 82	size_t size;
 83};
 84
 85struct hw_profile {
 86	struct bios_struct bios;
 87	struct unit_element_struct ue;
 88	struct flash_struct flash;
 89
 90	u8     sas_addr[SAS_ADDR_SIZE];
 91	char   pcba_sn[ASD_PCBA_SN_SIZE+1];
 92
 93	u8     enabled_phys;	  /* mask of enabled phys */
 94	struct asd_phy_desc phy_desc[ASD_MAX_PHYS];
 95	u32    max_scbs;	  /* absolute sequencer scb queue size */
 96	struct asd_dma_tok *scb_ext;
 97	u32    max_ddbs;
 98	struct asd_dma_tok *ddb_ext;
 99
100	spinlock_t ddb_lock;
101	void  *ddb_bitmap;
102
103	int    num_phys;	  /* ENABLEABLE */
104	int    max_phys;	  /* REPORTED + ENABLEABLE */
105
106	unsigned addr_range;	  /* max # of addrs; max # of possible ports */
107	unsigned port_name_base;
108	unsigned dev_name_base;
109	unsigned sata_name_base;
110};
111
112struct asd_ascb {
113	struct list_head list;
114	struct asd_ha_struct *ha;
115
116	struct scb *scb;	  /* equals dma_scb->vaddr */
117	struct asd_dma_tok dma_scb;
118	struct asd_dma_tok *sg_arr;
119
120	void (*tasklet_complete)(struct asd_ascb *, struct done_list_struct *);
121	u8     uldd_timer:1;
122
123	/* internally generated command */
124	struct timer_list timer;
125	struct completion *completion;
126	u8        tag_valid:1;
127	__be16    tag;		  /* error recovery only */
128
129	/* If this is an Empty SCB, index of first edb in seq->edb_arr. */
130	int    edb_index;
131
132	/* Used by the timer timeout function. */
133	int    tc_index;
134
135	void   *uldd_task;
136};
137
138#define ASD_DL_SIZE_BITS   0x8
139#define ASD_DL_SIZE        (1<<(2+ASD_DL_SIZE_BITS))
140#define ASD_DEF_DL_TOGGLE  0x01
141
142struct asd_seq_data {
143	spinlock_t pend_q_lock;
144	u16    scbpro;
145	int    pending;
146	struct list_head pend_q;
147	int    can_queue;	  /* per adapter */
148	struct asd_dma_tok next_scb; /* next scb to be delivered to CSEQ */
149
150	spinlock_t tc_index_lock;
151	void **tc_index_array;
152	void *tc_index_bitmap;
153	int   tc_index_bitmap_bits;
154
155	struct tasklet_struct dl_tasklet;
156	struct done_list_struct *dl; /* array of done list entries, equals */
157	struct asd_dma_tok *actual_dl; /* actual_dl->vaddr */
158	int    dl_toggle;
159	int    dl_next;
160
161	int    num_edbs;
162	struct asd_dma_tok **edb_arr;
163	int    num_escbs;
164	struct asd_ascb **escb_arr; /* array of pointers to escbs */
165};
166
167/* This is an internal port structure. These are used to get accurate
168 * phy_mask for updating DDB 0.
169 */
170struct asd_port {
171	u8  sas_addr[SAS_ADDR_SIZE];
172	u8  attached_sas_addr[SAS_ADDR_SIZE];
173	u32 phy_mask;
174	int num_phys;
175};
176
177/* This is the Host Adapter structure.  It describes the hardware
178 * SAS adapter.
179 */
180struct asd_ha_struct {
181	struct pci_dev   *pcidev;
182	const char       *name;
183
184	struct sas_ha_struct sas_ha;
185
186	u8                revision_id;
187
188	int               iospace;
189	spinlock_t        iolock;
190	struct asd_ha_addrspace io_handle[2];
191
192	struct hw_profile hw_prof;
193
194	struct asd_phy    phys[ASD_MAX_PHYS];
195	spinlock_t        asd_ports_lock;
196	struct asd_port   asd_ports[ASD_MAX_PHYS];
197	struct asd_sas_port   ports[ASD_MAX_PHYS];
198
199	struct dma_pool  *scb_pool;
200
201	struct asd_seq_data  seq; /* sequencer related */
202	u32    bios_status;
203	const struct firmware *bios_image;
204};
205
206/* ---------- Common macros ---------- */
207
208#define ASD_BUSADDR_LO(__dma_handle) ((u32)(__dma_handle))
209#define ASD_BUSADDR_HI(__dma_handle) (((sizeof(dma_addr_t))==8)     \
210                                    ? ((u32)((__dma_handle) >> 32)) \
211                                    : ((u32)0))
212
213#define dev_to_asd_ha(__dev)  pci_get_drvdata(to_pci_dev(__dev))
214#define SCB_SITE_VALID(__site_no) (((__site_no) & 0xF0FF) != 0x00FF   \
215				 && ((__site_no) & 0xF0FF) > 0x001F)
216/* For each bit set in __lseq_mask, set __lseq to equal the bit
217 * position of the set bit and execute the statement following.
218 * __mc is the temporary mask, used as a mask "counter".
219 */
220#define for_each_sequencer(__lseq_mask, __mc, __lseq)                        \
221	for ((__mc)=(__lseq_mask),(__lseq)=0;(__mc)!=0;(__lseq++),(__mc)>>=1)\
222		if (((__mc) & 1))
223#define for_each_phy(__lseq_mask, __mc, __lseq)                              \
224	for ((__mc)=(__lseq_mask),(__lseq)=0;(__mc)!=0;(__lseq++),(__mc)>>=1)\
225		if (((__mc) & 1))
226
227#define PHY_ENABLED(_HA, _I) ((_HA)->hw_prof.enabled_phys & (1<<(_I)))
228
229/* ---------- DMA allocs ---------- */
230
231static inline struct asd_dma_tok *asd_dmatok_alloc(gfp_t flags)
232{
233	return kmem_cache_alloc(asd_dma_token_cache, flags);
234}
235
236static inline void asd_dmatok_free(struct asd_dma_tok *token)
237{
238	kmem_cache_free(asd_dma_token_cache, token);
239}
240
241static inline struct asd_dma_tok *asd_alloc_coherent(struct asd_ha_struct *
242						     asd_ha, size_t size,
243						     gfp_t flags)
244{
245	struct asd_dma_tok *token = asd_dmatok_alloc(flags);
246	if (token) {
247		token->size = size;
248		token->vaddr = dma_alloc_coherent(&asd_ha->pcidev->dev,
249						  token->size,
250						  &token->dma_handle,
251						  flags);
252		if (!token->vaddr) {
253			asd_dmatok_free(token);
254			token = NULL;
255		}
256	}
257	return token;
258}
259
260static inline void asd_free_coherent(struct asd_ha_struct *asd_ha,
261				     struct asd_dma_tok *token)
262{
263	if (token) {
264		dma_free_coherent(&asd_ha->pcidev->dev, token->size,
265				  token->vaddr, token->dma_handle);
266		asd_dmatok_free(token);
267	}
268}
269
270static inline void asd_init_ascb(struct asd_ha_struct *asd_ha,
271				 struct asd_ascb *ascb)
272{
273	INIT_LIST_HEAD(&ascb->list);
274	ascb->scb = ascb->dma_scb.vaddr;
275	ascb->ha = asd_ha;
276	timer_setup(&ascb->timer, NULL, 0);
277	ascb->tc_index = -1;
278}
279
280/* Must be called with the tc_index_lock held!
281 */
282static inline void asd_tc_index_release(struct asd_seq_data *seq, int index)
283{
284	seq->tc_index_array[index] = NULL;
285	clear_bit(index, seq->tc_index_bitmap);
286}
287
288/* Must be called with the tc_index_lock held!
289 */
290static inline int asd_tc_index_get(struct asd_seq_data *seq, void *ptr)
291{
292	int index;
293
294	index = find_first_zero_bit(seq->tc_index_bitmap,
295				    seq->tc_index_bitmap_bits);
296	if (index == seq->tc_index_bitmap_bits)
297		return -1;
298
299	seq->tc_index_array[index] = ptr;
300	set_bit(index, seq->tc_index_bitmap);
301
302	return index;
303}
304
305/* Must be called with the tc_index_lock held!
306 */
307static inline void *asd_tc_index_find(struct asd_seq_data *seq, int index)
308{
309	return seq->tc_index_array[index];
310}
311
312/**
313 * asd_ascb_free -- free a single aSCB after is has completed
314 * @ascb: pointer to the aSCB of interest
315 *
316 * This frees an aSCB after it has been executed/completed by
317 * the sequencer.
318 */
319static inline void asd_ascb_free(struct asd_ascb *ascb)
320{
321	if (ascb) {
322		struct asd_ha_struct *asd_ha = ascb->ha;
323		unsigned long flags;
324
325		BUG_ON(!list_empty(&ascb->list));
326		spin_lock_irqsave(&ascb->ha->seq.tc_index_lock, flags);
327		asd_tc_index_release(&ascb->ha->seq, ascb->tc_index);
328		spin_unlock_irqrestore(&ascb->ha->seq.tc_index_lock, flags);
329		dma_pool_free(asd_ha->scb_pool, ascb->dma_scb.vaddr,
330			      ascb->dma_scb.dma_handle);
331		kmem_cache_free(asd_ascb_cache, ascb);
332	}
333}
334
335/**
336 * asd_ascb_list_free -- free a list of ascbs
337 * @ascb_list: a list of ascbs
338 *
339 * This function will free a list of ascbs allocated by asd_ascb_alloc_list.
340 * It is used when say the scb queueing function returned QUEUE_FULL,
341 * and we do not need the ascbs any more.
342 */
343static inline void asd_ascb_free_list(struct asd_ascb *ascb_list)
344{
345	LIST_HEAD(list);
346	struct list_head *n, *pos;
347
348	__list_add(&list, ascb_list->list.prev, &ascb_list->list);
349	list_for_each_safe(pos, n, &list) {
350		list_del_init(pos);
351		asd_ascb_free(list_entry(pos, struct asd_ascb, list));
352	}
353}
354
355/* ---------- Function declarations ---------- */
356
357int  asd_init_hw(struct asd_ha_struct *asd_ha);
358irqreturn_t asd_hw_isr(int irq, void *dev_id);
359
360
361struct asd_ascb *asd_ascb_alloc_list(struct asd_ha_struct
362				     *asd_ha, int *num,
363				     gfp_t gfp_mask);
364
365int  asd_post_ascb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
366			int num);
367int  asd_post_escb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
368			int num);
369
370int  asd_init_post_escbs(struct asd_ha_struct *asd_ha);
371void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc);
372void asd_control_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
373void asd_turn_led(struct asd_ha_struct *asd_ha, int phy_id, int op);
374int  asd_enable_phys(struct asd_ha_struct *asd_ha, const u8 phy_mask);
375
376void asd_ascb_timedout(struct timer_list *t);
377int  asd_chip_hardrst(struct asd_ha_struct *asd_ha);
378
379#endif