source: drsdaq/VME/struck/sis1100/V2.02/dev/pci/sis1100_autoconf_linux.c.~1.5.~@ 23

Last change on this file since 23 was 22, checked in by ogrimm, 16 years ago
First commit of drsdaq program
File size: 15.3 KB
Line 
1/* $ZEL: sis1100_autoconf_linux.c,v 1.5 2004/05/27 23:10:17 wuestner Exp $ */
2
3/*
4 * Copyright (c) 2001-2004
5 * Matthias Drochner, Peter Wuestner. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include "sis1100_sc.h"
30
31int sis1100_major = -1;
32
33struct pci_device_id sis1100_table[]={
34 {
35 PCI_VENDOR_FZJZEL, PCI_PRODUCT_FZJZEL_GIGALINK,
36 PCI_ANY_ID, PCI_ANY_ID,
37 0, 0,
38 0
39 },
40 { 0 }
41};
42
43MODULE_AUTHOR("Peter Wuestner <P.Wuestner@fz-juelich.de>");
44MODULE_DESCRIPTION("SIS1100 PCI-VME link/interface (http://zelweb.zel.kfa-juelich.de/projects/gigalink/)");
45#ifdef MODULE_LICENSE
46MODULE_LICENSE("GPL");
47#endif
48MODULE_SUPPORTED_DEVICE("sis1100/sis3100/sis5100; http://www.struck.de/pcivme.htm");
49
50#define DRIVER_VERSION "2.02 alpha"
51
52struct sis1100_softc *sis1100_devdata[sis1100_MAXCARDS];
53
54struct file_operations sis1100_fops = {
55 .owner = THIS_MODULE,
56 .llseek = sis1100_llseek,
57 .read = sis1100_read,
58 .write = sis1100_write,
59 .ioctl = sis1100_ioctl,
60 .mmap = sis1100_mmap,
61 .poll = sis1100_poll,
62 .open = sis1100_open,
63 .release = sis1100_release,
64};
65
66/*
67struct module *owner;
68loff_t (*llseek) (struct file *, loff_t, int);
69ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
70ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
71ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
72ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
73int (*readdir) (struct file *, void *, filldir_t);
74unsigned int (*poll) (struct file *, struct poll_table_struct *);
75int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
76int (*mmap) (struct file *, struct vm_area_struct *);
77int (*open) (struct inode *, struct file *);
78int (*flush) (struct file *);
79int (*release) (struct inode *, struct file *);
80int (*fsync) (struct file *, struct dentry *, int datasync);
81int (*aio_fsync) (struct kiocb *, int datasync);
82int (*fasync) (int, struct file *, int);
83int (*lock) (struct file *, int, struct file_lock *);
84ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
85ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
86ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void __user *);
87ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
88unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
89*/
90
91#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
92
93#define dev2pci(d) container_of(d, struct pci_dev, dev)
94#define dev2sc(d) pci_get_drvdata(dev2pci(d))
95
96ssize_t
97show_driver_version(struct device* d, char *buf)
98{
99 return snprintf(buf, PAGE_SIZE, DRIVER_VERSION "\n");
100}
101ssize_t
102show_physaddr_plx(struct device* d, char *buf)
103{
104 struct sis1100_softc *sc=dev2sc(d);
105 return snprintf(buf, PAGE_SIZE, "0x%08lx\n", sc->plx_addr);
106}
107ssize_t
108show_physaddr_reg(struct device* d, char *buf)
109{
110 struct sis1100_softc *sc=dev2sc(d);
111 return snprintf(buf, PAGE_SIZE, "0x%08lx\n", sc->reg_addr);
112}
113ssize_t
114show_physaddr_rem(struct device* d, char *buf)
115{
116 struct sis1100_softc *sc=dev2sc(d);
117 return snprintf(buf, PAGE_SIZE, "0x%08lx\n", sc->rem_addr);
118}
119ssize_t
120show_remote_size(struct device* d, char *buf)
121{
122 struct sis1100_softc *sc=dev2sc(d);
123 return snprintf(buf, PAGE_SIZE, "0x%x\n", sc->rem_size);
124}
125ssize_t
126show_local_version(struct device* d, char *buf)
127{
128 struct sis1100_softc *sc=dev2sc(d);
129 return snprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
130 sc->local_ident&0xff,
131 (sc->local_ident>>8)&0xff,
132 (sc->local_ident>>16)&0xff,
133 (sc->local_ident>>24)&0xff);
134}
135ssize_t
136show_remote_version(struct device* d, char *buf)
137{
138 struct sis1100_softc *sc=dev2sc(d);
139 if (sc->remote_hw==sis1100_hw_invalid) {
140 return snprintf(buf, PAGE_SIZE, "0 0 0 0\n");
141 } else {
142 return snprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
143 sc->remote_ident&0xff,
144 (sc->remote_ident>>8)&0xff,
145 (sc->remote_ident>>16)&0xff,
146 (sc->remote_ident>>24)&0xff);
147 }
148}
149
150ssize_t
151dummy_store(struct device* d, const char *buf, size_t count)
152{
153 return 0;
154}
155
156DEVICE_ATTR(driver_version, 0444, show_driver_version, dummy_store);
157DEVICE_ATTR(physaddr_plx, 0444, show_physaddr_plx, dummy_store);
158DEVICE_ATTR(physaddr_reg, 0444, show_physaddr_reg, dummy_store);
159DEVICE_ATTR(physaddr_rem, 0444, show_physaddr_rem, dummy_store);
160DEVICE_ATTR(remote_size, 0444, show_remote_size, dummy_store);
161DEVICE_ATTR(local_version, 0444, show_local_version, dummy_store);
162DEVICE_ATTR(remote_version, 0444, show_remote_version, dummy_store);
163
164#endif /* KERNEL_VERSION >= 2.6.0 */
165
166void __init sis1100_print_info(void)
167{
168 printk(KERN_INFO "SIS1100 driver V" DRIVER_VERSION
169 " (c) 08.Jan.2004 FZ Juelich\n");
170}
171
172int __init
173sis1100_linux_init(struct pci_dev *dev)
174{
175 struct sis1100_softc *sc;
176 int i, idx, res;
177
178#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
179 printk(KERN_INFO "sis1100: found %s at %s\n", dev->name, dev->slot_name);
180#else
181 printk(KERN_INFO "sis1100: found sis1100 at %s\n", dev->slot_name);
182#endif
183/*
184 printk(KERN_INFO "vendor=0x%04x\n", dev->vendor);
185 printk(KERN_INFO "device=0x%04x\n", dev->device);
186 printk(KERN_INFO "sub_vendor=0x%04x\n", dev->subsystem_vendor);
187 printk(KERN_INFO "sub_device=0x%04x\n", dev->subsystem_device);
188 printk(KERN_INFO "class=%d\n", dev->class);
189#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
190 printk(KERN_INFO "name=>%s<\n", dev->name);
191#else
192 printk(KERN_INFO "name=>%s<\n", dev->dev.name);
193#endif
194 printk(KERN_INFO "slot_name=>%s<\n", dev->slot_name);
195*/
196 for (idx = 0; idx < sis1100_MAXCARDS; idx++) {
197 if (!sis1100_devdata[idx]) break;
198 }
199 if (idx == sis1100_MAXCARDS) return -ENOMEM;
200
201 sc = kmalloc(sizeof(struct sis1100_softc), GFP_KERNEL);
202 if (!sc) return -ENOMEM;
203 sis1100_devdata[idx] = sc;
204 sc->unit = idx;
205
206 for (i=0; i<=sis1100_MINORUTMASK; i++) sc->fdatalist[i]=0;
207
208 init_waitqueue_head(&sc->handler_wait);
209 init_waitqueue_head(&sc->local_wait);
210 init_waitqueue_head(&sc->remoteirq_wait);
211 init_timer(&sc->link_up_timer);
212 sc->link_up_timer.function=sis1100_link_up_handler;
213 sc->link_up_timer.data=(unsigned long)sc;
214
215 init_MUTEX (&sc->sem_hw);
216 init_MUTEX (&sc->sem_fdata_list);
217 spin_lock_init(&sc->lock_intcsr);
218 spin_lock_init(&sc->handlercommand.lock);
219 spin_lock_init(&sc->lock_doorbell);
220 spin_lock_init(&sc->lock_lemo_status);
221 sc->handlercommand.command=0;
222 INIT_LIST_HEAD(&sc->fdata_list_head);
223 init_completion(&sc->handler_completion);
224
225 sc->handler_pid=kernel_thread(sis1100_irq_thread, sc, 0);
226 if (sc->handler_pid<0) {
227 printk(KERN_ERR "create sis1100_irq_handler: %d\n", sc->handler_pid);
228 res=sc->handler_pid;
229 goto fehler_kmalloc_sc;
230 }
231
232 sc->plxmembase=0;
233 sc->reg_base=0;
234 sc->rem_base=0;
235
236 sc->plx_addr = pci_resource_start(dev, 0);
237 sc->plxmemlen = pci_resource_len(dev, 0);
238 sc->plxmembase = ioremap_nocache(sc->plx_addr, sc->plxmemlen);
239 printk(KERN_INFO "sis1100: plx_addr=0x%08lx\n", sc->plx_addr);
240 printk(KERN_INFO "mapped at %p (size=0x%x)\n", sc->plxmembase, sc->plxmemlen);
241 if (!sc->plxmembase) {
242 res=-ENOMEM;
243 printk(KERN_ERR "sis1100: can't map plx space\n");
244 goto fehler_ioremap;
245 }
246 sc->reg_addr = pci_resource_start(dev, 2);
247 sc->reg_size = pci_resource_len(dev, 2);
248 sc->reg_base = ioremap_nocache(sc->reg_addr, sc->reg_size);
249 printk(KERN_INFO "sis1100: reg_addr=0x%08lx\n", sc->reg_addr);
250 printk(KERN_INFO "mapped at %p (size=0x%x)\n", sc->reg_base, sc->reg_size);
251 if (!sc->reg_base) {
252 res=-ENOMEM;
253 printk(KERN_ERR "sis1100: can't map register space\n");
254 goto fehler_ioremap;
255 }
256 sc->rem_addr = pci_resource_start(dev, 3);
257 sc->rem_size = pci_resource_len(dev, 3);
258 printk(KERN_INFO "sis1100: rem_addr=0x%08lx\n", sc->rem_addr);
259 printk(KERN_INFO "sis1100: rem_size=0x%08lx\n", (unsigned long)sc->rem_size);
260 do {
261 sc->rem_base = ioremap_nocache(sc->rem_addr, sc->rem_size);
262 if (!sc->rem_base) sc->rem_size>>=1;
263 } while (!sc->rem_base && sc->rem_size);
264 if (sc->rem_base) {
265 printk(KERN_INFO "sis1100: rem_addr=0x%08lx\n", sc->rem_addr);
266 printk(KERN_INFO "mapped at %p (size=0x%x)\n", sc->rem_base, sc->rem_size);
267 } else {
268 printk(KERN_WARNING "sis1100: can't map remote space (size=0x%x)\n", sc->rem_size);
269 printk(KERN_WARNING "sis1100: mmap not available\n");
270 sc->rem_size=0;
271 }
272 res = pci_request_regions(dev, "sis1100");
273 if (res)
274 goto fehler_ioremap;
275
276 res = request_irq(dev->irq, sis1100_intr, SA_SHIRQ, "sis1100", sc);
277 if (res) {
278 printk(KERN_WARNING "sis1100: error installing irq\n");
279 goto fehler_request_regions;
280 }
281
282 sc->pcidev = dev;
283 pci_set_drvdata(dev, sc);
284
285 pci_set_master(dev);
286
287#if 0
288 sc->no_dma=0;
289 /*if (!pci_set_dma_mask(dev, 0xffffffffffffffff)) {
290 printk(KERN_WARNING "sis1100: 64bit DMA available (but not used yet).\n");
291 sc->dma_dac=1;
292 } else*/ if (!pci_set_dma_mask(dev, 0xffffffff)) {
293 sc->dma_dac=0;
294 } else {
295 printk(KERN_WARNING "sis1100: DMA not available.\n");
296 sc->no_dma=1; /* not used yet */
297 }
298#endif
299 if (pci_set_dma_mask(dev, 0xffffffff)) {
300 printk(KERN_WARNING "sis1100: DMA not available.\n");
301 goto fehler_request_irq;
302 }
303#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
304 pci_set_consistent_dma_mask(dev, 0xffffffff);
305#endif
306
307#ifndef USE_SGL
308 if ((res=alloc_kiovec(1, &sc->iobuf))<0) {
309 sc->iobuf=0;
310 goto fehler_request_irq;
311 }
312#endif
313 sc->descbuf.size=SGL_SIZE*sizeof(struct plx9054_dmadesc);
314 sc->descbuf.cpu_addr=pci_alloc_consistent(sc->pcidev,
315 sc->descbuf.size, &sc->descbuf.dma_handle);
316 if (!sc->descbuf.cpu_addr) {
317 printk(KERN_ERR "sis1100: pci_alloc_consistent failed\n");
318 res=-ENOMEM;
319 goto fehler_alloc_kiovec;
320 }
321 /*mem_map_reserve(virt_to_page(sc->descbuf.cpu_addr));*/
322 printk(KERN_INFO "sis1100: descbuf.dma_handle=0x%08llx\n",
323 (unsigned long long)sc->descbuf.dma_handle);
324 /*
325 printk(KERN_INFO "sis1100: descbuf.cpu_addr=0x%08llx\n",
326 (unsigned long long)sc->descbuf.cpu_addr);
327 */
328 res=-sis1100_init(sc);
329 if (res) {
330 goto fehler_alloc_descbuf;
331 }
332
333#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
334/* create files for sysfs */
335 device_create_file(&dev->dev, &dev_attr_driver_version);
336 device_create_file(&dev->dev, &dev_attr_physaddr_plx);
337 device_create_file(&dev->dev, &dev_attr_physaddr_reg);
338 device_create_file(&dev->dev, &dev_attr_physaddr_rem);
339 device_create_file(&dev->dev, &dev_attr_remote_size);
340 device_create_file(&dev->dev, &dev_attr_local_version);
341 device_create_file(&dev->dev, &dev_attr_remote_version);
342#endif
343
344 return 0;
345
346/*fehler_sis1100_init:*/
347 sis1100_done(sc);
348
349fehler_alloc_descbuf:
350 /*mem_map_unreserve(virt_to_page(sc->descbuf.cpu_addr));*/
351 pci_free_consistent(sc->pcidev, sc->descbuf.size,
352 sc->descbuf.cpu_addr, sc->descbuf.dma_handle);
353
354fehler_alloc_kiovec:
355#ifndef USE_SGL
356 free_kiovec(1, &sc->iobuf);
357 /*mem_map_unreserve(virt_to_page(sc->descbuf.cpu_addr));*/
358#endif
359
360fehler_request_irq:
361 free_irq(dev->irq, sc);
362
363fehler_request_regions:
364 pci_release_regions(dev);
365
366fehler_ioremap:
367 if (sc->plxmembase) iounmap((void *)sc->plxmembase);
368 if (sc->reg_base) iounmap((void *)sc->reg_base);
369 if (sc->rem_base) iounmap((void *)sc->rem_base);
370
371/*fehler_irq_thread:*/
372 {
373 unsigned long flags;
374 spin_lock_irqsave(&sc->handlercommand.lock, flags);
375 sc->handlercommand.command=handlercomm_die;
376 spin_unlock_irqrestore(&sc->handlercommand.lock, flags);
377 wake_up(&sc->handler_wait);
378 wait_for_completion (&sc->handler_completion);
379 }
380
381fehler_kmalloc_sc:
382 sis1100_devdata[sc->unit] = 0;
383 kfree(sc);
384 pci_set_drvdata(dev, NULL);
385 if (res>=0) {
386 printk(KERN_ERR "sis1100_linux_init: res=%d\n", res);
387 res=-EINVAL;
388 }
389 return res;
390}
391
392void __exit
393sis1100_linux_done(struct pci_dev *dev)
394{
395 struct sis1100_softc *sc;
396
397 sc = pci_get_drvdata(dev);
398
399#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
400/* delete files from sysfs */
401 device_remove_file(&dev->dev, &dev_attr_driver_version);
402 device_remove_file(&dev->dev, &dev_attr_physaddr_plx);
403 device_remove_file(&dev->dev, &dev_attr_physaddr_reg);
404 device_remove_file(&dev->dev, &dev_attr_physaddr_rem);
405 device_remove_file(&dev->dev, &dev_attr_remote_size);
406 device_remove_file(&dev->dev, &dev_attr_local_version);
407 device_remove_file(&dev->dev, &dev_attr_remote_version);
408#endif
409
410#ifndef USE_SGL
411 free_kiovec(1, &sc->iobuf);
412 /*mem_map_unreserve(virt_to_page(sc->descbuf.cpu_addr));*/
413#endif
414 pci_free_consistent(sc->pcidev, sc->descbuf.size,
415 sc->descbuf.cpu_addr, sc->descbuf.dma_handle);
416
417 sis1100_done(sc);
418 free_irq(dev->irq, sc);
419 del_timer_sync(&sc->link_up_timer);
420 if (sc->handler_pid>=0) {
421 unsigned long flags;
422 spin_lock_irqsave(&sc->handlercommand.lock, flags);
423 sc->handlercommand.command=handlercomm_die;
424 spin_unlock_irqrestore(&sc->handlercommand.lock, flags);
425 wake_up(&sc->handler_wait);
426 wait_for_completion (&sc->handler_completion);
427 }
428 iounmap((void *)sc->plxmembase);
429 iounmap((void *)sc->reg_base);
430 iounmap((void *)sc->rem_base);
431 sis1100_devdata[sc->unit] = 0;
432
433 kfree(sc);
434 pci_release_regions(dev);
435 pci_set_drvdata(dev, NULL);
436}
437
438int __init
439sis1100_linux_drvinit(void)
440{
441 sis1100_major=register_chrdev(0, "sis1100", &sis1100_fops);
442 if (sis1100_major<0) {
443 printk(KERN_WARNING "sis1100: unable to register device\n");
444 return -EBUSY;
445 }
446 return 0;
447}
448
449void __exit
450sis1100_linux_drvdone(void)
451{
452 unregister_chrdev(sis1100_major, "sis1100");
453}
Note: See TracBrowser for help on using the repository browser.