]>
Commit | Line | Data |
---|---|---|
e184e2be | 1 | // SPDX-License-Identifier: GPL-2.0+ |
6ca27334 | 2 | /* |
b40369d6 IA |
3 | * comedi/drivers/8255.c |
4 | * Driver for 8255 | |
5 | * | |
6 | * COMEDI - Linux Control and Measurement Device Interface | |
7 | * Copyright (C) 1998 David A. Schleef <ds@schleef.org> | |
b40369d6 | 8 | */ |
6ca27334 | 9 | |
6ca27334 | 10 | /* |
20f2ff88 IA |
11 | * Driver: 8255 |
12 | * Description: generic 8255 support | |
13 | * Devices: [standard] 8255 (8255) | |
14 | * Author: ds | |
15 | * Status: works | |
16 | * Updated: Fri, 7 Jun 2002 12:56:45 -0700 | |
17 | * | |
18 | * The classic in digital I/O. The 8255 appears in Comedi as a single | |
19 | * digital I/O subdevice with 24 channels. The channel 0 corresponds | |
20 | * to the 8255's port A, bit 0; channel 23 corresponds to port C, bit | |
21 | * 7. Direction configuration is done in blocks, with channels 0-7, | |
22 | * 8-15, 16-19, and 20-23 making up the 4 blocks. The only 8255 mode | |
23 | * supported is mode 0. | |
24 | * | |
25 | * You should enable compilation this driver if you plan to use a board | |
26 | * that has an 8255 chip. For multifunction boards, the main driver will | |
27 | * configure the 8255 subdevice automatically. | |
28 | * | |
29 | * This driver also works independently with ISA and PCI cards that | |
30 | * directly map the 8255 registers to I/O ports, including cards with | |
31 | * multiple 8255 chips. To configure the driver for such a card, the | |
32 | * option list should be a list of the I/O port bases for each of the | |
33 | * 8255 chips. For example, | |
34 | * | |
35 | * comedi_config /dev/comedi0 8255 0x200,0x204,0x208,0x20c | |
36 | * | |
37 | * Note that most PCI 8255 boards do NOT work with this driver, and | |
38 | * need a separate driver as a wrapper. For those that do work, the | |
39 | * I/O port base address can be found in the output of 'lspci -v'. | |
40 | */ | |
6ca27334 | 41 | |
ce157f80 | 42 | #include <linux/module.h> |
6ca27334 DS |
43 | #include "../comedidev.h" |
44 | ||
c5efe58b | 45 | #include "8255.h" |
6ca27334 | 46 | |
0a85b6f0 MT |
47 | static int dev_8255_attach(struct comedi_device *dev, |
48 | struct comedi_devconfig *it) | |
6ca27334 | 49 | { |
e40e8375 | 50 | struct comedi_subdevice *s; |
6ca27334 | 51 | unsigned long iobase; |
4085e93b | 52 | int ret; |
6ca27334 DS |
53 | int i; |
54 | ||
6ca27334 DS |
55 | for (i = 0; i < COMEDI_NDEVCONFOPTS; i++) { |
56 | iobase = it->options[i]; | |
57 | if (!iobase) | |
58 | break; | |
59 | } | |
60 | if (i == 0) { | |
01bd3e3f | 61 | dev_warn(dev->class_dev, "no devices specified\n"); |
6ca27334 DS |
62 | return -EINVAL; |
63 | } | |
64 | ||
2f0b9d08 | 65 | ret = comedi_alloc_subdevices(dev, i); |
8b6c5694 | 66 | if (ret) |
6ca27334 | 67 | return ret; |
02638697 | 68 | |
6ca27334 | 69 | for (i = 0; i < dev->n_subdevices; i++) { |
5101b4d1 | 70 | s = &dev->subdevices[i]; |
6ca27334 DS |
71 | iobase = it->options[i]; |
72 | ||
4085e93b HS |
73 | /* |
74 | * __comedi_request_region() does not set dev->iobase. | |
75 | * | |
76 | * For 8255 devices that are manually attached using | |
77 | * comedi_config, the 'iobase' is the actual I/O port | |
78 | * base address of the chip. | |
79 | */ | |
f0162091 | 80 | ret = __comedi_request_region(dev, iobase, I8255_SIZE); |
e9720fd2 | 81 | if (ret) { |
e40e8375 | 82 | s->type = COMEDI_SUBD_UNUSED; |
6ca27334 | 83 | } else { |
3e189f08 | 84 | ret = subdev_8255_init(dev, s, NULL, iobase); |
7e0b1b60 IA |
85 | if (ret) { |
86 | /* | |
87 | * Release the I/O port region here, as the | |
88 | * "detach" handler cannot find it. | |
89 | */ | |
90 | release_region(iobase, I8255_SIZE); | |
91 | s->type = COMEDI_SUBD_UNUSED; | |
3e189f08 | 92 | return ret; |
7e0b1b60 | 93 | } |
6ca27334 DS |
94 | } |
95 | } | |
96 | ||
6ca27334 DS |
97 | return 0; |
98 | } | |
99 | ||
484ecc95 | 100 | static void dev_8255_detach(struct comedi_device *dev) |
6ca27334 | 101 | { |
34c43922 | 102 | struct comedi_subdevice *s; |
7c61452a | 103 | int i; |
6ca27334 | 104 | |
6ca27334 | 105 | for (i = 0; i < dev->n_subdevices; i++) { |
5101b4d1 | 106 | s = &dev->subdevices[i]; |
6ca27334 | 107 | if (s->type != COMEDI_SUBD_UNUSED) { |
968d1778 IA |
108 | unsigned long regbase = subdev_8255_regbase(s); |
109 | ||
110 | release_region(regbase, I8255_SIZE); | |
6ca27334 | 111 | } |
6ca27334 | 112 | } |
6ca27334 | 113 | } |
90f703d3 | 114 | |
294f930d | 115 | static struct comedi_driver dev_8255_driver = { |
3e699ed1 HS |
116 | .driver_name = "8255", |
117 | .module = THIS_MODULE, | |
118 | .attach = dev_8255_attach, | |
119 | .detach = dev_8255_detach, | |
120 | }; | |
294f930d | 121 | module_comedi_driver(dev_8255_driver); |
3e699ed1 | 122 | |
90f703d3 | 123 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
968d1778 | 124 | MODULE_DESCRIPTION("Comedi driver for standalone 8255 devices"); |
90f703d3 | 125 | MODULE_LICENSE("GPL"); |