PageRenderTime 38ms CodeModel.GetById 22ms app.highlight 14ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/staging/comedi/drivers/icp_multi.h

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C Header | 298 lines | 222 code | 42 blank | 34 comment | 42 complexity | a6738980bbcde97d7a65d9333c55d1f2 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1/*
  2    comedi/drivers/icp_multi.h
  3
  4    Stuff for ICP Multi
  5
  6    Author: Anne Smorthit <anne.smorthit@sfwte.ch>
  7
  8*/
  9
 10#ifndef _ICP_MULTI_H_
 11#define _ICP_MULTI_H_
 12
 13#include "../comedidev.h"
 14#include "comedi_pci.h"
 15
 16/****************************************************************************/
 17
 18struct pcilst_struct {
 19	struct pcilst_struct *next;
 20	int used;
 21	struct pci_dev *pcidev;
 22	unsigned short vendor;
 23	unsigned short device;
 24	unsigned char pci_bus;
 25	unsigned char pci_slot;
 26	unsigned char pci_func;
 27	resource_size_t io_addr[5];
 28	unsigned int irq;
 29};
 30
 31struct pcilst_struct *inova_devices;
 32/* ptr to root list of all Inova devices */
 33
 34/****************************************************************************/
 35
 36static void pci_card_list_init(unsigned short pci_vendor, char display);
 37static void pci_card_list_cleanup(unsigned short pci_vendor);
 38static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
 39							  vendor_id,
 40							  unsigned short
 41							  device_id);
 42static int find_free_pci_card_by_position(unsigned short vendor_id,
 43					  unsigned short device_id,
 44					  unsigned short pci_bus,
 45					  unsigned short pci_slot,
 46					  struct pcilst_struct **card);
 47static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
 48						       unsigned short device_id,
 49						       unsigned short pci_bus,
 50						       unsigned short pci_slot);
 51
 52static int pci_card_alloc(struct pcilst_struct *amcc);
 53static int pci_card_free(struct pcilst_struct *amcc);
 54static void pci_card_list_display(void);
 55static int pci_card_data(struct pcilst_struct *amcc,
 56			 unsigned char *pci_bus, unsigned char *pci_slot,
 57			 unsigned char *pci_func, resource_size_t * io_addr,
 58			 unsigned int *irq);
 59
 60/****************************************************************************/
 61
 62/* build list of Inova cards in this system */
 63static void pci_card_list_init(unsigned short pci_vendor, char display)
 64{
 65	struct pci_dev *pcidev = NULL;
 66	struct pcilst_struct *inova, *last;
 67	int i;
 68
 69	inova_devices = NULL;
 70	last = NULL;
 71
 72	for_each_pci_dev(pcidev) {
 73		if (pcidev->vendor == pci_vendor) {
 74			inova = kzalloc(sizeof(*inova), GFP_KERNEL);
 75			if (!inova) {
 76				printk
 77				    ("icp_multi: pci_card_list_init: allocation failed\n");
 78				pci_dev_put(pcidev);
 79				break;
 80			}
 81
 82			inova->pcidev = pci_dev_get(pcidev);
 83			if (last) {
 84				last->next = inova;
 85			} else {
 86				inova_devices = inova;
 87			}
 88			last = inova;
 89
 90			inova->vendor = pcidev->vendor;
 91			inova->device = pcidev->device;
 92			inova->pci_bus = pcidev->bus->number;
 93			inova->pci_slot = PCI_SLOT(pcidev->devfn);
 94			inova->pci_func = PCI_FUNC(pcidev->devfn);
 95			/* Note: resources may be invalid if PCI device
 96			 * not enabled, but they are corrected in
 97			 * pci_card_alloc. */
 98			for (i = 0; i < 5; i++)
 99				inova->io_addr[i] =
100				    pci_resource_start(pcidev, i);
101			inova->irq = pcidev->irq;
102		}
103	}
104
105	if (display)
106		pci_card_list_display();
107}
108
109/****************************************************************************/
110/* free up list of amcc cards in this system */
111static void pci_card_list_cleanup(unsigned short pci_vendor)
112{
113	struct pcilst_struct *inova, *next;
114
115	for (inova = inova_devices; inova; inova = next) {
116		next = inova->next;
117		pci_dev_put(inova->pcidev);
118		kfree(inova);
119	}
120
121	inova_devices = NULL;
122}
123
124/****************************************************************************/
125/* find first unused card with this device_id */
126static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
127							  vendor_id,
128							  unsigned short
129							  device_id)
130{
131	struct pcilst_struct *inova, *next;
132
133	for (inova = inova_devices; inova; inova = next) {
134		next = inova->next;
135		if ((!inova->used) && (inova->device == device_id)
136		    && (inova->vendor == vendor_id))
137			return inova;
138
139	}
140
141	return NULL;
142}
143
144/****************************************************************************/
145/* find card on requested position */
146static int find_free_pci_card_by_position(unsigned short vendor_id,
147					  unsigned short device_id,
148					  unsigned short pci_bus,
149					  unsigned short pci_slot,
150					  struct pcilst_struct **card)
151{
152	struct pcilst_struct *inova, *next;
153
154	*card = NULL;
155	for (inova = inova_devices; inova; inova = next) {
156		next = inova->next;
157		if ((inova->vendor == vendor_id) && (inova->device == device_id)
158		    && (inova->pci_bus == pci_bus)
159		    && (inova->pci_slot == pci_slot)) {
160			if (!(inova->used)) {
161				*card = inova;
162				return 0;	/* ok, card is found */
163			} else {
164				return 2;	/* card exist but is used */
165			}
166		}
167	}
168
169	return 1;		/* no card found */
170}
171
172/****************************************************************************/
173/* mark card as used */
174static int pci_card_alloc(struct pcilst_struct *inova)
175{
176	int i;
177
178	if (!inova) {
179		printk(" - BUG!! inova is NULL!\n");
180		return -1;
181	}
182
183	if (inova->used)
184		return 1;
185	if (comedi_pci_enable(inova->pcidev, "icp_multi")) {
186		printk(" - Can't enable PCI device and request regions!\n");
187		return -1;
188	}
189	/* Resources will be accurate now. */
190	for (i = 0; i < 5; i++)
191		inova->io_addr[i] = pci_resource_start(inova->pcidev, i);
192	inova->irq = inova->pcidev->irq;
193	inova->used = 1;
194	return 0;
195}
196
197/****************************************************************************/
198/* mark card as free */
199static int pci_card_free(struct pcilst_struct *inova)
200{
201	if (!inova)
202		return -1;
203
204	if (!inova->used)
205		return 1;
206	inova->used = 0;
207	comedi_pci_disable(inova->pcidev);
208	return 0;
209}
210
211/****************************************************************************/
212/* display list of found cards */
213static void pci_card_list_display(void)
214{
215	struct pcilst_struct *inova, *next;
216
217	printk("Anne's List of pci cards\n");
218	printk("bus:slot:func vendor device io_inova io_daq irq used\n");
219
220	for (inova = inova_devices; inova; inova = next) {
221		next = inova->next;
222		printk
223		    ("%2d   %2d   %2d  0x%4x 0x%4x   0x%8llx 0x%8llx  %2u  %2d\n",
224		     inova->pci_bus, inova->pci_slot, inova->pci_func,
225		     inova->vendor, inova->device,
226		     (unsigned long long)inova->io_addr[0],
227		     (unsigned long long)inova->io_addr[2], inova->irq,
228		     inova->used);
229
230	}
231}
232
233/****************************************************************************/
234/* return all card information for driver */
235static int pci_card_data(struct pcilst_struct *inova,
236			 unsigned char *pci_bus, unsigned char *pci_slot,
237			 unsigned char *pci_func, resource_size_t * io_addr,
238			 unsigned int *irq)
239{
240	int i;
241
242	if (!inova)
243		return -1;
244	*pci_bus = inova->pci_bus;
245	*pci_slot = inova->pci_slot;
246	*pci_func = inova->pci_func;
247	for (i = 0; i < 5; i++)
248		io_addr[i] = inova->io_addr[i];
249	*irq = inova->irq;
250	return 0;
251}
252
253/****************************************************************************/
254/* select and alloc card */
255static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
256						       unsigned short device_id,
257						       unsigned short pci_bus,
258						       unsigned short pci_slot)
259{
260	struct pcilst_struct *card;
261	int err;
262
263	if ((pci_bus < 1) & (pci_slot < 1)) {	/* use autodetection */
264
265		card = find_free_pci_card_by_device(vendor_id, device_id);
266		if (card == NULL) {
267			printk(" - Unused card not found in system!\n");
268			return NULL;
269		}
270	} else {
271		switch (find_free_pci_card_by_position(vendor_id, device_id,
272						       pci_bus, pci_slot,
273						       &card)) {
274		case 1:
275			printk
276			    (" - Card not found on requested position b:s %d:%d!\n",
277			     pci_bus, pci_slot);
278			return NULL;
279		case 2:
280			printk
281			    (" - Card on requested position is used b:s %d:%d!\n",
282			     pci_bus, pci_slot);
283			return NULL;
284		}
285	}
286
287	err = pci_card_alloc(card);
288	if (err != 0) {
289		if (err > 0)
290			printk(" - Can't allocate card!\n");
291		/* else: error already printed. */
292		return NULL;
293	}
294
295	return card;
296}
297
298#endif