* better
[mascara-docs.git] / i386 / linux-2.3.21 / drivers / net / irda / airport.c
blobedfc2e6e60a1e413d23974a66e2488d68a2b7109
1 /*********************************************************************
2 *
3 * Filename: airport.c
4 * Version: 0.2
5 * Description: Implementation for the Adaptec Airport 1000 and 2000
6 * dongles
7 * Status: Experimental.
8 * Author: Fons Botman <budely@tref.nl>
9 * Created at: Wed May 19 23:14:34 CEST 1999
10 * Based on: actisys.c
11 * By: Dag Brattli <dagb@cs.uit.no>
13 * Copyright (c) 1998-1999 Fons Botman, All Rights Reserved.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * Neither Fons Botman nor anyone else admit liability nor
21 * provide warranty for any of this software. This material is
22 * provided "AS-IS" and at no charge.
24 ********************************************************************/
26 #include <linux/module.h>
27 #include <linux/delay.h>
28 #include <linux/tty.h>
29 #include <linux/sched.h>
30 #include <linux/init.h>
32 #include <net/irda/irda.h>
33 #include <net/irda/irmod.h>
34 #include <net/irda/irda_device.h>
35 #include <net/irda/dongle.h>
38 static void airport_reset(struct irda_device *dev);
39 static void airport_open(struct irda_device *idev, int type);
40 static void airport_close(struct irda_device *dev);
41 static void airport_change_speed( struct irda_device *dev, __u32 speed);
42 static void airport_init_qos(struct irda_device *idev, struct qos_info *qos);
45 static struct dongle dongle = {
46 AIRPORT_DONGLE,
47 airport_open,
48 airport_close,
49 airport_reset,
50 airport_change_speed,
51 airport_init_qos,
55 int __init airport_init(void)
57 int ret;
59 DEBUG(2, __FUNCTION__ "()\n");
60 ret = irda_device_register_dongle(&dongle);
61 if (ret < 0)
62 return ret;
63 return 0;
66 void airport_cleanup(void)
68 DEBUG(2, __FUNCTION__ "()\n");
69 irda_device_unregister_dongle(&dongle);
72 static void airport_open(struct irda_device *idev, int type)
74 DEBUG(2, __FUNCTION__ "(,%d)\n", type);
75 if (strlen(idev->description) < sizeof(idev->description) - 13)
76 strcat(idev->description, " <-> airport");
77 else
78 DEBUG(0, __FUNCTION__ " description too long: %s\n",
79 idev->description);
81 idev->io.dongle_id = type;
82 idev->flags |= IFF_DONGLE;
84 MOD_INC_USE_COUNT;
87 static void airport_close(struct irda_device *idev)
89 DEBUG(2, __FUNCTION__ "()\n");
90 /* Power off dongle */
91 irda_device_set_dtr_rts(idev, FALSE, FALSE);
93 MOD_DEC_USE_COUNT;
96 static void airport_set_command_mode(struct irda_device *idev)
98 DEBUG(2, __FUNCTION__ "()\n");
99 irda_device_set_dtr_rts(idev, FALSE, TRUE);
102 static void airport_set_normal_mode(struct irda_device *idev)
104 DEBUG(2, __FUNCTION__ "()\n");
105 irda_device_set_dtr_rts(idev, TRUE, TRUE);
109 void airport_write_char(struct irda_device *idev, unsigned char c)
111 int actual;
112 DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff);
113 actual = idev->raw_write(idev, &c, 1);
114 ASSERT(actual == 1, return;);
117 #define JIFFIES_TO_MSECS(j) ((j)*1000/HZ)
119 static int airport_waitfor_char(struct irda_device *idev, unsigned char c)
121 int i, found = FALSE;
122 int before;
123 DEBUG(2, __FUNCTION__ "(,0x%x)\n", c);
125 /* Sleep approx. 10 ms */
126 before = jiffies;
127 current->state = TASK_INTERRUPTIBLE;
128 schedule_timeout(MSECS_TO_JIFFIES(20));
129 DEBUG(4, __FUNCTION__ " waited %ldms\n",
130 JIFFIES_TO_MSECS(jiffies - before));
132 for ( i = 0 ; !found && i < idev->rx_buff.len ; i++ ) {
133 /* DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */
134 found = c == idev->rx_buff.data[i];
136 idev->rx_buff.len = 0;
138 DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false"));
139 return found;
142 static int airport_check_command_mode(struct irda_device *idev)
144 int i;
145 int found = FALSE;
147 DEBUG(2, __FUNCTION__ "()\n");
148 current->state = TASK_INTERRUPTIBLE;
149 schedule_timeout(MSECS_TO_JIFFIES(20));
150 airport_set_command_mode(idev);
152 /* Loop until the time expires (200ms) or we get the magic char. */
154 for ( i = 0 ; i < 25 ; i++ ) {
155 airport_write_char(idev, 0xff);
156 if (airport_waitfor_char(idev, 0xc3)) {
157 found = TRUE;
158 break;
162 if (found) {
163 DEBUG(2, __FUNCTION__ " OK. (%d)\n", i);
164 } else {
165 DEBUG(0, __FUNCTION__ " FAILED!\n");
167 return found;
171 static int airport_write_register(struct irda_device *idev, unsigned char reg)
173 int ok = FALSE;
174 int i;
176 DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg);
177 airport_check_command_mode(idev);
179 for ( i = 0 ; i < 6 ; i++ ) {
180 airport_write_char(idev, reg);
181 if (!airport_waitfor_char(idev, reg))
182 continue;
184 /* Now read it back */
185 airport_write_char(idev, (reg << 4) | 0x0f);
186 if (airport_waitfor_char(idev, reg)) {
187 ok = TRUE;
188 break;
192 airport_set_normal_mode(idev);
193 if (ok) {
194 DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg);
195 } else {
196 DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg);
198 return ok;
203 * Function airport_change_speed (tty, baud)
205 * Change speed of the Airport type IrDA dongles.
207 static void airport_change_speed(struct irda_device *idev, __u32 speed)
209 __u32 current_baudrate;
210 int baudcode;
212 DEBUG(4, __FUNCTION__ "(,%d)\n", speed);
214 ASSERT(idev != NULL, return;);
215 ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
217 /* Find the correct baudrate code for the required baudrate */
218 switch (speed) {
219 case 2400: baudcode = 0x10; break;
220 case 4800: baudcode = 0x20; break;
221 case 9600: baudcode = 0x30; break;
222 case 19200: baudcode = 0x40; break;
223 case 38400: baudcode = 0x50; break;
224 case 57600: baudcode = 0x60; break;
225 case 115200: baudcode = 0x70; break;
226 default:
227 DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed);
228 return;
231 current_baudrate = idev->qos.baud_rate.value;
232 DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate);
234 /* The dongle falls back to 9600 baud */
235 if (current_baudrate != 9600) {
236 DEBUG(4, __FUNCTION__ " resetting speed to 9600 baud\n");
237 ASSERT(idev->change_speed , return;);
238 idev->change_speed(idev, 9600);
239 idev->qos.baud_rate.value = 9600;
242 if (idev->set_raw_mode)
243 idev->set_raw_mode(idev, TRUE);
245 /* Set the new speed in both registers */
246 if (airport_write_register(idev, baudcode)) {
247 if (airport_write_register(idev, baudcode|0x01)) {
248 /* ok */
249 } else {
250 DEBUG(0, __FUNCTION__
251 " Cannot set new speed in second register\n");
253 } else {
254 DEBUG(0, __FUNCTION__
255 " Cannot set new speed in first register\n");
258 if (idev->set_raw_mode)
259 idev->set_raw_mode(idev, FALSE);
261 /* How do I signal an error in these functions? */
263 DEBUG(4, __FUNCTION__ " returning\n");
268 * Function airport_reset (idev)
270 * Reset the Airport type dongle. Warning, this function must only be
271 * called with a process context!
274 static void airport_reset(struct irda_device *idev)
276 int ok;
278 DEBUG(2, __FUNCTION__ "()\n");
279 ASSERT(idev != NULL, return;);
280 ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
281 ASSERT(idev->set_raw_mode /* The airport needs this */, return;);
283 if (idev->set_raw_mode)
284 idev->set_raw_mode(idev, TRUE);
286 airport_set_normal_mode(idev);
288 /* Sleep 2000 ms */
289 DEBUG(2, __FUNCTION__ " waiting for powerup\n");
290 current->state = TASK_INTERRUPTIBLE;
291 schedule_timeout(MSECS_TO_JIFFIES(2000));
292 DEBUG(2, __FUNCTION__ " finished waiting for powerup\n");
294 /* set dongle speed to 9600 */
295 ok = TRUE;
297 if (ok)
298 ok = airport_write_register(idev, 0x30);
299 if (!ok)
300 MESSAGE(__FUNCTION__ "() dongle not connected?\n");
301 if (ok)
302 ok = airport_write_register(idev, 0x31);
304 if (ok)
305 ok = airport_write_register(idev, 0x02);
306 if (ok)
307 ok = airport_write_register(idev, 0x03);
309 if (ok) {
310 ok = airport_check_command_mode(idev);
312 if (ok) {
313 airport_write_char(idev, 0x04);
314 ok = airport_waitfor_char(idev, 0x04);
316 airport_set_normal_mode(idev);
319 if (idev->set_raw_mode)
320 idev->set_raw_mode(idev, FALSE);
323 current->state = TASK_INTERRUPTIBLE;
324 schedule_timeout(MSECS_TO_JIFFIES(20));
325 DEBUG(4, __FUNCTION__ " waited 20ms\n");
327 idev->qos.baud_rate.value = 9600;
328 if (!ok)
329 MESSAGE(__FUNCTION__ "() failed.\n");
330 DEBUG(2, __FUNCTION__ " returning.\n");
334 * Function airport_init_qos (qos)
336 * Initialize QoS capabilities
339 static void airport_init_qos(struct irda_device *idev, struct qos_info *qos)
341 qos->baud_rate.bits &=
342 IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
343 /* May need 1ms */
344 qos->min_turn_time.bits &= 0x07;
347 #ifdef MODULE
349 MODULE_AUTHOR("Fons Botman <budely@tref.nl>");
350 MODULE_DESCRIPTION("Adaptec Airport 1000 and 2000 dongle driver");
353 * Function init_module (void)
355 * Initialize Airport module
358 int init_module(void)
360 return airport_init();
364 * Function cleanup_module (void)
366 * Cleanup Airport module
369 void cleanup_module(void)
371 airport_cleanup();
374 #endif