File: /usr/src/linux/drivers/net/irda/girbil.c

1     /*********************************************************************
2      *                
3      * Filename:      girbil.c
4      * Version:       1.2
5      * Description:   Implementation for the Greenwich GIrBIL dongle
6      * Status:        Experimental.
7      * Author:        Dag Brattli <dagb@cs.uit.no>
8      * Created at:    Sat Feb  6 21:02:33 1999
9      * Modified at:   Fri Dec 17 09:13:20 1999
10      * Modified by:   Dag Brattli <dagb@cs.uit.no>
11      * 
12      *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
13      *      
14      *     This program is free software; you can redistribute it and/or 
15      *     modify it under the terms of the GNU General Public License as 
16      *     published by the Free Software Foundation; either version 2 of 
17      *     the License, or (at your option) any later version.
18      *  
19      *     Neither Dag Brattli nor University of Tromsų admit liability nor
20      *     provide warranty for any of this software. This material is 
21      *     provided "AS-IS" and at no charge.
22      *     
23      ********************************************************************/
24     
25     #include <linux/module.h>
26     #include <linux/delay.h>
27     #include <linux/tty.h>
28     #include <linux/sched.h>
29     #include <linux/init.h>
30     
31     #include <net/irda/irda.h>
32     #include <net/irda/irmod.h>
33     #include <net/irda/irda_device.h>
34     #include <net/irda/irtty.h>
35     
36     static int  girbil_reset(struct irda_task *task);
37     static void girbil_open(dongle_t *self, struct qos_info *qos);
38     static void girbil_close(dongle_t *self);
39     static int  girbil_change_speed(struct irda_task *task);
40     
41     /* Control register 1 */
42     #define GIRBIL_TXEN    0x01 /* Enable transmitter */
43     #define GIRBIL_RXEN    0x02 /* Enable receiver */
44     #define GIRBIL_ECAN    0x04 /* Cancel self emmited data */
45     #define GIRBIL_ECHO    0x08 /* Echo control characters */
46     
47     /* LED Current Register (0x2) */
48     #define GIRBIL_HIGH    0x20
49     #define GIRBIL_MEDIUM  0x21
50     #define GIRBIL_LOW     0x22
51     
52     /* Baud register (0x3) */
53     #define GIRBIL_2400    0x30
54     #define GIRBIL_4800    0x31	
55     #define GIRBIL_9600    0x32
56     #define GIRBIL_19200   0x33
57     #define GIRBIL_38400   0x34	
58     #define GIRBIL_57600   0x35	
59     #define GIRBIL_115200  0x36
60     
61     /* Mode register (0x4) */
62     #define GIRBIL_IRDA    0x40
63     #define GIRBIL_ASK     0x41
64     
65     /* Control register 2 (0x5) */
66     #define GIRBIL_LOAD    0x51 /* Load the new baud rate value */
67     
68     static struct dongle_reg dongle = {
69     	Q_NULL,
70     	IRDA_GIRBIL_DONGLE,
71     	girbil_open,
72     	girbil_close,
73     	girbil_reset,
74     	girbil_change_speed,
75     };
76     
77     int __init girbil_init(void)
78     {
79     	return irda_device_register_dongle(&dongle);
80     }
81     
82     void girbil_cleanup(void)
83     {
84     	irda_device_unregister_dongle(&dongle);
85     }
86     
87     static void girbil_open(dongle_t *self, struct qos_info *qos)
88     {
89     	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
90     	qos->min_turn_time.bits = 0x03;
91     
92     	MOD_INC_USE_COUNT;
93     }
94     
95     static void girbil_close(dongle_t *self)
96     {
97     	/* Power off dongle */
98     	self->set_dtr_rts(self->dev, FALSE, FALSE);
99     
100     	MOD_DEC_USE_COUNT;
101     }
102     
103     /*
104      * Function girbil_change_speed (dev, speed)
105      *
106      *    Set the speed for the Girbil type dongle.
107      *
108      */
109     static int girbil_change_speed(struct irda_task *task)
110     {
111     	dongle_t *self = (dongle_t *) task->instance;
112     	__u32 speed = (__u32) task->param;
113     	__u8 control[2];
114     	int ret = 0;
115     
116     	self->speed_task = task;
117     
118     	switch (task->state) {
119     	case IRDA_TASK_INIT:
120     		/* Need to reset the dongle and go to 9600 bps before
121                        programming */
122     		if (irda_task_execute(self, girbil_reset, NULL, task, 
123     				      (void *) speed))
124     		{
125     			/* Dongle need more time to reset */
126     			irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
127     
128     			/* Give reset 1 sec to finish */
129     			ret = MSECS_TO_JIFFIES(1000);
130     		}
131     		break;
132     	case IRDA_TASK_CHILD_WAIT:
133     		WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
134     		ret = -1;
135     		break;
136     	case IRDA_TASK_CHILD_DONE:
137     		/* Set DTR and Clear RTS to enter command mode */
138     		self->set_dtr_rts(self->dev, FALSE, TRUE);
139     
140     		switch (speed) {
141     		case 9600:
142     		default:
143     			control[0] = GIRBIL_9600;
144     			break;
145     		case 19200:
146     			control[0] = GIRBIL_19200;
147     			break;
148     		case 34800:
149     			control[0] = GIRBIL_38400;
150     			break;
151     		case 57600:
152     			control[0] = GIRBIL_57600;
153     			break;
154     		case 115200:
155     			control[0] = GIRBIL_115200;
156     			break;
157     		}
158     		control[1] = GIRBIL_LOAD;
159     		
160     		/* Write control bytes */
161     		self->write(self->dev, control, 2);
162     		irda_task_next_state(task, IRDA_TASK_WAIT);
163     		ret = MSECS_TO_JIFFIES(100);
164     		break;
165     	case IRDA_TASK_WAIT:
166     		/* Go back to normal mode */
167     		self->set_dtr_rts(self->dev, TRUE, TRUE);
168     		irda_task_next_state(task, IRDA_TASK_DONE);
169     		self->speed_task = NULL;
170     		break;
171     	default:
172     		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
173     		irda_task_next_state(task, IRDA_TASK_DONE);
174     		self->speed_task = NULL;
175     		ret = -1;
176     		break;
177     	}
178     	return ret;
179     }
180     
181     /*
182      * Function girbil_reset (driver)
183      *
184      *      This function resets the girbil dongle.
185      *
186      *      Algorithm:
187      *    	  0. set RTS, and wait at least 5 ms 
188      *        1. clear RTS 
189      */
190     static int girbil_reset(struct irda_task *task)
191     {
192     	dongle_t *self = (dongle_t *) task->instance;
193     	__u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
194     	int ret = 0;
195     
196     	self->reset_task = task;
197     
198     	switch (task->state) {
199     	case IRDA_TASK_INIT:
200     		/* Reset dongle */
201     		self->set_dtr_rts(self->dev, TRUE, FALSE);
202     		irda_task_next_state(task, IRDA_TASK_WAIT1);
203     		/* Sleep at least 5 ms */
204     		ret = MSECS_TO_JIFFIES(20);
205     		break;
206     	case IRDA_TASK_WAIT1:
207     		/* Set DTR and clear RTS to enter command mode */
208     		self->set_dtr_rts(self->dev, FALSE, TRUE);
209     		irda_task_next_state(task, IRDA_TASK_WAIT2);
210     		ret = MSECS_TO_JIFFIES(20);
211     		break;
212     	case IRDA_TASK_WAIT2:
213     		/* Write control byte */
214     		self->write(self->dev, &control, 1);
215     		irda_task_next_state(task, IRDA_TASK_WAIT3);
216     		ret = MSECS_TO_JIFFIES(20);
217     		break;
218     	case IRDA_TASK_WAIT3:
219     		/* Go back to normal mode */
220     		self->set_dtr_rts(self->dev, TRUE, TRUE);
221     		irda_task_next_state(task, IRDA_TASK_DONE);
222     		self->reset_task = NULL;
223     		break;
224     	default:
225     		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
226     		irda_task_next_state(task, IRDA_TASK_DONE);
227     		self->reset_task = NULL;
228     		ret = -1;
229     		break;
230     	}
231     	return ret;
232     }
233     
234     #ifdef MODULE
235     MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
236     MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
237     	
238     /*
239      * Function init_module (void)
240      *
241      *    Initialize Girbil module
242      *
243      */
244     int init_module(void)
245     {
246     	return girbil_init();
247     }
248     
249     /*
250      * Function cleanup_module (void)
251      *
252      *    Cleanup Girbil module
253      *
254      */
255     void cleanup_module(void)
256     {
257             girbil_cleanup();
258     }
259     #endif /* MODULE */
260