diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hisax/st5481_init.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/hisax/st5481_init.c')
-rw-r--r-- | drivers/isdn/hisax/st5481_init.c | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c new file mode 100644 index 000000000000..7aa810d5d333 --- /dev/null +++ b/drivers/isdn/hisax/st5481_init.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Driver for ST5481 USB ISDN modem | ||
3 | * | ||
4 | * Author Frode Isaksen | ||
5 | * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com> | ||
6 | * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de> | ||
7 | * | ||
8 | * This software may be used and distributed according to the terms | ||
9 | * of the GNU General Public License, incorporated herein by reference. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * TODO: | ||
15 | * | ||
16 | * b layer1 delay? | ||
17 | * hotplug / unregister issues | ||
18 | * mod_inc/dec_use_count | ||
19 | * unify parts of d/b channel usb handling | ||
20 | * file header | ||
21 | * avoid copy to isoc buffer? | ||
22 | * improve usb delay? | ||
23 | * merge l1 state machines? | ||
24 | * clean up debug | ||
25 | */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/version.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/usb.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include "st5481.h" | ||
34 | |||
35 | MODULE_DESCRIPTION("ISDN4Linux: driver for ST5481 USB ISDN adapter"); | ||
36 | MODULE_AUTHOR("Frode Isaksen"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | static int protocol = 2; /* EURO-ISDN Default */ | ||
40 | module_param(protocol, int, 0); | ||
41 | |||
42 | static int number_of_leds = 2; /* 2 LEDs on the adpater default */ | ||
43 | module_param(number_of_leds, int, 0); | ||
44 | |||
45 | #ifdef CONFIG_HISAX_DEBUG | ||
46 | static int debug = 0x1; | ||
47 | module_param(debug, int, 0); | ||
48 | int st5481_debug; | ||
49 | #endif | ||
50 | |||
51 | static LIST_HEAD(adapter_list); | ||
52 | |||
53 | /* ====================================================================== | ||
54 | * registration/deregistration with the USB layer | ||
55 | */ | ||
56 | |||
57 | /* | ||
58 | * This function will be called when the adapter is plugged | ||
59 | * into the USB bus. | ||
60 | */ | ||
61 | static int probe_st5481(struct usb_interface *intf, | ||
62 | const struct usb_device_id *id) | ||
63 | { | ||
64 | struct usb_device *dev = interface_to_usbdev(intf); | ||
65 | struct st5481_adapter *adapter; | ||
66 | struct hisax_b_if *b_if[2]; | ||
67 | int retval, i; | ||
68 | |||
69 | printk(KERN_INFO "st541: found adapter VendorId %04x, ProductId %04x, LEDs %d\n", | ||
70 | le16_to_cpu(dev->descriptor.idVendor), | ||
71 | le16_to_cpu(dev->descriptor.idProduct), | ||
72 | number_of_leds); | ||
73 | |||
74 | adapter = kmalloc(sizeof(struct st5481_adapter), GFP_KERNEL); | ||
75 | if (!adapter) | ||
76 | return -ENOMEM; | ||
77 | |||
78 | memset(adapter, 0, sizeof(struct st5481_adapter)); | ||
79 | |||
80 | adapter->number_of_leds = number_of_leds; | ||
81 | adapter->usb_dev = dev; | ||
82 | |||
83 | adapter->hisax_d_if.owner = THIS_MODULE; | ||
84 | adapter->hisax_d_if.ifc.priv = adapter; | ||
85 | adapter->hisax_d_if.ifc.l2l1 = st5481_d_l2l1; | ||
86 | |||
87 | for (i = 0; i < 2; i++) { | ||
88 | adapter->bcs[i].adapter = adapter; | ||
89 | adapter->bcs[i].channel = i; | ||
90 | adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i]; | ||
91 | adapter->bcs[i].b_if.ifc.l2l1 = st5481_b_l2l1; | ||
92 | } | ||
93 | list_add(&adapter->list, &adapter_list); | ||
94 | |||
95 | retval = st5481_setup_usb(adapter); | ||
96 | if (retval < 0) | ||
97 | goto err; | ||
98 | |||
99 | retval = st5481_setup_d(adapter); | ||
100 | if (retval < 0) | ||
101 | goto err_usb; | ||
102 | |||
103 | retval = st5481_setup_b(&adapter->bcs[0]); | ||
104 | if (retval < 0) | ||
105 | goto err_d; | ||
106 | |||
107 | retval = st5481_setup_b(&adapter->bcs[1]); | ||
108 | if (retval < 0) | ||
109 | goto err_b; | ||
110 | |||
111 | for (i = 0; i < 2; i++) | ||
112 | b_if[i] = &adapter->bcs[i].b_if; | ||
113 | |||
114 | hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb", protocol); | ||
115 | st5481_start(adapter); | ||
116 | |||
117 | usb_set_intfdata(intf, adapter); | ||
118 | return 0; | ||
119 | |||
120 | err_b: | ||
121 | st5481_release_b(&adapter->bcs[0]); | ||
122 | err_d: | ||
123 | st5481_release_d(adapter); | ||
124 | err_usb: | ||
125 | st5481_release_usb(adapter); | ||
126 | err: | ||
127 | return -EIO; | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * This function will be called when the adapter is removed | ||
132 | * from the USB bus. | ||
133 | */ | ||
134 | static void disconnect_st5481(struct usb_interface *intf) | ||
135 | { | ||
136 | struct st5481_adapter *adapter = usb_get_intfdata(intf); | ||
137 | |||
138 | DBG(1,""); | ||
139 | |||
140 | usb_set_intfdata(intf, NULL); | ||
141 | if (!adapter) | ||
142 | return; | ||
143 | |||
144 | list_del(&adapter->list); | ||
145 | |||
146 | st5481_stop(adapter); | ||
147 | st5481_release_b(&adapter->bcs[1]); | ||
148 | st5481_release_b(&adapter->bcs[0]); | ||
149 | st5481_release_d(adapter); | ||
150 | // we would actually better wait for completion of outstanding urbs | ||
151 | mdelay(2); | ||
152 | st5481_release_usb(adapter); | ||
153 | |||
154 | hisax_unregister(&adapter->hisax_d_if); | ||
155 | |||
156 | kfree(adapter); | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * The last 4 bits in the Product Id is set with 4 pins on the chip. | ||
161 | */ | ||
162 | static struct usb_device_id st5481_ids[] = { | ||
163 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x0) }, | ||
164 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x1) }, | ||
165 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x2) }, | ||
166 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x3) }, | ||
167 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x4) }, | ||
168 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x5) }, | ||
169 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x6) }, | ||
170 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x7) }, | ||
171 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x8) }, | ||
172 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x9) }, | ||
173 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xA) }, | ||
174 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xB) }, | ||
175 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xC) }, | ||
176 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xD) }, | ||
177 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xE) }, | ||
178 | { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xF) }, | ||
179 | { } | ||
180 | }; | ||
181 | MODULE_DEVICE_TABLE (usb, st5481_ids); | ||
182 | |||
183 | static struct usb_driver st5481_usb_driver = { | ||
184 | .owner = THIS_MODULE, | ||
185 | .name = "st5481_usb", | ||
186 | .probe = probe_st5481, | ||
187 | .disconnect = disconnect_st5481, | ||
188 | .id_table = st5481_ids, | ||
189 | }; | ||
190 | |||
191 | static int __init st5481_usb_init(void) | ||
192 | { | ||
193 | int retval; | ||
194 | |||
195 | #ifdef CONFIG_HISAX_DEBUG | ||
196 | st5481_debug = debug; | ||
197 | #endif | ||
198 | |||
199 | printk(KERN_INFO "hisax_st5481: ST5481 USB ISDN driver $Revision: 2.4.2.3 $\n"); | ||
200 | |||
201 | retval = st5481_d_init(); | ||
202 | if (retval < 0) | ||
203 | goto out; | ||
204 | |||
205 | retval = usb_register(&st5481_usb_driver); | ||
206 | if (retval < 0) | ||
207 | goto out_d_exit; | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | out_d_exit: | ||
212 | st5481_d_exit(); | ||
213 | out: | ||
214 | return retval; | ||
215 | } | ||
216 | |||
217 | static void __exit st5481_usb_exit(void) | ||
218 | { | ||
219 | usb_deregister(&st5481_usb_driver); | ||
220 | st5481_d_exit(); | ||
221 | } | ||
222 | |||
223 | module_init(st5481_usb_init); | ||
224 | module_exit(st5481_usb_exit); | ||