diff options
Diffstat (limited to 'drivers/char/ip2')
-rw-r--r-- | drivers/char/ip2/Makefile | 8 | ||||
-rw-r--r-- | drivers/char/ip2/i2cmd.c | 210 | ||||
-rw-r--r-- | drivers/char/ip2/i2cmd.h | 630 | ||||
-rw-r--r-- | drivers/char/ip2/i2ellis.c | 1403 | ||||
-rw-r--r-- | drivers/char/ip2/i2ellis.h | 566 | ||||
-rw-r--r-- | drivers/char/ip2/i2hw.h | 652 | ||||
-rw-r--r-- | drivers/char/ip2/i2lib.c | 2214 | ||||
-rw-r--r-- | drivers/char/ip2/i2lib.h | 351 | ||||
-rw-r--r-- | drivers/char/ip2/i2pack.h | 364 | ||||
-rw-r--r-- | drivers/char/ip2/ip2.h | 107 | ||||
-rw-r--r-- | drivers/char/ip2/ip2ioctl.h | 35 | ||||
-rw-r--r-- | drivers/char/ip2/ip2main.c | 3234 | ||||
-rw-r--r-- | drivers/char/ip2/ip2trace.h | 42 | ||||
-rw-r--r-- | drivers/char/ip2/ip2types.h | 57 |
14 files changed, 0 insertions, 9873 deletions
diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile deleted file mode 100644 index 7b78e0dfc5b0..000000000000 --- a/drivers/char/ip2/Makefile +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for the Computone IntelliPort Plus Driver | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_COMPUTONE) += ip2.o | ||
6 | |||
7 | ip2-y := ip2main.o | ||
8 | |||
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c deleted file mode 100644 index e7af647800b6..000000000000 --- a/drivers/char/ip2/i2cmd.c +++ /dev/null | |||
@@ -1,210 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Definition table for In-line and Bypass commands. Applicable | ||
12 | * only when the standard loadware is active. (This is included | ||
13 | * source code, not a separate compilation module.) | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | |||
17 | //------------------------------------------------------------------------------ | ||
18 | // | ||
19 | // Revision History: | ||
20 | // | ||
21 | // 10 October 1991 MAG First Draft | ||
22 | // 7 November 1991 MAG Reflects additional commands. | ||
23 | // 24 February 1992 MAG Additional commands for 1.4.x loadware | ||
24 | // 11 March 1992 MAG Additional commands | ||
25 | // 30 March 1992 MAG Additional command: CMD_DSS_NOW | ||
26 | // 18 May 1992 MAG Discovered commands 39 & 40 must be at the end of a | ||
27 | // packet: affects implementation. | ||
28 | //------------------------------------------------------------------------------ | ||
29 | |||
30 | //************ | ||
31 | //* Includes * | ||
32 | //************ | ||
33 | |||
34 | #include "i2cmd.h" /* To get some bit-defines */ | ||
35 | |||
36 | //------------------------------------------------------------------------------ | ||
37 | // Here is the table of global arrays which represent each type of command | ||
38 | // supported in the IntelliPort standard loadware. See also i2cmd.h | ||
39 | // for a more complete explanation of what is going on. | ||
40 | //------------------------------------------------------------------------------ | ||
41 | |||
42 | // Here are the various globals: note that the names are not used except through | ||
43 | // the macros defined in i2cmd.h. Also note that although they are character | ||
44 | // arrays here (for extendability) they are cast to structure pointers in the | ||
45 | // i2cmd.h macros. See i2cmd.h for flags definitions. | ||
46 | |||
47 | // Length Flags Command | ||
48 | static UCHAR ct02[] = { 1, BTH, 0x02 }; // DTR UP | ||
49 | static UCHAR ct03[] = { 1, BTH, 0x03 }; // DTR DN | ||
50 | static UCHAR ct04[] = { 1, BTH, 0x04 }; // RTS UP | ||
51 | static UCHAR ct05[] = { 1, BTH, 0x05 }; // RTS DN | ||
52 | static UCHAR ct06[] = { 1, BYP, 0x06 }; // START FL | ||
53 | static UCHAR ct07[] = { 2, BTH, 0x07,0 }; // BAUD | ||
54 | static UCHAR ct08[] = { 2, BTH, 0x08,0 }; // BITS | ||
55 | static UCHAR ct09[] = { 2, BTH, 0x09,0 }; // STOP | ||
56 | static UCHAR ct10[] = { 2, BTH, 0x0A,0 }; // PARITY | ||
57 | static UCHAR ct11[] = { 2, BTH, 0x0B,0 }; // XON | ||
58 | static UCHAR ct12[] = { 2, BTH, 0x0C,0 }; // XOFF | ||
59 | static UCHAR ct13[] = { 1, BTH, 0x0D }; // STOP FL | ||
60 | static UCHAR ct14[] = { 1, BYP|VIP, 0x0E }; // ACK HOTK | ||
61 | //static UCHAR ct15[]={ 2, BTH|VIP, 0x0F,0 }; // IRQ SET | ||
62 | static UCHAR ct16[] = { 2, INL, 0x10,0 }; // IXONOPTS | ||
63 | static UCHAR ct17[] = { 2, INL, 0x11,0 }; // OXONOPTS | ||
64 | static UCHAR ct18[] = { 1, INL, 0x12 }; // CTSENAB | ||
65 | static UCHAR ct19[] = { 1, BTH, 0x13 }; // CTSDSAB | ||
66 | static UCHAR ct20[] = { 1, INL, 0x14 }; // DCDENAB | ||
67 | static UCHAR ct21[] = { 1, BTH, 0x15 }; // DCDDSAB | ||
68 | static UCHAR ct22[] = { 1, BTH, 0x16 }; // DSRENAB | ||
69 | static UCHAR ct23[] = { 1, BTH, 0x17 }; // DSRDSAB | ||
70 | static UCHAR ct24[] = { 1, BTH, 0x18 }; // RIENAB | ||
71 | static UCHAR ct25[] = { 1, BTH, 0x19 }; // RIDSAB | ||
72 | static UCHAR ct26[] = { 2, BTH, 0x1A,0 }; // BRKENAB | ||
73 | static UCHAR ct27[] = { 1, BTH, 0x1B }; // BRKDSAB | ||
74 | //static UCHAR ct28[]={ 2, BTH, 0x1C,0 }; // MAXBLOKSIZE | ||
75 | //static UCHAR ct29[]={ 2, 0, 0x1D,0 }; // reserved | ||
76 | static UCHAR ct30[] = { 1, INL, 0x1E }; // CTSFLOWENAB | ||
77 | static UCHAR ct31[] = { 1, INL, 0x1F }; // CTSFLOWDSAB | ||
78 | static UCHAR ct32[] = { 1, INL, 0x20 }; // RTSFLOWENAB | ||
79 | static UCHAR ct33[] = { 1, INL, 0x21 }; // RTSFLOWDSAB | ||
80 | static UCHAR ct34[] = { 2, BTH, 0x22,0 }; // ISTRIPMODE | ||
81 | static UCHAR ct35[] = { 2, BTH|END, 0x23,0 }; // SENDBREAK | ||
82 | static UCHAR ct36[] = { 2, BTH, 0x24,0 }; // SETERRMODE | ||
83 | //static UCHAR ct36a[]={ 3, INL, 0x24,0,0 }; // SET_REPLACE | ||
84 | |||
85 | // The following is listed for completeness, but should never be sent directly | ||
86 | // by user-level code. It is sent only by library routines in response to data | ||
87 | // movement. | ||
88 | //static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0 }; // FLOW PACKET | ||
89 | |||
90 | // Back to normal | ||
91 | //static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ | ||
92 | //static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0 }; // OPOSTON | ||
93 | //static UCHAR ct40[]={ 1, BTH|END, 0x28 }; // OPOSTOFF | ||
94 | static UCHAR ct41[] = { 1, BYP, 0x29 }; // RESUME | ||
95 | //static UCHAR ct42[]={ 2, BTH, 0x2A,0 }; // TXBAUD | ||
96 | //static UCHAR ct43[]={ 2, BTH, 0x2B,0 }; // RXBAUD | ||
97 | //static UCHAR ct44[]={ 2, BTH, 0x2C,0 }; // MS PING | ||
98 | //static UCHAR ct45[]={ 1, BTH, 0x2D }; // HOTENAB | ||
99 | //static UCHAR ct46[]={ 1, BTH, 0x2E }; // HOTDSAB | ||
100 | //static UCHAR ct47[]={ 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS | ||
101 | //static UCHAR ct48[]={ 1, BTH, 0x30 }; // DSRFLOWENAB | ||
102 | //static UCHAR ct49[]={ 1, BTH, 0x31 }; // DSRFLOWDSAB | ||
103 | //static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB | ||
104 | //static UCHAR ct51[]={ 1, BTH, 0x33 }; // DTRFLOWDSAB | ||
105 | //static UCHAR ct52[]={ 1, BTH, 0x34 }; // BAUDTABRESET | ||
106 | //static UCHAR ct53[] = { 3, BTH, 0x35,0,0 }; // BAUDREMAP | ||
107 | static UCHAR ct54[] = { 3, BTH, 0x36,0,0 }; // CUSTOMBAUD1 | ||
108 | static UCHAR ct55[] = { 3, BTH, 0x37,0,0 }; // CUSTOMBAUD2 | ||
109 | static UCHAR ct56[] = { 2, BTH|END, 0x38,0 }; // PAUSE | ||
110 | static UCHAR ct57[] = { 1, BYP, 0x39 }; // SUSPEND | ||
111 | static UCHAR ct58[] = { 1, BYP, 0x3A }; // UNSUSPEND | ||
112 | static UCHAR ct59[] = { 2, BTH, 0x3B,0 }; // PARITYCHK | ||
113 | static UCHAR ct60[] = { 1, INL|VIP, 0x3C }; // BOOKMARKREQ | ||
114 | //static UCHAR ct61[]={ 2, BTH, 0x3D,0 }; // INTERNALLOOP | ||
115 | //static UCHAR ct62[]={ 2, BTH, 0x3E,0 }; // HOTKTIMEOUT | ||
116 | static UCHAR ct63[] = { 2, INL, 0x3F,0 }; // SETTXON | ||
117 | static UCHAR ct64[] = { 2, INL, 0x40,0 }; // SETTXOFF | ||
118 | //static UCHAR ct65[]={ 2, BTH, 0x41,0 }; // SETAUTORTS | ||
119 | //static UCHAR ct66[]={ 2, BTH, 0x42,0 }; // SETHIGHWAT | ||
120 | //static UCHAR ct67[]={ 2, BYP, 0x43,0 }; // STARTSELFL | ||
121 | //static UCHAR ct68[]={ 2, INL, 0x44,0 }; // ENDSELFL | ||
122 | //static UCHAR ct69[]={ 1, BYP, 0x45 }; // HWFLOW_OFF | ||
123 | //static UCHAR ct70[]={ 1, BTH, 0x46 }; // ODSRFL_ENAB | ||
124 | //static UCHAR ct71[]={ 1, BTH, 0x47 }; // ODSRFL_DSAB | ||
125 | //static UCHAR ct72[]={ 1, BTH, 0x48 }; // ODCDFL_ENAB | ||
126 | //static UCHAR ct73[]={ 1, BTH, 0x49 }; // ODCDFL_DSAB | ||
127 | //static UCHAR ct74[]={ 2, BTH, 0x4A,0 }; // LOADLEVEL | ||
128 | //static UCHAR ct75[]={ 2, BTH, 0x4B,0 }; // STATDATA | ||
129 | //static UCHAR ct76[]={ 1, BYP, 0x4C }; // BREAK_ON | ||
130 | //static UCHAR ct77[]={ 1, BYP, 0x4D }; // BREAK_OFF | ||
131 | //static UCHAR ct78[]={ 1, BYP, 0x4E }; // GETFC | ||
132 | static UCHAR ct79[] = { 2, BYP, 0x4F,0 }; // XMIT_NOW | ||
133 | //static UCHAR ct80[]={ 4, BTH, 0x50,0,0,0 }; // DIVISOR_LATCH | ||
134 | //static UCHAR ct81[]={ 1, BYP, 0x51 }; // GET_STATUS | ||
135 | //static UCHAR ct82[]={ 1, BYP, 0x52 }; // GET_TXCNT | ||
136 | //static UCHAR ct83[]={ 1, BYP, 0x53 }; // GET_RXCNT | ||
137 | //static UCHAR ct84[]={ 1, BYP, 0x54 }; // GET_BOXIDS | ||
138 | //static UCHAR ct85[]={10, BYP, 0x55,0,0,0,0,0,0,0,0,0 }; // ENAB_MULT | ||
139 | //static UCHAR ct86[]={ 2, BTH, 0x56,0 }; // RCV_ENABLE | ||
140 | static UCHAR ct87[] = { 1, BYP, 0x57 }; // HW_TEST | ||
141 | //static UCHAR ct88[]={ 3, BTH, 0x58,0,0 }; // RCV_THRESHOLD | ||
142 | //static UCHAR ct90[]={ 3, BYP, 0x5A,0,0 }; // Set SILO | ||
143 | //static UCHAR ct91[]={ 2, BYP, 0x5B,0 }; // timed break | ||
144 | |||
145 | // Some composite commands as well | ||
146 | //static UCHAR cc01[]={ 2, BTH, 0x02,0x04 }; // DTR & RTS UP | ||
147 | //static UCHAR cc02[]={ 2, BTH, 0x03,0x05 }; // DTR & RTS DN | ||
148 | |||
149 | //******** | ||
150 | //* Code * | ||
151 | //******** | ||
152 | |||
153 | //****************************************************************************** | ||
154 | // Function: i2cmdUnixFlags(iflag, cflag, lflag) | ||
155 | // Parameters: Unix tty flags | ||
156 | // | ||
157 | // Returns: Pointer to command structure | ||
158 | // | ||
159 | // Description: | ||
160 | // | ||
161 | // This routine sets the parameters of command 47 and returns a pointer to the | ||
162 | // appropriate structure. | ||
163 | //****************************************************************************** | ||
164 | #if 0 | ||
165 | cmdSyntaxPtr | ||
166 | i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag) | ||
167 | { | ||
168 | cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct47; | ||
169 | |||
170 | pCM->cmd[1] = (unsigned char) iflag; | ||
171 | pCM->cmd[2] = (unsigned char) (iflag >> 8); | ||
172 | pCM->cmd[3] = (unsigned char) cflag; | ||
173 | pCM->cmd[4] = (unsigned char) (cflag >> 8); | ||
174 | pCM->cmd[5] = (unsigned char) lflag; | ||
175 | pCM->cmd[6] = (unsigned char) (lflag >> 8); | ||
176 | return pCM; | ||
177 | } | ||
178 | #endif /* 0 */ | ||
179 | |||
180 | //****************************************************************************** | ||
181 | // Function: i2cmdBaudDef(which, rate) | ||
182 | // Parameters: ? | ||
183 | // | ||
184 | // Returns: Pointer to command structure | ||
185 | // | ||
186 | // Description: | ||
187 | // | ||
188 | // This routine sets the parameters of commands 54 or 55 (according to the | ||
189 | // argument which), and returns a pointer to the appropriate structure. | ||
190 | //****************************************************************************** | ||
191 | static cmdSyntaxPtr | ||
192 | i2cmdBaudDef(int which, unsigned short rate) | ||
193 | { | ||
194 | cmdSyntaxPtr pCM; | ||
195 | |||
196 | switch(which) | ||
197 | { | ||
198 | case 1: | ||
199 | pCM = (cmdSyntaxPtr) ct54; | ||
200 | break; | ||
201 | default: | ||
202 | case 2: | ||
203 | pCM = (cmdSyntaxPtr) ct55; | ||
204 | break; | ||
205 | } | ||
206 | pCM->cmd[1] = (unsigned char) rate; | ||
207 | pCM->cmd[2] = (unsigned char) (rate >> 8); | ||
208 | return pCM; | ||
209 | } | ||
210 | |||
diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h deleted file mode 100644 index 29277ec6b8ed..000000000000 --- a/drivers/char/ip2/i2cmd.h +++ /dev/null | |||
@@ -1,630 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Definitions and support for In-line and Bypass commands. | ||
12 | * Applicable only when the standard loadware is active. | ||
13 | * | ||
14 | *******************************************************************************/ | ||
15 | //------------------------------------------------------------------------------ | ||
16 | // Revision History: | ||
17 | // | ||
18 | // 10 October 1991 MAG First Draft | ||
19 | // 7 November 1991 MAG Reflects some new commands | ||
20 | // 20 February 1992 MAG CMD_HOTACK corrected: no argument. | ||
21 | // 24 February 1992 MAG Support added for new commands for 1.4.x loadware. | ||
22 | // 11 March 1992 MAG Additional commands. | ||
23 | // 16 March 1992 MAG Additional commands. | ||
24 | // 30 March 1992 MAG Additional command: CMD_DSS_NOW | ||
25 | // 18 May 1992 MAG Changed CMD_OPOST | ||
26 | // | ||
27 | //------------------------------------------------------------------------------ | ||
28 | #ifndef I2CMD_H // To prevent multiple includes | ||
29 | #define I2CMD_H 1 | ||
30 | |||
31 | #include "ip2types.h" | ||
32 | |||
33 | // This module is designed to provide a uniform method of sending commands to | ||
34 | // the board through command packets. The difficulty is, some commands take | ||
35 | // parameters, others do not. Furthermore, it is often useful to send several | ||
36 | // commands to the same channel as part of the same packet. (See also i2pack.h.) | ||
37 | // | ||
38 | // This module is designed so that the caller should not be responsible for | ||
39 | // remembering the exact syntax of each command, or at least so that the | ||
40 | // compiler could check things somewhat. I'll explain as we go... | ||
41 | // | ||
42 | // First, a structure which can embody the syntax of each type of command. | ||
43 | // | ||
44 | typedef struct _cmdSyntax | ||
45 | { | ||
46 | UCHAR length; // Number of bytes in the command | ||
47 | UCHAR flags; // Information about the command (see below) | ||
48 | |||
49 | // The command and its parameters, which may be of arbitrary length. Don't | ||
50 | // worry yet how the parameters will be initialized; macros later take care | ||
51 | // of it. Also, don't worry about the arbitrary length issue; this structure | ||
52 | // is never used to allocate space (see i2cmd.c). | ||
53 | UCHAR cmd[2]; | ||
54 | } cmdSyntax, *cmdSyntaxPtr; | ||
55 | |||
56 | // Bit assignments for flags | ||
57 | |||
58 | #define INL 1 // Set if suitable for inline commands | ||
59 | #define BYP 2 // Set if suitable for bypass commands | ||
60 | #define BTH (INL|BYP) // suitable for either! | ||
61 | #define END 4 // Set if this must be the last command in a block | ||
62 | #define VIP 8 // Set if this command is special in some way and really | ||
63 | // should only be sent from the library-level and not | ||
64 | // directly from user-level | ||
65 | #define VAR 0x10 // This command is of variable length! | ||
66 | |||
67 | // Declarations for the global arrays used to bear the commands and their | ||
68 | // arguments. | ||
69 | // | ||
70 | // Note: Since these are globals and the arguments might change, it is important | ||
71 | // that the library routine COPY these into buffers from whence they would be | ||
72 | // sent, rather than merely storing the pointers. In multi-threaded | ||
73 | // environments, important that the copy should obtain before any context switch | ||
74 | // is allowed. Also, for parameterized commands, DO NOT ISSUE THE SAME COMMAND | ||
75 | // MORE THAN ONCE WITH THE SAME PARAMETERS in the same call. | ||
76 | // | ||
77 | static UCHAR ct02[]; | ||
78 | static UCHAR ct03[]; | ||
79 | static UCHAR ct04[]; | ||
80 | static UCHAR ct05[]; | ||
81 | static UCHAR ct06[]; | ||
82 | static UCHAR ct07[]; | ||
83 | static UCHAR ct08[]; | ||
84 | static UCHAR ct09[]; | ||
85 | static UCHAR ct10[]; | ||
86 | static UCHAR ct11[]; | ||
87 | static UCHAR ct12[]; | ||
88 | static UCHAR ct13[]; | ||
89 | static UCHAR ct14[]; | ||
90 | static UCHAR ct15[]; | ||
91 | static UCHAR ct16[]; | ||
92 | static UCHAR ct17[]; | ||
93 | static UCHAR ct18[]; | ||
94 | static UCHAR ct19[]; | ||
95 | static UCHAR ct20[]; | ||
96 | static UCHAR ct21[]; | ||
97 | static UCHAR ct22[]; | ||
98 | static UCHAR ct23[]; | ||
99 | static UCHAR ct24[]; | ||
100 | static UCHAR ct25[]; | ||
101 | static UCHAR ct26[]; | ||
102 | static UCHAR ct27[]; | ||
103 | static UCHAR ct28[]; | ||
104 | static UCHAR ct29[]; | ||
105 | static UCHAR ct30[]; | ||
106 | static UCHAR ct31[]; | ||
107 | static UCHAR ct32[]; | ||
108 | static UCHAR ct33[]; | ||
109 | static UCHAR ct34[]; | ||
110 | static UCHAR ct35[]; | ||
111 | static UCHAR ct36[]; | ||
112 | static UCHAR ct36a[]; | ||
113 | static UCHAR ct41[]; | ||
114 | static UCHAR ct42[]; | ||
115 | static UCHAR ct43[]; | ||
116 | static UCHAR ct44[]; | ||
117 | static UCHAR ct45[]; | ||
118 | static UCHAR ct46[]; | ||
119 | static UCHAR ct48[]; | ||
120 | static UCHAR ct49[]; | ||
121 | static UCHAR ct50[]; | ||
122 | static UCHAR ct51[]; | ||
123 | static UCHAR ct52[]; | ||
124 | static UCHAR ct56[]; | ||
125 | static UCHAR ct57[]; | ||
126 | static UCHAR ct58[]; | ||
127 | static UCHAR ct59[]; | ||
128 | static UCHAR ct60[]; | ||
129 | static UCHAR ct61[]; | ||
130 | static UCHAR ct62[]; | ||
131 | static UCHAR ct63[]; | ||
132 | static UCHAR ct64[]; | ||
133 | static UCHAR ct65[]; | ||
134 | static UCHAR ct66[]; | ||
135 | static UCHAR ct67[]; | ||
136 | static UCHAR ct68[]; | ||
137 | static UCHAR ct69[]; | ||
138 | static UCHAR ct70[]; | ||
139 | static UCHAR ct71[]; | ||
140 | static UCHAR ct72[]; | ||
141 | static UCHAR ct73[]; | ||
142 | static UCHAR ct74[]; | ||
143 | static UCHAR ct75[]; | ||
144 | static UCHAR ct76[]; | ||
145 | static UCHAR ct77[]; | ||
146 | static UCHAR ct78[]; | ||
147 | static UCHAR ct79[]; | ||
148 | static UCHAR ct80[]; | ||
149 | static UCHAR ct81[]; | ||
150 | static UCHAR ct82[]; | ||
151 | static UCHAR ct83[]; | ||
152 | static UCHAR ct84[]; | ||
153 | static UCHAR ct85[]; | ||
154 | static UCHAR ct86[]; | ||
155 | static UCHAR ct87[]; | ||
156 | static UCHAR ct88[]; | ||
157 | static UCHAR ct89[]; | ||
158 | static UCHAR ct90[]; | ||
159 | static UCHAR ct91[]; | ||
160 | static UCHAR cc01[]; | ||
161 | static UCHAR cc02[]; | ||
162 | |||
163 | // Now, refer to i2cmd.c, and see the character arrays defined there. They are | ||
164 | // cast here to cmdSyntaxPtr. | ||
165 | // | ||
166 | // There are library functions for issuing bypass or inline commands. These | ||
167 | // functions take one or more arguments of the type cmdSyntaxPtr. The routine | ||
168 | // then can figure out how long each command is supposed to be and easily add it | ||
169 | // to the list. | ||
170 | // | ||
171 | // For ease of use, we define manifests which return pointers to appropriate | ||
172 | // cmdSyntaxPtr things. But some commands also take arguments. If a single | ||
173 | // argument is used, we define a macro which performs the single assignment and | ||
174 | // (through the expedient of a comma expression) references the appropriate | ||
175 | // pointer. For commands requiring several arguments, we actually define a | ||
176 | // function to perform the assignments. | ||
177 | |||
178 | #define CMD_DTRUP (cmdSyntaxPtr)(ct02) // Raise DTR | ||
179 | #define CMD_DTRDN (cmdSyntaxPtr)(ct03) // Lower DTR | ||
180 | #define CMD_RTSUP (cmdSyntaxPtr)(ct04) // Raise RTS | ||
181 | #define CMD_RTSDN (cmdSyntaxPtr)(ct05) // Lower RTS | ||
182 | #define CMD_STARTFL (cmdSyntaxPtr)(ct06) // Start Flushing Data | ||
183 | |||
184 | #define CMD_DTRRTS_UP (cmdSyntaxPtr)(cc01) // Raise DTR and RTS | ||
185 | #define CMD_DTRRTS_DN (cmdSyntaxPtr)(cc02) // Lower DTR and RTS | ||
186 | |||
187 | // Set Baud Rate for transmit and receive | ||
188 | #define CMD_SETBAUD(arg) \ | ||
189 | (((cmdSyntaxPtr)(ct07))->cmd[1] = (arg),(cmdSyntaxPtr)(ct07)) | ||
190 | |||
191 | #define CBR_50 1 | ||
192 | #define CBR_75 2 | ||
193 | #define CBR_110 3 | ||
194 | #define CBR_134 4 | ||
195 | #define CBR_150 5 | ||
196 | #define CBR_200 6 | ||
197 | #define CBR_300 7 | ||
198 | #define CBR_600 8 | ||
199 | #define CBR_1200 9 | ||
200 | #define CBR_1800 10 | ||
201 | #define CBR_2400 11 | ||
202 | #define CBR_4800 12 | ||
203 | #define CBR_9600 13 | ||
204 | #define CBR_19200 14 | ||
205 | #define CBR_38400 15 | ||
206 | #define CBR_2000 16 | ||
207 | #define CBR_3600 17 | ||
208 | #define CBR_7200 18 | ||
209 | #define CBR_56000 19 | ||
210 | #define CBR_57600 20 | ||
211 | #define CBR_64000 21 | ||
212 | #define CBR_76800 22 | ||
213 | #define CBR_115200 23 | ||
214 | #define CBR_C1 24 // Custom baud rate 1 | ||
215 | #define CBR_C2 25 // Custom baud rate 2 | ||
216 | #define CBR_153600 26 | ||
217 | #define CBR_230400 27 | ||
218 | #define CBR_307200 28 | ||
219 | #define CBR_460800 29 | ||
220 | #define CBR_921600 30 | ||
221 | |||
222 | // Set Character size | ||
223 | // | ||
224 | #define CMD_SETBITS(arg) \ | ||
225 | (((cmdSyntaxPtr)(ct08))->cmd[1] = (arg),(cmdSyntaxPtr)(ct08)) | ||
226 | |||
227 | #define CSZ_5 0 | ||
228 | #define CSZ_6 1 | ||
229 | #define CSZ_7 2 | ||
230 | #define CSZ_8 3 | ||
231 | |||
232 | // Set number of stop bits | ||
233 | // | ||
234 | #define CMD_SETSTOP(arg) \ | ||
235 | (((cmdSyntaxPtr)(ct09))->cmd[1] = (arg),(cmdSyntaxPtr)(ct09)) | ||
236 | |||
237 | #define CST_1 0 | ||
238 | #define CST_15 1 // 1.5 stop bits | ||
239 | #define CST_2 2 | ||
240 | |||
241 | // Set parity option | ||
242 | // | ||
243 | #define CMD_SETPAR(arg) \ | ||
244 | (((cmdSyntaxPtr)(ct10))->cmd[1] = (arg),(cmdSyntaxPtr)(ct10)) | ||
245 | |||
246 | #define CSP_NP 0 // no parity | ||
247 | #define CSP_OD 1 // odd parity | ||
248 | #define CSP_EV 2 // Even parity | ||
249 | #define CSP_SP 3 // Space parity | ||
250 | #define CSP_MK 4 // Mark parity | ||
251 | |||
252 | // Define xon char for transmitter flow control | ||
253 | // | ||
254 | #define CMD_DEF_IXON(arg) \ | ||
255 | (((cmdSyntaxPtr)(ct11))->cmd[1] = (arg),(cmdSyntaxPtr)(ct11)) | ||
256 | |||
257 | // Define xoff char for transmitter flow control | ||
258 | // | ||
259 | #define CMD_DEF_IXOFF(arg) \ | ||
260 | (((cmdSyntaxPtr)(ct12))->cmd[1] = (arg),(cmdSyntaxPtr)(ct12)) | ||
261 | |||
262 | #define CMD_STOPFL (cmdSyntaxPtr)(ct13) // Stop Flushing data | ||
263 | |||
264 | // Acknowledge receipt of hotkey signal | ||
265 | // | ||
266 | #define CMD_HOTACK (cmdSyntaxPtr)(ct14) | ||
267 | |||
268 | // Define irq level to use. Should actually be sent by library-level code, not | ||
269 | // directly from user... | ||
270 | // | ||
271 | #define CMDVALUE_IRQ 15 // For library use at initialization. Until this command | ||
272 | // is sent, board processing doesn't really start. | ||
273 | #define CMD_SET_IRQ(arg) \ | ||
274 | (((cmdSyntaxPtr)(ct15))->cmd[1] = (arg),(cmdSyntaxPtr)(ct15)) | ||
275 | |||
276 | #define CIR_POLL 0 // No IRQ - Poll | ||
277 | #define CIR_3 3 // IRQ 3 | ||
278 | #define CIR_4 4 // IRQ 4 | ||
279 | #define CIR_5 5 // IRQ 5 | ||
280 | #define CIR_7 7 // IRQ 7 | ||
281 | #define CIR_10 10 // IRQ 10 | ||
282 | #define CIR_11 11 // IRQ 11 | ||
283 | #define CIR_12 12 // IRQ 12 | ||
284 | #define CIR_15 15 // IRQ 15 | ||
285 | |||
286 | // Select transmit flow xon/xoff options | ||
287 | // | ||
288 | #define CMD_IXON_OPT(arg) \ | ||
289 | (((cmdSyntaxPtr)(ct16))->cmd[1] = (arg),(cmdSyntaxPtr)(ct16)) | ||
290 | |||
291 | #define CIX_NONE 0 // Incoming Xon/Xoff characters not special | ||
292 | #define CIX_XON 1 // Xoff disable, Xon enable | ||
293 | #define CIX_XANY 2 // Xoff disable, any key enable | ||
294 | |||
295 | // Select receive flow xon/xoff options | ||
296 | // | ||
297 | #define CMD_OXON_OPT(arg) \ | ||
298 | (((cmdSyntaxPtr)(ct17))->cmd[1] = (arg),(cmdSyntaxPtr)(ct17)) | ||
299 | |||
300 | #define COX_NONE 0 // Don't send Xon/Xoff | ||
301 | #define COX_XON 1 // Send xon/xoff to start/stop incoming data | ||
302 | |||
303 | |||
304 | #define CMD_CTS_REP (cmdSyntaxPtr)(ct18) // Enable CTS reporting | ||
305 | #define CMD_CTS_NREP (cmdSyntaxPtr)(ct19) // Disable CTS reporting | ||
306 | |||
307 | #define CMD_DCD_REP (cmdSyntaxPtr)(ct20) // Enable DCD reporting | ||
308 | #define CMD_DCD_NREP (cmdSyntaxPtr)(ct21) // Disable DCD reporting | ||
309 | |||
310 | #define CMD_DSR_REP (cmdSyntaxPtr)(ct22) // Enable DSR reporting | ||
311 | #define CMD_DSR_NREP (cmdSyntaxPtr)(ct23) // Disable DSR reporting | ||
312 | |||
313 | #define CMD_RI_REP (cmdSyntaxPtr)(ct24) // Enable RI reporting | ||
314 | #define CMD_RI_NREP (cmdSyntaxPtr)(ct25) // Disable RI reporting | ||
315 | |||
316 | // Enable break reporting and select style | ||
317 | // | ||
318 | #define CMD_BRK_REP(arg) \ | ||
319 | (((cmdSyntaxPtr)(ct26))->cmd[1] = (arg),(cmdSyntaxPtr)(ct26)) | ||
320 | |||
321 | #define CBK_STAT 0x00 // Report breaks as a status (exception,irq) | ||
322 | #define CBK_NULL 0x01 // Report breaks as a good null | ||
323 | #define CBK_STAT_SEQ 0x02 // Report breaks as a status AND as in-band character | ||
324 | // sequence FFh, 01h, 10h | ||
325 | #define CBK_SEQ 0x03 // Report breaks as the in-band | ||
326 | //sequence FFh, 01h, 10h ONLY. | ||
327 | #define CBK_FLSH 0x04 // if this bit set also flush input data | ||
328 | #define CBK_POSIX 0x08 // if this bit set report as FF,0,0 sequence | ||
329 | #define CBK_SINGLE 0x10 // if this bit set with CBK_SEQ or CBK_STAT_SEQ | ||
330 | //then reports single null instead of triple | ||
331 | |||
332 | #define CMD_BRK_NREP (cmdSyntaxPtr)(ct27) // Disable break reporting | ||
333 | |||
334 | // Specify maximum block size for received data | ||
335 | // | ||
336 | #define CMD_MAX_BLOCK(arg) \ | ||
337 | (((cmdSyntaxPtr)(ct28))->cmd[1] = (arg),(cmdSyntaxPtr)(ct28)) | ||
338 | |||
339 | // -- COMMAND 29 is reserved -- | ||
340 | |||
341 | #define CMD_CTSFL_ENAB (cmdSyntaxPtr)(ct30) // Enable CTS flow control | ||
342 | #define CMD_CTSFL_DSAB (cmdSyntaxPtr)(ct31) // Disable CTS flow control | ||
343 | #define CMD_RTSFL_ENAB (cmdSyntaxPtr)(ct32) // Enable RTS flow control | ||
344 | #define CMD_RTSFL_DSAB (cmdSyntaxPtr)(ct33) // Disable RTS flow control | ||
345 | |||
346 | // Specify istrip option | ||
347 | // | ||
348 | #define CMD_ISTRIP_OPT(arg) \ | ||
349 | (((cmdSyntaxPtr)(ct34))->cmd[1] = (arg),(cmdSyntaxPtr)(ct34)) | ||
350 | |||
351 | #define CIS_NOSTRIP 0 // Strip characters to character size | ||
352 | #define CIS_STRIP 1 // Strip any 8-bit characters to 7 bits | ||
353 | |||
354 | // Send a break of arg milliseconds | ||
355 | // | ||
356 | #define CMD_SEND_BRK(arg) \ | ||
357 | (((cmdSyntaxPtr)(ct35))->cmd[1] = (arg),(cmdSyntaxPtr)(ct35)) | ||
358 | |||
359 | // Set error reporting mode | ||
360 | // | ||
361 | #define CMD_SET_ERROR(arg) \ | ||
362 | (((cmdSyntaxPtr)(ct36))->cmd[1] = (arg),(cmdSyntaxPtr)(ct36)) | ||
363 | |||
364 | #define CSE_ESTAT 0 // Report error in a status packet | ||
365 | #define CSE_NOREP 1 // Treat character as though it were good | ||
366 | #define CSE_DROP 2 // Discard the character | ||
367 | #define CSE_NULL 3 // Replace with a null | ||
368 | #define CSE_MARK 4 // Replace with a 3-character sequence (as Unix) | ||
369 | |||
370 | #define CSE_REPLACE 0x8 // Replace the errored character with the | ||
371 | // replacement character defined here | ||
372 | |||
373 | #define CSE_STAT_REPLACE 0x18 // Replace the errored character with the | ||
374 | // replacement character defined here AND | ||
375 | // report the error as a status packet (as in | ||
376 | // CSE_ESTAT). | ||
377 | |||
378 | |||
379 | // COMMAND 37, to send flow control packets, is handled only by low-level | ||
380 | // library code in response to data movement and shouldn't ever be sent by the | ||
381 | // user code. See i2pack.h and the body of i2lib.c for details. | ||
382 | |||
383 | // Enable on-board post-processing, using options given in oflag argument. | ||
384 | // Formerly, this command was automatically preceded by a CMD_OPOST_OFF command | ||
385 | // because the loadware does not permit sending back-to-back CMD_OPOST_ON | ||
386 | // commands without an intervening CMD_OPOST_OFF. BUT, WE LEARN 18 MAY 92, that | ||
387 | // CMD_OPOST_ON and CMD_OPOST_OFF must each be at the end of a packet (or in a | ||
388 | // solo packet). This means the caller must specify separately CMD_OPOST_OFF, | ||
389 | // CMD_OPOST_ON(parm) when he calls i2QueueCommands(). That function will ensure | ||
390 | // each gets a separate packet. Extra CMD_OPOST_OFF's are always ok. | ||
391 | // | ||
392 | #define CMD_OPOST_ON(oflag) \ | ||
393 | (*(USHORT *)(((cmdSyntaxPtr)(ct39))->cmd[1]) = (oflag), \ | ||
394 | (cmdSyntaxPtr)(ct39)) | ||
395 | |||
396 | #define CMD_OPOST_OFF (cmdSyntaxPtr)(ct40) // Disable on-board post-proc | ||
397 | |||
398 | #define CMD_RESUME (cmdSyntaxPtr)(ct41) // Resume: behave as though an XON | ||
399 | // were received; | ||
400 | |||
401 | // Set Transmit baud rate (see command 7 for arguments) | ||
402 | // | ||
403 | #define CMD_SETBAUD_TX(arg) \ | ||
404 | (((cmdSyntaxPtr)(ct42))->cmd[1] = (arg),(cmdSyntaxPtr)(ct42)) | ||
405 | |||
406 | // Set Receive baud rate (see command 7 for arguments) | ||
407 | // | ||
408 | #define CMD_SETBAUD_RX(arg) \ | ||
409 | (((cmdSyntaxPtr)(ct43))->cmd[1] = (arg),(cmdSyntaxPtr)(ct43)) | ||
410 | |||
411 | // Request interrupt from board each arg milliseconds. Interrupt will specify | ||
412 | // "received data", even though there may be no data present. If arg == 0, | ||
413 | // disables any such interrupts. | ||
414 | // | ||
415 | #define CMD_PING_REQ(arg) \ | ||
416 | (((cmdSyntaxPtr)(ct44))->cmd[1] = (arg),(cmdSyntaxPtr)(ct44)) | ||
417 | |||
418 | #define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking | ||
419 | #define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking | ||
420 | |||
421 | #if 0 | ||
422 | // COMMAND 47: Send Protocol info via Unix flags: | ||
423 | // iflag = Unix tty t_iflag | ||
424 | // cflag = Unix tty t_cflag | ||
425 | // lflag = Unix tty t_lflag | ||
426 | // See System V Unix/Xenix documentation for the meanings of the bit fields | ||
427 | // within these flags | ||
428 | // | ||
429 | #define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag) | ||
430 | #endif /* 0 */ | ||
431 | |||
432 | #define CMD_DSRFL_ENAB (cmdSyntaxPtr)(ct48) // Enable DSR receiver ctrl | ||
433 | #define CMD_DSRFL_DSAB (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl | ||
434 | #define CMD_DTRFL_ENAB (cmdSyntaxPtr)(ct50) // Enable DTR flow control | ||
435 | #define CMD_DTRFL_DSAB (cmdSyntaxPtr)(ct51) // Disable DTR flow control | ||
436 | #define CMD_BAUD_RESET (cmdSyntaxPtr)(ct52) // Reset baudrate table | ||
437 | |||
438 | // COMMAND 54: Define custom rate #1 | ||
439 | // rate = (short) 1/10 of the desired baud rate | ||
440 | // | ||
441 | #define CMD_BAUD_DEF1(rate) i2cmdBaudDef(1,rate) | ||
442 | |||
443 | // COMMAND 55: Define custom rate #2 | ||
444 | // rate = (short) 1/10 of the desired baud rate | ||
445 | // | ||
446 | #define CMD_BAUD_DEF2(rate) i2cmdBaudDef(2,rate) | ||
447 | |||
448 | // Pause arg hundredths of seconds. (Note, this is NOT milliseconds.) | ||
449 | // | ||
450 | #define CMD_PAUSE(arg) \ | ||
451 | (((cmdSyntaxPtr)(ct56))->cmd[1] = (arg),(cmdSyntaxPtr)(ct56)) | ||
452 | |||
453 | #define CMD_SUSPEND (cmdSyntaxPtr)(ct57) // Suspend output | ||
454 | #define CMD_UNSUSPEND (cmdSyntaxPtr)(ct58) // Un-Suspend output | ||
455 | |||
456 | // Set parity-checking options | ||
457 | // | ||
458 | #define CMD_PARCHK(arg) \ | ||
459 | (((cmdSyntaxPtr)(ct59))->cmd[1] = (arg),(cmdSyntaxPtr)(ct59)) | ||
460 | |||
461 | #define CPK_ENAB 0 // Enable parity checking on input | ||
462 | #define CPK_DSAB 1 // Disable parity checking on input | ||
463 | |||
464 | #define CMD_BMARK_REQ (cmdSyntaxPtr)(ct60) // Bookmark request | ||
465 | |||
466 | |||
467 | // Enable/Disable internal loopback mode | ||
468 | // | ||
469 | #define CMD_INLOOP(arg) \ | ||
470 | (((cmdSyntaxPtr)(ct61))->cmd[1] = (arg),(cmdSyntaxPtr)(ct61)) | ||
471 | |||
472 | #define CIN_DISABLE 0 // Normal operation (default) | ||
473 | #define CIN_ENABLE 1 // Internal (local) loopback | ||
474 | #define CIN_REMOTE 2 // Remote loopback | ||
475 | |||
476 | // Specify timeout for hotkeys: Delay will be (arg x 10) milliseconds, arg == 0 | ||
477 | // --> no timeout: wait forever. | ||
478 | // | ||
479 | #define CMD_HOT_TIME(arg) \ | ||
480 | (((cmdSyntaxPtr)(ct62))->cmd[1] = (arg),(cmdSyntaxPtr)(ct62)) | ||
481 | |||
482 | |||
483 | // Define (outgoing) xon for receive flow control | ||
484 | // | ||
485 | #define CMD_DEF_OXON(arg) \ | ||
486 | (((cmdSyntaxPtr)(ct63))->cmd[1] = (arg),(cmdSyntaxPtr)(ct63)) | ||
487 | |||
488 | // Define (outgoing) xoff for receiver flow control | ||
489 | // | ||
490 | #define CMD_DEF_OXOFF(arg) \ | ||
491 | (((cmdSyntaxPtr)(ct64))->cmd[1] = (arg),(cmdSyntaxPtr)(ct64)) | ||
492 | |||
493 | // Enable/Disable RTS on transmit (1/2 duplex-style) | ||
494 | // | ||
495 | #define CMD_RTS_XMIT(arg) \ | ||
496 | (((cmdSyntaxPtr)(ct65))->cmd[1] = (arg),(cmdSyntaxPtr)(ct65)) | ||
497 | |||
498 | #define CHD_DISABLE 0 | ||
499 | #define CHD_ENABLE 1 | ||
500 | |||
501 | // Set high-water-mark level (debugging use only) | ||
502 | // | ||
503 | #define CMD_SETHIGHWAT(arg) \ | ||
504 | (((cmdSyntaxPtr)(ct66))->cmd[1] = (arg),(cmdSyntaxPtr)(ct66)) | ||
505 | |||
506 | // Start flushing tagged data (tag = 0-14) | ||
507 | // | ||
508 | #define CMD_START_SELFL(tag) \ | ||
509 | (((cmdSyntaxPtr)(ct67))->cmd[1] = (tag),(cmdSyntaxPtr)(ct67)) | ||
510 | |||
511 | // End flushing tagged data (tag = 0-14) | ||
512 | // | ||
513 | #define CMD_END_SELFL(tag) \ | ||
514 | (((cmdSyntaxPtr)(ct68))->cmd[1] = (tag),(cmdSyntaxPtr)(ct68)) | ||
515 | |||
516 | #define CMD_HWFLOW_OFF (cmdSyntaxPtr)(ct69) // Disable HW TX flow control | ||
517 | #define CMD_ODSRFL_ENAB (cmdSyntaxPtr)(ct70) // Enable DSR output f/c | ||
518 | #define CMD_ODSRFL_DSAB (cmdSyntaxPtr)(ct71) // Disable DSR output f/c | ||
519 | #define CMD_ODCDFL_ENAB (cmdSyntaxPtr)(ct72) // Enable DCD output f/c | ||
520 | #define CMD_ODCDFL_DSAB (cmdSyntaxPtr)(ct73) // Disable DCD output f/c | ||
521 | |||
522 | // Set transmit interrupt load level. Count should be an even value 2-12 | ||
523 | // | ||
524 | #define CMD_LOADLEVEL(count) \ | ||
525 | (((cmdSyntaxPtr)(ct74))->cmd[1] = (count),(cmdSyntaxPtr)(ct74)) | ||
526 | |||
527 | // If reporting DSS changes, map to character sequence FFh, 2, MSR | ||
528 | // | ||
529 | #define CMD_STATDATA(arg) \ | ||
530 | (((cmdSyntaxPtr)(ct75))->cmd[1] = (arg),(cmdSyntaxPtr)(ct75)) | ||
531 | |||
532 | #define CSTD_DISABLE// Report DSS changes as status packets only (default) | ||
533 | #define CSTD_ENABLE // Report DSS changes as in-band data sequence as well as | ||
534 | // by status packet. | ||
535 | |||
536 | #define CMD_BREAK_ON (cmdSyntaxPtr)(ct76)// Set break and stop xmit | ||
537 | #define CMD_BREAK_OFF (cmdSyntaxPtr)(ct77)// End break and restart xmit | ||
538 | #define CMD_GETFC (cmdSyntaxPtr)(ct78)// Request for flow control packet | ||
539 | // from board. | ||
540 | |||
541 | // Transmit this character immediately | ||
542 | // | ||
543 | #define CMD_XMIT_NOW(ch) \ | ||
544 | (((cmdSyntaxPtr)(ct79))->cmd[1] = (ch),(cmdSyntaxPtr)(ct79)) | ||
545 | |||
546 | // Set baud rate via "divisor latch" | ||
547 | // | ||
548 | #define CMD_DIVISOR_LATCH(which,value) \ | ||
549 | (((cmdSyntaxPtr)(ct80))->cmd[1] = (which), \ | ||
550 | *(USHORT *)(((cmdSyntaxPtr)(ct80))->cmd[2]) = (value), \ | ||
551 | (cmdSyntaxPtr)(ct80)) | ||
552 | |||
553 | #define CDL_RX 1 // Set receiver rate | ||
554 | #define CDL_TX 2 // Set transmit rate | ||
555 | // (CDL_TX | CDL_RX) Set both rates | ||
556 | |||
557 | // Request for special diagnostic status pkt from the board. | ||
558 | // | ||
559 | #define CMD_GET_STATUS (cmdSyntaxPtr)(ct81) | ||
560 | |||
561 | // Request time-stamped transmit character count packet. | ||
562 | // | ||
563 | #define CMD_GET_TXCNT (cmdSyntaxPtr)(ct82) | ||
564 | |||
565 | // Request time-stamped receive character count packet. | ||
566 | // | ||
567 | #define CMD_GET_RXCNT (cmdSyntaxPtr)(ct83) | ||
568 | |||
569 | // Request for box/board I.D. packet. | ||
570 | #define CMD_GET_BOXIDS (cmdSyntaxPtr)(ct84) | ||
571 | |||
572 | // Enable or disable multiple channels according to bit-mapped ushorts box 1-4 | ||
573 | // | ||
574 | #define CMD_ENAB_MULT(enable, box1, box2, box3, box4) \ | ||
575 | (((cmdSytaxPtr)(ct85))->cmd[1] = (enable), \ | ||
576 | *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[2]) = (box1), \ | ||
577 | *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[4]) = (box2), \ | ||
578 | *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[6]) = (box3), \ | ||
579 | *(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[8]) = (box4), \ | ||
580 | (cmdSyntaxPtr)(ct85)) | ||
581 | |||
582 | #define CEM_DISABLE 0 | ||
583 | #define CEM_ENABLE 1 | ||
584 | |||
585 | // Enable or disable receiver or receiver interrupts (default both enabled) | ||
586 | // | ||
587 | #define CMD_RCV_ENABLE(ch) \ | ||
588 | (((cmdSyntaxPtr)(ct86))->cmd[1] = (ch),(cmdSyntaxPtr)(ct86)) | ||
589 | |||
590 | #define CRE_OFF 0 // Disable the receiver | ||
591 | #define CRE_ON 1 // Enable the receiver | ||
592 | #define CRE_INTOFF 2 // Disable receiver interrupts (to loadware) | ||
593 | #define CRE_INTON 3 // Enable receiver interrupts (to loadware) | ||
594 | |||
595 | // Starts up a hardware test process, which runs transparently, and sends a | ||
596 | // STAT_HWFAIL packet in case a hardware failure is detected. | ||
597 | // | ||
598 | #define CMD_HW_TEST (cmdSyntaxPtr)(ct87) | ||
599 | |||
600 | // Change receiver threshold and timeout value: | ||
601 | // Defaults: timeout = 20mS | ||
602 | // threshold count = 8 when DTRflow not in use, | ||
603 | // threshold count = 5 when DTRflow in use. | ||
604 | // | ||
605 | #define CMD_RCV_THRESHOLD(count,ms) \ | ||
606 | (((cmdSyntaxPtr)(ct88))->cmd[1] = (count), \ | ||
607 | ((cmdSyntaxPtr)(ct88))->cmd[2] = (ms), \ | ||
608 | (cmdSyntaxPtr)(ct88)) | ||
609 | |||
610 | // Makes the loadware report DSS signals for this channel immediately. | ||
611 | // | ||
612 | #define CMD_DSS_NOW (cmdSyntaxPtr)(ct89) | ||
613 | |||
614 | // Set the receive silo parameters | ||
615 | // timeout is ms idle wait until delivery (~VTIME) | ||
616 | // threshold is max characters cause interrupt (~VMIN) | ||
617 | // | ||
618 | #define CMD_SET_SILO(timeout,threshold) \ | ||
619 | (((cmdSyntaxPtr)(ct90))->cmd[1] = (timeout), \ | ||
620 | ((cmdSyntaxPtr)(ct90))->cmd[2] = (threshold), \ | ||
621 | (cmdSyntaxPtr)(ct90)) | ||
622 | |||
623 | // Set timed break in decisecond (1/10s) | ||
624 | // | ||
625 | #define CMD_LBREAK(ds) \ | ||
626 | (((cmdSyntaxPtr)(ct91))->cmd[1] = (ds),(cmdSyntaxPtr)(ct66)) | ||
627 | |||
628 | |||
629 | |||
630 | #endif // I2CMD_H | ||
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c deleted file mode 100644 index 29db44de399f..000000000000 --- a/drivers/char/ip2/i2ellis.c +++ /dev/null | |||
@@ -1,1403 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Low-level interface code for the device driver | ||
12 | * (This is included source code, not a separate compilation | ||
13 | * module.) | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | //--------------------------------------------- | ||
17 | // Function declarations private to this module | ||
18 | //--------------------------------------------- | ||
19 | // Functions called only indirectly through i2eBordStr entries. | ||
20 | |||
21 | static int iiWriteBuf16(i2eBordStrPtr, unsigned char *, int); | ||
22 | static int iiWriteBuf8(i2eBordStrPtr, unsigned char *, int); | ||
23 | static int iiReadBuf16(i2eBordStrPtr, unsigned char *, int); | ||
24 | static int iiReadBuf8(i2eBordStrPtr, unsigned char *, int); | ||
25 | |||
26 | static unsigned short iiReadWord16(i2eBordStrPtr); | ||
27 | static unsigned short iiReadWord8(i2eBordStrPtr); | ||
28 | static void iiWriteWord16(i2eBordStrPtr, unsigned short); | ||
29 | static void iiWriteWord8(i2eBordStrPtr, unsigned short); | ||
30 | |||
31 | static int iiWaitForTxEmptyII(i2eBordStrPtr, int); | ||
32 | static int iiWaitForTxEmptyIIEX(i2eBordStrPtr, int); | ||
33 | static int iiTxMailEmptyII(i2eBordStrPtr); | ||
34 | static int iiTxMailEmptyIIEX(i2eBordStrPtr); | ||
35 | static int iiTrySendMailII(i2eBordStrPtr, unsigned char); | ||
36 | static int iiTrySendMailIIEX(i2eBordStrPtr, unsigned char); | ||
37 | |||
38 | static unsigned short iiGetMailII(i2eBordStrPtr); | ||
39 | static unsigned short iiGetMailIIEX(i2eBordStrPtr); | ||
40 | |||
41 | static void iiEnableMailIrqII(i2eBordStrPtr); | ||
42 | static void iiEnableMailIrqIIEX(i2eBordStrPtr); | ||
43 | static void iiWriteMaskII(i2eBordStrPtr, unsigned char); | ||
44 | static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char); | ||
45 | |||
46 | static void ii2Nop(void); | ||
47 | |||
48 | //*************** | ||
49 | //* Static Data * | ||
50 | //*************** | ||
51 | |||
52 | static int ii2Safe; // Safe I/O address for delay routine | ||
53 | |||
54 | static int iiDelayed; // Set when the iiResetDelay function is | ||
55 | // called. Cleared when ANY board is reset. | ||
56 | static DEFINE_RWLOCK(Dl_spinlock); | ||
57 | |||
58 | //******** | ||
59 | //* Code * | ||
60 | //******** | ||
61 | |||
62 | //======================================================= | ||
63 | // Initialization Routines | ||
64 | // | ||
65 | // iiSetAddress | ||
66 | // iiReset | ||
67 | // iiResetDelay | ||
68 | // iiInitialize | ||
69 | //======================================================= | ||
70 | |||
71 | //****************************************************************************** | ||
72 | // Function: iiSetAddress(pB, address, delay) | ||
73 | // Parameters: pB - pointer to the board structure | ||
74 | // address - the purported I/O address of the board | ||
75 | // delay - pointer to the 1-ms delay function to use | ||
76 | // in this and any future operations to this board | ||
77 | // | ||
78 | // Returns: True if everything appears copacetic. | ||
79 | // False if there is any error: the pB->i2eError field has the error | ||
80 | // | ||
81 | // Description: | ||
82 | // | ||
83 | // This routine (roughly) checks for address validity, sets the i2eValid OK and | ||
84 | // sets the state to II_STATE_COLD which means that we haven't even sent a reset | ||
85 | // yet. | ||
86 | // | ||
87 | //****************************************************************************** | ||
88 | static int | ||
89 | iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay ) | ||
90 | { | ||
91 | // Should any failure occur before init is finished... | ||
92 | pB->i2eValid = I2E_INCOMPLETE; | ||
93 | |||
94 | // Cannot check upper limit except extremely: Might be microchannel | ||
95 | // Address must be on an 8-byte boundary | ||
96 | |||
97 | if ((unsigned int)address <= 0x100 | ||
98 | || (unsigned int)address >= 0xfff8 | ||
99 | || (address & 0x7) | ||
100 | ) | ||
101 | { | ||
102 | I2_COMPLETE(pB, I2EE_BADADDR); | ||
103 | } | ||
104 | |||
105 | // Initialize accelerators | ||
106 | pB->i2eBase = address; | ||
107 | pB->i2eData = address + FIFO_DATA; | ||
108 | pB->i2eStatus = address + FIFO_STATUS; | ||
109 | pB->i2ePointer = address + FIFO_PTR; | ||
110 | pB->i2eXMail = address + FIFO_MAIL; | ||
111 | pB->i2eXMask = address + FIFO_MASK; | ||
112 | |||
113 | // Initialize i/o address for ii2DelayIO | ||
114 | ii2Safe = address + FIFO_NOP; | ||
115 | |||
116 | // Initialize the delay routine | ||
117 | pB->i2eDelay = ((delay != (delayFunc_t)NULL) ? delay : (delayFunc_t)ii2Nop); | ||
118 | |||
119 | pB->i2eValid = I2E_MAGIC; | ||
120 | pB->i2eState = II_STATE_COLD; | ||
121 | |||
122 | I2_COMPLETE(pB, I2EE_GOOD); | ||
123 | } | ||
124 | |||
125 | //****************************************************************************** | ||
126 | // Function: iiReset(pB) | ||
127 | // Parameters: pB - pointer to the board structure | ||
128 | // | ||
129 | // Returns: True if everything appears copacetic. | ||
130 | // False if there is any error: the pB->i2eError field has the error | ||
131 | // | ||
132 | // Description: | ||
133 | // | ||
134 | // Attempts to reset the board (see also i2hw.h). Normally, we would use this to | ||
135 | // reset a board immediately after iiSetAddress(), but it is valid to reset a | ||
136 | // board from any state, say, in order to change or re-load loadware. (Under | ||
137 | // such circumstances, no reason to re-run iiSetAddress(), which is why it is a | ||
138 | // separate routine and not included in this routine. | ||
139 | // | ||
140 | //****************************************************************************** | ||
141 | static int | ||
142 | iiReset(i2eBordStrPtr pB) | ||
143 | { | ||
144 | // Magic number should be set, else even the address is suspect | ||
145 | if (pB->i2eValid != I2E_MAGIC) | ||
146 | { | ||
147 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
148 | } | ||
149 | |||
150 | outb(0, pB->i2eBase + FIFO_RESET); /* Any data will do */ | ||
151 | iiDelay(pB, 50); // Pause between resets | ||
152 | outb(0, pB->i2eBase + FIFO_RESET); /* Second reset */ | ||
153 | |||
154 | // We must wait before even attempting to read anything from the FIFO: the | ||
155 | // board's P.O.S.T may actually attempt to read and write its end of the | ||
156 | // FIFO in order to check flags, loop back (where supported), etc. On | ||
157 | // completion of this testing it would reset the FIFO, and on completion | ||
158 | // of all // P.O.S.T., write the message. We must not mistake data which | ||
159 | // might have been sent for testing as part of the reset message. To | ||
160 | // better utilize time, say, when resetting several boards, we allow the | ||
161 | // delay to be performed externally; in this way the caller can reset | ||
162 | // several boards, delay a single time, then call the initialization | ||
163 | // routine for all. | ||
164 | |||
165 | pB->i2eState = II_STATE_RESET; | ||
166 | |||
167 | iiDelayed = 0; // i.e., the delay routine hasn't been called since the most | ||
168 | // recent reset. | ||
169 | |||
170 | // Ensure anything which would have been of use to standard loadware is | ||
171 | // blanked out, since board has now forgotten everything!. | ||
172 | |||
173 | pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */ | ||
174 | pB->i2eWaitingForEmptyFifo = 0; | ||
175 | pB->i2eOutMailWaiting = 0; | ||
176 | pB->i2eChannelPtr = NULL; | ||
177 | pB->i2eChannelCnt = 0; | ||
178 | |||
179 | pB->i2eLeadoffWord[0] = 0; | ||
180 | pB->i2eFifoInInts = 0; | ||
181 | pB->i2eFifoOutInts = 0; | ||
182 | pB->i2eFatalTrap = NULL; | ||
183 | pB->i2eFatal = 0; | ||
184 | |||
185 | I2_COMPLETE(pB, I2EE_GOOD); | ||
186 | } | ||
187 | |||
188 | //****************************************************************************** | ||
189 | // Function: iiResetDelay(pB) | ||
190 | // Parameters: pB - pointer to the board structure | ||
191 | // | ||
192 | // Returns: True if everything appears copacetic. | ||
193 | // False if there is any error: the pB->i2eError field has the error | ||
194 | // | ||
195 | // Description: | ||
196 | // | ||
197 | // Using the delay defined in board structure, waits two seconds (for board to | ||
198 | // reset). | ||
199 | // | ||
200 | //****************************************************************************** | ||
201 | static int | ||
202 | iiResetDelay(i2eBordStrPtr pB) | ||
203 | { | ||
204 | if (pB->i2eValid != I2E_MAGIC) { | ||
205 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
206 | } | ||
207 | if (pB->i2eState != II_STATE_RESET) { | ||
208 | I2_COMPLETE(pB, I2EE_BADSTATE); | ||
209 | } | ||
210 | iiDelay(pB,2000); /* Now we wait for two seconds. */ | ||
211 | iiDelayed = 1; /* Delay has been called: ok to initialize */ | ||
212 | I2_COMPLETE(pB, I2EE_GOOD); | ||
213 | } | ||
214 | |||
215 | //****************************************************************************** | ||
216 | // Function: iiInitialize(pB) | ||
217 | // Parameters: pB - pointer to the board structure | ||
218 | // | ||
219 | // Returns: True if everything appears copacetic. | ||
220 | // False if there is any error: the pB->i2eError field has the error | ||
221 | // | ||
222 | // Description: | ||
223 | // | ||
224 | // Attempts to read the Power-on reset message. Initializes any remaining fields | ||
225 | // in the pB structure. | ||
226 | // | ||
227 | // This should be called as the third step of a process beginning with | ||
228 | // iiReset(), then iiResetDelay(). This routine checks to see that the structure | ||
229 | // is "valid" and in the reset state, also confirms that the delay routine has | ||
230 | // been called since the latest reset (to any board! overly strong!). | ||
231 | // | ||
232 | //****************************************************************************** | ||
233 | static int | ||
234 | iiInitialize(i2eBordStrPtr pB) | ||
235 | { | ||
236 | int itemp; | ||
237 | unsigned char c; | ||
238 | unsigned short utemp; | ||
239 | unsigned int ilimit; | ||
240 | |||
241 | if (pB->i2eValid != I2E_MAGIC) | ||
242 | { | ||
243 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
244 | } | ||
245 | |||
246 | if (pB->i2eState != II_STATE_RESET || !iiDelayed) | ||
247 | { | ||
248 | I2_COMPLETE(pB, I2EE_BADSTATE); | ||
249 | } | ||
250 | |||
251 | // In case there is a failure short of our completely reading the power-up | ||
252 | // message. | ||
253 | pB->i2eValid = I2E_INCOMPLETE; | ||
254 | |||
255 | |||
256 | // Now attempt to read the message. | ||
257 | |||
258 | for (itemp = 0; itemp < sizeof(porStr); itemp++) | ||
259 | { | ||
260 | // We expect the entire message is ready. | ||
261 | if (!I2_HAS_INPUT(pB)) { | ||
262 | pB->i2ePomSize = itemp; | ||
263 | I2_COMPLETE(pB, I2EE_PORM_SHORT); | ||
264 | } | ||
265 | |||
266 | pB->i2ePom.c[itemp] = c = inb(pB->i2eData); | ||
267 | |||
268 | // We check the magic numbers as soon as they are supposed to be read | ||
269 | // (rather than after) to minimize effect of reading something we | ||
270 | // already suspect can't be "us". | ||
271 | if ( (itemp == POR_1_INDEX && c != POR_MAGIC_1) || | ||
272 | (itemp == POR_2_INDEX && c != POR_MAGIC_2)) | ||
273 | { | ||
274 | pB->i2ePomSize = itemp+1; | ||
275 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | pB->i2ePomSize = itemp; | ||
280 | |||
281 | // Ensure that this was all the data... | ||
282 | if (I2_HAS_INPUT(pB)) | ||
283 | I2_COMPLETE(pB, I2EE_PORM_LONG); | ||
284 | |||
285 | // For now, we'll fail to initialize if P.O.S.T reports bad chip mapper: | ||
286 | // Implying we will not be able to download any code either: That's ok: the | ||
287 | // condition is pretty explicit. | ||
288 | if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER) | ||
289 | { | ||
290 | I2_COMPLETE(pB, I2EE_POSTERR); | ||
291 | } | ||
292 | |||
293 | // Determine anything which must be done differently depending on the family | ||
294 | // of boards! | ||
295 | switch (pB->i2ePom.e.porID & POR_ID_FAMILY) | ||
296 | { | ||
297 | case POR_ID_FII: // IntelliPort-II | ||
298 | |||
299 | pB->i2eFifoStyle = FIFO_II; | ||
300 | pB->i2eFifoSize = 512; // 512 bytes, always | ||
301 | pB->i2eDataWidth16 = false; | ||
302 | |||
303 | pB->i2eMaxIrq = 15; // Because board cannot tell us it is in an 8-bit | ||
304 | // slot, we do allow it to be done (documentation!) | ||
305 | |||
306 | pB->i2eGoodMap[1] = | ||
307 | pB->i2eGoodMap[2] = | ||
308 | pB->i2eGoodMap[3] = | ||
309 | pB->i2eChannelMap[1] = | ||
310 | pB->i2eChannelMap[2] = | ||
311 | pB->i2eChannelMap[3] = 0; | ||
312 | |||
313 | switch (pB->i2ePom.e.porID & POR_ID_SIZE) | ||
314 | { | ||
315 | case POR_ID_II_4: | ||
316 | pB->i2eGoodMap[0] = | ||
317 | pB->i2eChannelMap[0] = 0x0f; // four-port | ||
318 | |||
319 | // Since porPorts1 is based on the Hardware ID register, the numbers | ||
320 | // should always be consistent for IntelliPort-II. Ditto below... | ||
321 | if (pB->i2ePom.e.porPorts1 != 4) | ||
322 | { | ||
323 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
324 | } | ||
325 | break; | ||
326 | |||
327 | case POR_ID_II_8: | ||
328 | case POR_ID_II_8R: | ||
329 | pB->i2eGoodMap[0] = | ||
330 | pB->i2eChannelMap[0] = 0xff; // Eight port | ||
331 | if (pB->i2ePom.e.porPorts1 != 8) | ||
332 | { | ||
333 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
334 | } | ||
335 | break; | ||
336 | |||
337 | case POR_ID_II_6: | ||
338 | pB->i2eGoodMap[0] = | ||
339 | pB->i2eChannelMap[0] = 0x3f; // Six Port | ||
340 | if (pB->i2ePom.e.porPorts1 != 6) | ||
341 | { | ||
342 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
343 | } | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | // Fix up the "good channel list based on any errors reported. | ||
348 | if (pB->i2ePom.e.porDiag1 & POR_BAD_UART1) | ||
349 | { | ||
350 | pB->i2eGoodMap[0] &= ~0x0f; | ||
351 | } | ||
352 | |||
353 | if (pB->i2ePom.e.porDiag1 & POR_BAD_UART2) | ||
354 | { | ||
355 | pB->i2eGoodMap[0] &= ~0xf0; | ||
356 | } | ||
357 | |||
358 | break; // POR_ID_FII case | ||
359 | |||
360 | case POR_ID_FIIEX: // IntelliPort-IIEX | ||
361 | |||
362 | pB->i2eFifoStyle = FIFO_IIEX; | ||
363 | |||
364 | itemp = pB->i2ePom.e.porFifoSize; | ||
365 | |||
366 | // Implicit assumption that fifo would not grow beyond 32k, | ||
367 | // nor would ever be less than 256. | ||
368 | |||
369 | if (itemp < 8 || itemp > 15) | ||
370 | { | ||
371 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
372 | } | ||
373 | pB->i2eFifoSize = (1 << itemp); | ||
374 | |||
375 | // These are based on what P.O.S.T thinks should be there, based on | ||
376 | // box ID registers | ||
377 | ilimit = pB->i2ePom.e.porNumBoxes; | ||
378 | if (ilimit > ABS_MAX_BOXES) | ||
379 | { | ||
380 | ilimit = ABS_MAX_BOXES; | ||
381 | } | ||
382 | |||
383 | // For as many boxes as EXIST, gives the type of box. | ||
384 | // Added 8/6/93: check for the ISA-4 (asic) which looks like an | ||
385 | // expandable but for whom "8 or 16?" is not the right question. | ||
386 | |||
387 | utemp = pB->i2ePom.e.porFlags; | ||
388 | if (utemp & POR_CEX4) | ||
389 | { | ||
390 | pB->i2eChannelMap[0] = 0x000f; | ||
391 | } else { | ||
392 | utemp &= POR_BOXES; | ||
393 | for (itemp = 0; itemp < ilimit; itemp++) | ||
394 | { | ||
395 | pB->i2eChannelMap[itemp] = | ||
396 | ((utemp & POR_BOX_16) ? 0xffff : 0x00ff); | ||
397 | utemp >>= 1; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | // These are based on what P.O.S.T actually found. | ||
402 | |||
403 | utemp = (pB->i2ePom.e.porPorts2 << 8) + pB->i2ePom.e.porPorts1; | ||
404 | |||
405 | for (itemp = 0; itemp < ilimit; itemp++) | ||
406 | { | ||
407 | pB->i2eGoodMap[itemp] = 0; | ||
408 | if (utemp & 1) pB->i2eGoodMap[itemp] |= 0x000f; | ||
409 | if (utemp & 2) pB->i2eGoodMap[itemp] |= 0x00f0; | ||
410 | if (utemp & 4) pB->i2eGoodMap[itemp] |= 0x0f00; | ||
411 | if (utemp & 8) pB->i2eGoodMap[itemp] |= 0xf000; | ||
412 | utemp >>= 4; | ||
413 | } | ||
414 | |||
415 | // Now determine whether we should transfer in 8 or 16-bit mode. | ||
416 | switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) ) | ||
417 | { | ||
418 | case POR_BUS_SLOT16 | POR_BUS_DIP16: | ||
419 | pB->i2eDataWidth16 = true; | ||
420 | pB->i2eMaxIrq = 15; | ||
421 | break; | ||
422 | |||
423 | case POR_BUS_SLOT16: | ||
424 | pB->i2eDataWidth16 = false; | ||
425 | pB->i2eMaxIrq = 15; | ||
426 | break; | ||
427 | |||
428 | case 0: | ||
429 | case POR_BUS_DIP16: // In an 8-bit slot, DIP switch don't care. | ||
430 | default: | ||
431 | pB->i2eDataWidth16 = false; | ||
432 | pB->i2eMaxIrq = 7; | ||
433 | break; | ||
434 | } | ||
435 | break; // POR_ID_FIIEX case | ||
436 | |||
437 | default: // Unknown type of board | ||
438 | I2_COMPLETE(pB, I2EE_BAD_FAMILY); | ||
439 | break; | ||
440 | } // End the switch based on family | ||
441 | |||
442 | // Temporarily, claim there is no room in the outbound fifo. | ||
443 | // We will maintain this whenever we check for an empty outbound FIFO. | ||
444 | pB->i2eFifoRemains = 0; | ||
445 | |||
446 | // Now, based on the bus type, should we expect to be able to re-configure | ||
447 | // interrupts (say, for testing purposes). | ||
448 | switch (pB->i2ePom.e.porBus & POR_BUS_TYPE) | ||
449 | { | ||
450 | case POR_BUS_T_ISA: | ||
451 | case POR_BUS_T_UNK: // If the type of bus is undeclared, assume ok. | ||
452 | case POR_BUS_T_MCA: | ||
453 | case POR_BUS_T_EISA: | ||
454 | break; | ||
455 | default: | ||
456 | I2_COMPLETE(pB, I2EE_BADBUS); | ||
457 | } | ||
458 | |||
459 | if (pB->i2eDataWidth16) | ||
460 | { | ||
461 | pB->i2eWriteBuf = iiWriteBuf16; | ||
462 | pB->i2eReadBuf = iiReadBuf16; | ||
463 | pB->i2eWriteWord = iiWriteWord16; | ||
464 | pB->i2eReadWord = iiReadWord16; | ||
465 | } else { | ||
466 | pB->i2eWriteBuf = iiWriteBuf8; | ||
467 | pB->i2eReadBuf = iiReadBuf8; | ||
468 | pB->i2eWriteWord = iiWriteWord8; | ||
469 | pB->i2eReadWord = iiReadWord8; | ||
470 | } | ||
471 | |||
472 | switch(pB->i2eFifoStyle) | ||
473 | { | ||
474 | case FIFO_II: | ||
475 | pB->i2eWaitForTxEmpty = iiWaitForTxEmptyII; | ||
476 | pB->i2eTxMailEmpty = iiTxMailEmptyII; | ||
477 | pB->i2eTrySendMail = iiTrySendMailII; | ||
478 | pB->i2eGetMail = iiGetMailII; | ||
479 | pB->i2eEnableMailIrq = iiEnableMailIrqII; | ||
480 | pB->i2eWriteMask = iiWriteMaskII; | ||
481 | |||
482 | break; | ||
483 | |||
484 | case FIFO_IIEX: | ||
485 | pB->i2eWaitForTxEmpty = iiWaitForTxEmptyIIEX; | ||
486 | pB->i2eTxMailEmpty = iiTxMailEmptyIIEX; | ||
487 | pB->i2eTrySendMail = iiTrySendMailIIEX; | ||
488 | pB->i2eGetMail = iiGetMailIIEX; | ||
489 | pB->i2eEnableMailIrq = iiEnableMailIrqIIEX; | ||
490 | pB->i2eWriteMask = iiWriteMaskIIEX; | ||
491 | |||
492 | break; | ||
493 | |||
494 | default: | ||
495 | I2_COMPLETE(pB, I2EE_INCONSIST); | ||
496 | } | ||
497 | |||
498 | // Initialize state information. | ||
499 | pB->i2eState = II_STATE_READY; // Ready to load loadware. | ||
500 | |||
501 | // Some Final cleanup: | ||
502 | // For some boards, the bootstrap firmware may perform some sort of test | ||
503 | // resulting in a stray character pending in the incoming mailbox. If one is | ||
504 | // there, it should be read and discarded, especially since for the standard | ||
505 | // firmware, it's the mailbox that interrupts the host. | ||
506 | |||
507 | pB->i2eStartMail = iiGetMail(pB); | ||
508 | |||
509 | // Throw it away and clear the mailbox structure element | ||
510 | pB->i2eStartMail = NO_MAIL_HERE; | ||
511 | |||
512 | // Everything is ok now, return with good status/ | ||
513 | |||
514 | pB->i2eValid = I2E_MAGIC; | ||
515 | I2_COMPLETE(pB, I2EE_GOOD); | ||
516 | } | ||
517 | |||
518 | //****************************************************************************** | ||
519 | // Function: ii2DelayTimer(mseconds) | ||
520 | // Parameters: mseconds - number of milliseconds to delay | ||
521 | // | ||
522 | // Returns: Nothing | ||
523 | // | ||
524 | // Description: | ||
525 | // | ||
526 | // This routine delays for approximately mseconds milliseconds and is intended | ||
527 | // to be called indirectly through i2Delay field in i2eBordStr. It uses the | ||
528 | // Linux timer_list mechanism. | ||
529 | // | ||
530 | // The Linux timers use a unit called "jiffies" which are 10mS in the Intel | ||
531 | // architecture. This function rounds the delay period up to the next "jiffy". | ||
532 | // In the Alpha architecture the "jiffy" is 1mS, but this driver is not intended | ||
533 | // for Alpha platforms at this time. | ||
534 | // | ||
535 | //****************************************************************************** | ||
536 | static void | ||
537 | ii2DelayTimer(unsigned int mseconds) | ||
538 | { | ||
539 | msleep_interruptible(mseconds); | ||
540 | } | ||
541 | |||
542 | #if 0 | ||
543 | //static void ii2DelayIO(unsigned int); | ||
544 | //****************************************************************************** | ||
545 | // !!! Not Used, this is DOS crap, some of you young folks may be interested in | ||
546 | // in how things were done in the stone age of caculating machines !!! | ||
547 | // Function: ii2DelayIO(mseconds) | ||
548 | // Parameters: mseconds - number of milliseconds to delay | ||
549 | // | ||
550 | // Returns: Nothing | ||
551 | // | ||
552 | // Description: | ||
553 | // | ||
554 | // This routine delays for approximately mseconds milliseconds and is intended | ||
555 | // to be called indirectly through i2Delay field in i2eBordStr. It is intended | ||
556 | // for use where a clock-based function is impossible: for example, DOS drivers. | ||
557 | // | ||
558 | // This function uses the IN instruction to place bounds on the timing and | ||
559 | // assumes that ii2Safe has been set. This is because I/O instructions are not | ||
560 | // subject to caching and will therefore take a certain minimum time. To ensure | ||
561 | // the delay is at least long enough on fast machines, it is based on some | ||
562 | // fastest-case calculations. On slower machines this may cause VERY long | ||
563 | // delays. (3 x fastest case). In the fastest case, everything is cached except | ||
564 | // the I/O instruction itself. | ||
565 | // | ||
566 | // Timing calculations: | ||
567 | // The fastest bus speed for I/O operations is likely to be 10 MHz. The I/O | ||
568 | // operation in question is a byte operation to an odd address. For 8-bit | ||
569 | // operations, the architecture generally enforces two wait states. At 10 MHz, a | ||
570 | // single cycle time is 100nS. A read operation at two wait states takes 6 | ||
571 | // cycles for a total time of 600nS. Therefore approximately 1666 iterations | ||
572 | // would be required to generate a single millisecond delay. The worst | ||
573 | // (reasonable) case would be an 8MHz system with no cacheing. In this case, the | ||
574 | // I/O instruction would take 125nS x 6 cyles = 750 nS. More importantly, code | ||
575 | // fetch of other instructions in the loop would take time (zero wait states, | ||
576 | // however) and would be hard to estimate. This is minimized by using in-line | ||
577 | // assembler for the in inner loop of IN instructions. This consists of just a | ||
578 | // few bytes. So we'll guess about four code fetches per loop. Each code fetch | ||
579 | // should take four cycles, so we have 125nS * 8 = 1000nS. Worst case then is | ||
580 | // that what should have taken 1 mS takes instead 1666 * (1750) = 2.9 mS. | ||
581 | // | ||
582 | // So much for theoretical timings: results using 1666 value on some actual | ||
583 | // machines: | ||
584 | // IBM 286 6MHz 3.15 mS | ||
585 | // Zenith 386 33MHz 2.45 mS | ||
586 | // (brandX) 386 33MHz 1.90 mS (has cache) | ||
587 | // (brandY) 486 33MHz 2.35 mS | ||
588 | // NCR 486 ?? 1.65 mS (microchannel) | ||
589 | // | ||
590 | // For most machines, it is probably safe to scale this number back (remember, | ||
591 | // for robust operation use an actual timed delay if possible), so we are using | ||
592 | // a value of 1190. This yields 1.17 mS for the fastest machine in our sample, | ||
593 | // 1.75 mS for typical 386 machines, and 2.25 mS the absolute slowest machine. | ||
594 | // | ||
595 | // 1/29/93: | ||
596 | // The above timings are too slow. Actual cycle times might be faster. ISA cycle | ||
597 | // times could approach 500 nS, and ... | ||
598 | // The IBM model 77 being microchannel has no wait states for 8-bit reads and | ||
599 | // seems to be accessing the I/O at 440 nS per access (from start of one to | ||
600 | // start of next). This would imply we need 1000/.440 = 2272 iterations to | ||
601 | // guarantee we are fast enough. In actual testing, we see that 2 * 1190 are in | ||
602 | // fact enough. For diagnostics, we keep the level at 1190, but developers note | ||
603 | // this needs tuning. | ||
604 | // | ||
605 | // Safe assumption: 2270 i/o reads = 1 millisecond | ||
606 | // | ||
607 | //****************************************************************************** | ||
608 | |||
609 | |||
610 | static int ii2DelValue = 1190; // See timing calculations below | ||
611 | // 1666 for fastest theoretical machine | ||
612 | // 1190 safe for most fast 386 machines | ||
613 | // 1000 for fastest machine tested here | ||
614 | // 540 (sic) for AT286/6Mhz | ||
615 | static void | ||
616 | ii2DelayIO(unsigned int mseconds) | ||
617 | { | ||
618 | if (!ii2Safe) | ||
619 | return; /* Do nothing if this variable uninitialized */ | ||
620 | |||
621 | while(mseconds--) { | ||
622 | int i = ii2DelValue; | ||
623 | while ( i-- ) { | ||
624 | inb(ii2Safe); | ||
625 | } | ||
626 | } | ||
627 | } | ||
628 | #endif | ||
629 | |||
630 | //****************************************************************************** | ||
631 | // Function: ii2Nop() | ||
632 | // Parameters: None | ||
633 | // | ||
634 | // Returns: Nothing | ||
635 | // | ||
636 | // Description: | ||
637 | // | ||
638 | // iiInitialize will set i2eDelay to this if the delay parameter is NULL. This | ||
639 | // saves checking for a NULL pointer at every call. | ||
640 | //****************************************************************************** | ||
641 | static void | ||
642 | ii2Nop(void) | ||
643 | { | ||
644 | return; // no mystery here | ||
645 | } | ||
646 | |||
647 | //======================================================= | ||
648 | // Routines which are available in 8/16-bit versions, or | ||
649 | // in different fifo styles. These are ALL called | ||
650 | // indirectly through the board structure. | ||
651 | //======================================================= | ||
652 | |||
653 | //****************************************************************************** | ||
654 | // Function: iiWriteBuf16(pB, address, count) | ||
655 | // Parameters: pB - pointer to board structure | ||
656 | // address - address of data to write | ||
657 | // count - number of data bytes to write | ||
658 | // | ||
659 | // Returns: True if everything appears copacetic. | ||
660 | // False if there is any error: the pB->i2eError field has the error | ||
661 | // | ||
662 | // Description: | ||
663 | // | ||
664 | // Writes 'count' bytes from 'address' to the data fifo specified by the board | ||
665 | // structure pointer pB. Should count happen to be odd, an extra pad byte is | ||
666 | // sent (identity unknown...). Uses 16-bit (word) operations. Is called | ||
667 | // indirectly through pB->i2eWriteBuf. | ||
668 | // | ||
669 | //****************************************************************************** | ||
670 | static int | ||
671 | iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count) | ||
672 | { | ||
673 | // Rudimentary sanity checking here. | ||
674 | if (pB->i2eValid != I2E_MAGIC) | ||
675 | I2_COMPLETE(pB, I2EE_INVALID); | ||
676 | |||
677 | I2_OUTSW(pB->i2eData, address, count); | ||
678 | |||
679 | I2_COMPLETE(pB, I2EE_GOOD); | ||
680 | } | ||
681 | |||
682 | //****************************************************************************** | ||
683 | // Function: iiWriteBuf8(pB, address, count) | ||
684 | // Parameters: pB - pointer to board structure | ||
685 | // address - address of data to write | ||
686 | // count - number of data bytes to write | ||
687 | // | ||
688 | // Returns: True if everything appears copacetic. | ||
689 | // False if there is any error: the pB->i2eError field has the error | ||
690 | // | ||
691 | // Description: | ||
692 | // | ||
693 | // Writes 'count' bytes from 'address' to the data fifo specified by the board | ||
694 | // structure pointer pB. Should count happen to be odd, an extra pad byte is | ||
695 | // sent (identity unknown...). This is to be consistent with the 16-bit version. | ||
696 | // Uses 8-bit (byte) operations. Is called indirectly through pB->i2eWriteBuf. | ||
697 | // | ||
698 | //****************************************************************************** | ||
699 | static int | ||
700 | iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count) | ||
701 | { | ||
702 | /* Rudimentary sanity checking here */ | ||
703 | if (pB->i2eValid != I2E_MAGIC) | ||
704 | I2_COMPLETE(pB, I2EE_INVALID); | ||
705 | |||
706 | I2_OUTSB(pB->i2eData, address, count); | ||
707 | |||
708 | I2_COMPLETE(pB, I2EE_GOOD); | ||
709 | } | ||
710 | |||
711 | //****************************************************************************** | ||
712 | // Function: iiReadBuf16(pB, address, count) | ||
713 | // Parameters: pB - pointer to board structure | ||
714 | // address - address to put data read | ||
715 | // count - number of data bytes to read | ||
716 | // | ||
717 | // Returns: True if everything appears copacetic. | ||
718 | // False if there is any error: the pB->i2eError field has the error | ||
719 | // | ||
720 | // Description: | ||
721 | // | ||
722 | // Reads 'count' bytes into 'address' from the data fifo specified by the board | ||
723 | // structure pointer pB. Should count happen to be odd, an extra pad byte is | ||
724 | // received (identity unknown...). Uses 16-bit (word) operations. Is called | ||
725 | // indirectly through pB->i2eReadBuf. | ||
726 | // | ||
727 | //****************************************************************************** | ||
728 | static int | ||
729 | iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count) | ||
730 | { | ||
731 | // Rudimentary sanity checking here. | ||
732 | if (pB->i2eValid != I2E_MAGIC) | ||
733 | I2_COMPLETE(pB, I2EE_INVALID); | ||
734 | |||
735 | I2_INSW(pB->i2eData, address, count); | ||
736 | |||
737 | I2_COMPLETE(pB, I2EE_GOOD); | ||
738 | } | ||
739 | |||
740 | //****************************************************************************** | ||
741 | // Function: iiReadBuf8(pB, address, count) | ||
742 | // Parameters: pB - pointer to board structure | ||
743 | // address - address to put data read | ||
744 | // count - number of data bytes to read | ||
745 | // | ||
746 | // Returns: True if everything appears copacetic. | ||
747 | // False if there is any error: the pB->i2eError field has the error | ||
748 | // | ||
749 | // Description: | ||
750 | // | ||
751 | // Reads 'count' bytes into 'address' from the data fifo specified by the board | ||
752 | // structure pointer pB. Should count happen to be odd, an extra pad byte is | ||
753 | // received (identity unknown...). This to match the 16-bit behaviour. Uses | ||
754 | // 8-bit (byte) operations. Is called indirectly through pB->i2eReadBuf. | ||
755 | // | ||
756 | //****************************************************************************** | ||
757 | static int | ||
758 | iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count) | ||
759 | { | ||
760 | // Rudimentary sanity checking here. | ||
761 | if (pB->i2eValid != I2E_MAGIC) | ||
762 | I2_COMPLETE(pB, I2EE_INVALID); | ||
763 | |||
764 | I2_INSB(pB->i2eData, address, count); | ||
765 | |||
766 | I2_COMPLETE(pB, I2EE_GOOD); | ||
767 | } | ||
768 | |||
769 | //****************************************************************************** | ||
770 | // Function: iiReadWord16(pB) | ||
771 | // Parameters: pB - pointer to board structure | ||
772 | // | ||
773 | // Returns: True if everything appears copacetic. | ||
774 | // False if there is any error: the pB->i2eError field has the error | ||
775 | // | ||
776 | // Description: | ||
777 | // | ||
778 | // Returns the word read from the data fifo specified by the board-structure | ||
779 | // pointer pB. Uses a 16-bit operation. Is called indirectly through | ||
780 | // pB->i2eReadWord. | ||
781 | // | ||
782 | //****************************************************************************** | ||
783 | static unsigned short | ||
784 | iiReadWord16(i2eBordStrPtr pB) | ||
785 | { | ||
786 | return inw(pB->i2eData); | ||
787 | } | ||
788 | |||
789 | //****************************************************************************** | ||
790 | // Function: iiReadWord8(pB) | ||
791 | // Parameters: pB - pointer to board structure | ||
792 | // | ||
793 | // Returns: True if everything appears copacetic. | ||
794 | // False if there is any error: the pB->i2eError field has the error | ||
795 | // | ||
796 | // Description: | ||
797 | // | ||
798 | // Returns the word read from the data fifo specified by the board-structure | ||
799 | // pointer pB. Uses two 8-bit operations. Bytes are assumed to be LSB first. Is | ||
800 | // called indirectly through pB->i2eReadWord. | ||
801 | // | ||
802 | //****************************************************************************** | ||
803 | static unsigned short | ||
804 | iiReadWord8(i2eBordStrPtr pB) | ||
805 | { | ||
806 | unsigned short urs; | ||
807 | |||
808 | urs = inb(pB->i2eData); | ||
809 | |||
810 | return (inb(pB->i2eData) << 8) | urs; | ||
811 | } | ||
812 | |||
813 | //****************************************************************************** | ||
814 | // Function: iiWriteWord16(pB, value) | ||
815 | // Parameters: pB - pointer to board structure | ||
816 | // value - data to write | ||
817 | // | ||
818 | // Returns: True if everything appears copacetic. | ||
819 | // False if there is any error: the pB->i2eError field has the error | ||
820 | // | ||
821 | // Description: | ||
822 | // | ||
823 | // Writes the word 'value' to the data fifo specified by the board-structure | ||
824 | // pointer pB. Uses 16-bit operation. Is called indirectly through | ||
825 | // pB->i2eWriteWord. | ||
826 | // | ||
827 | //****************************************************************************** | ||
828 | static void | ||
829 | iiWriteWord16(i2eBordStrPtr pB, unsigned short value) | ||
830 | { | ||
831 | outw((int)value, pB->i2eData); | ||
832 | } | ||
833 | |||
834 | //****************************************************************************** | ||
835 | // Function: iiWriteWord8(pB, value) | ||
836 | // Parameters: pB - pointer to board structure | ||
837 | // value - data to write | ||
838 | // | ||
839 | // Returns: True if everything appears copacetic. | ||
840 | // False if there is any error: the pB->i2eError field has the error | ||
841 | // | ||
842 | // Description: | ||
843 | // | ||
844 | // Writes the word 'value' to the data fifo specified by the board-structure | ||
845 | // pointer pB. Uses two 8-bit operations (writes LSB first). Is called | ||
846 | // indirectly through pB->i2eWriteWord. | ||
847 | // | ||
848 | //****************************************************************************** | ||
849 | static void | ||
850 | iiWriteWord8(i2eBordStrPtr pB, unsigned short value) | ||
851 | { | ||
852 | outb((char)value, pB->i2eData); | ||
853 | outb((char)(value >> 8), pB->i2eData); | ||
854 | } | ||
855 | |||
856 | //****************************************************************************** | ||
857 | // Function: iiWaitForTxEmptyII(pB, mSdelay) | ||
858 | // Parameters: pB - pointer to board structure | ||
859 | // mSdelay - period to wait before returning | ||
860 | // | ||
861 | // Returns: True if the FIFO is empty. | ||
862 | // False if it not empty in the required time: the pB->i2eError | ||
863 | // field has the error. | ||
864 | // | ||
865 | // Description: | ||
866 | // | ||
867 | // Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if | ||
868 | // not empty by the required time, returns false and error in pB->i2eError, | ||
869 | // otherwise returns true. | ||
870 | // | ||
871 | // mSdelay == 0 is taken to mean must be empty on the first test. | ||
872 | // | ||
873 | // This version operates on IntelliPort-II - style FIFO's | ||
874 | // | ||
875 | // Note this routine is organized so that if status is ok there is no delay at | ||
876 | // all called either before or after the test. Is called indirectly through | ||
877 | // pB->i2eWaitForTxEmpty. | ||
878 | // | ||
879 | //****************************************************************************** | ||
880 | static int | ||
881 | iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay) | ||
882 | { | ||
883 | unsigned long flags; | ||
884 | int itemp; | ||
885 | |||
886 | for (;;) | ||
887 | { | ||
888 | // This routine hinges on being able to see the "other" status register | ||
889 | // (as seen by the local processor). His incoming fifo is our outgoing | ||
890 | // FIFO. | ||
891 | // | ||
892 | // By the nature of this routine, you would be using this as part of a | ||
893 | // larger atomic context: i.e., you would use this routine to ensure the | ||
894 | // fifo empty, then act on this information. Between these two halves, | ||
895 | // you will generally not want to service interrupts or in any way | ||
896 | // disrupt the assumptions implicit in the larger context. | ||
897 | // | ||
898 | // Even worse, however, this routine "shifts" the status register to | ||
899 | // point to the local status register which is not the usual situation. | ||
900 | // Therefore for extra safety, we force the critical section to be | ||
901 | // completely atomic, and pick up after ourselves before allowing any | ||
902 | // interrupts of any kind. | ||
903 | |||
904 | |||
905 | write_lock_irqsave(&Dl_spinlock, flags); | ||
906 | outb(SEL_COMMAND, pB->i2ePointer); | ||
907 | outb(SEL_CMD_SH, pB->i2ePointer); | ||
908 | |||
909 | itemp = inb(pB->i2eStatus); | ||
910 | |||
911 | outb(SEL_COMMAND, pB->i2ePointer); | ||
912 | outb(SEL_CMD_UNSH, pB->i2ePointer); | ||
913 | |||
914 | if (itemp & ST_IN_EMPTY) | ||
915 | { | ||
916 | I2_UPDATE_FIFO_ROOM(pB); | ||
917 | write_unlock_irqrestore(&Dl_spinlock, flags); | ||
918 | I2_COMPLETE(pB, I2EE_GOOD); | ||
919 | } | ||
920 | |||
921 | write_unlock_irqrestore(&Dl_spinlock, flags); | ||
922 | |||
923 | if (mSdelay-- == 0) | ||
924 | break; | ||
925 | |||
926 | iiDelay(pB, 1); /* 1 mS granularity on checking condition */ | ||
927 | } | ||
928 | I2_COMPLETE(pB, I2EE_TXE_TIME); | ||
929 | } | ||
930 | |||
931 | //****************************************************************************** | ||
932 | // Function: iiWaitForTxEmptyIIEX(pB, mSdelay) | ||
933 | // Parameters: pB - pointer to board structure | ||
934 | // mSdelay - period to wait before returning | ||
935 | // | ||
936 | // Returns: True if the FIFO is empty. | ||
937 | // False if it not empty in the required time: the pB->i2eError | ||
938 | // field has the error. | ||
939 | // | ||
940 | // Description: | ||
941 | // | ||
942 | // Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if | ||
943 | // not empty by the required time, returns false and error in pB->i2eError, | ||
944 | // otherwise returns true. | ||
945 | // | ||
946 | // mSdelay == 0 is taken to mean must be empty on the first test. | ||
947 | // | ||
948 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
949 | // | ||
950 | // Note this routine is organized so that if status is ok there is no delay at | ||
951 | // all called either before or after the test. Is called indirectly through | ||
952 | // pB->i2eWaitForTxEmpty. | ||
953 | // | ||
954 | //****************************************************************************** | ||
955 | static int | ||
956 | iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay) | ||
957 | { | ||
958 | unsigned long flags; | ||
959 | |||
960 | for (;;) | ||
961 | { | ||
962 | // By the nature of this routine, you would be using this as part of a | ||
963 | // larger atomic context: i.e., you would use this routine to ensure the | ||
964 | // fifo empty, then act on this information. Between these two halves, | ||
965 | // you will generally not want to service interrupts or in any way | ||
966 | // disrupt the assumptions implicit in the larger context. | ||
967 | |||
968 | write_lock_irqsave(&Dl_spinlock, flags); | ||
969 | |||
970 | if (inb(pB->i2eStatus) & STE_OUT_MT) { | ||
971 | I2_UPDATE_FIFO_ROOM(pB); | ||
972 | write_unlock_irqrestore(&Dl_spinlock, flags); | ||
973 | I2_COMPLETE(pB, I2EE_GOOD); | ||
974 | } | ||
975 | write_unlock_irqrestore(&Dl_spinlock, flags); | ||
976 | |||
977 | if (mSdelay-- == 0) | ||
978 | break; | ||
979 | |||
980 | iiDelay(pB, 1); // 1 mS granularity on checking condition | ||
981 | } | ||
982 | I2_COMPLETE(pB, I2EE_TXE_TIME); | ||
983 | } | ||
984 | |||
985 | //****************************************************************************** | ||
986 | // Function: iiTxMailEmptyII(pB) | ||
987 | // Parameters: pB - pointer to board structure | ||
988 | // | ||
989 | // Returns: True if the transmit mailbox is empty. | ||
990 | // False if it not empty. | ||
991 | // | ||
992 | // Description: | ||
993 | // | ||
994 | // Returns true or false according to whether the transmit mailbox is empty (and | ||
995 | // therefore able to accept more mail) | ||
996 | // | ||
997 | // This version operates on IntelliPort-II - style FIFO's | ||
998 | // | ||
999 | //****************************************************************************** | ||
1000 | static int | ||
1001 | iiTxMailEmptyII(i2eBordStrPtr pB) | ||
1002 | { | ||
1003 | int port = pB->i2ePointer; | ||
1004 | outb(SEL_OUTMAIL, port); | ||
1005 | return inb(port) == 0; | ||
1006 | } | ||
1007 | |||
1008 | //****************************************************************************** | ||
1009 | // Function: iiTxMailEmptyIIEX(pB) | ||
1010 | // Parameters: pB - pointer to board structure | ||
1011 | // | ||
1012 | // Returns: True if the transmit mailbox is empty. | ||
1013 | // False if it not empty. | ||
1014 | // | ||
1015 | // Description: | ||
1016 | // | ||
1017 | // Returns true or false according to whether the transmit mailbox is empty (and | ||
1018 | // therefore able to accept more mail) | ||
1019 | // | ||
1020 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1021 | // | ||
1022 | //****************************************************************************** | ||
1023 | static int | ||
1024 | iiTxMailEmptyIIEX(i2eBordStrPtr pB) | ||
1025 | { | ||
1026 | return !(inb(pB->i2eStatus) & STE_OUT_MAIL); | ||
1027 | } | ||
1028 | |||
1029 | //****************************************************************************** | ||
1030 | // Function: iiTrySendMailII(pB,mail) | ||
1031 | // Parameters: pB - pointer to board structure | ||
1032 | // mail - value to write to mailbox | ||
1033 | // | ||
1034 | // Returns: True if the transmit mailbox is empty, and mail is sent. | ||
1035 | // False if it not empty. | ||
1036 | // | ||
1037 | // Description: | ||
1038 | // | ||
1039 | // If outgoing mailbox is empty, sends mail and returns true. If outgoing | ||
1040 | // mailbox is not empty, returns false. | ||
1041 | // | ||
1042 | // This version operates on IntelliPort-II - style FIFO's | ||
1043 | // | ||
1044 | //****************************************************************************** | ||
1045 | static int | ||
1046 | iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail) | ||
1047 | { | ||
1048 | int port = pB->i2ePointer; | ||
1049 | |||
1050 | outb(SEL_OUTMAIL, port); | ||
1051 | if (inb(port) == 0) { | ||
1052 | outb(SEL_OUTMAIL, port); | ||
1053 | outb(mail, port); | ||
1054 | return 1; | ||
1055 | } | ||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | //****************************************************************************** | ||
1060 | // Function: iiTrySendMailIIEX(pB,mail) | ||
1061 | // Parameters: pB - pointer to board structure | ||
1062 | // mail - value to write to mailbox | ||
1063 | // | ||
1064 | // Returns: True if the transmit mailbox is empty, and mail is sent. | ||
1065 | // False if it not empty. | ||
1066 | // | ||
1067 | // Description: | ||
1068 | // | ||
1069 | // If outgoing mailbox is empty, sends mail and returns true. If outgoing | ||
1070 | // mailbox is not empty, returns false. | ||
1071 | // | ||
1072 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1073 | // | ||
1074 | //****************************************************************************** | ||
1075 | static int | ||
1076 | iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail) | ||
1077 | { | ||
1078 | if (inb(pB->i2eStatus) & STE_OUT_MAIL) | ||
1079 | return 0; | ||
1080 | outb(mail, pB->i2eXMail); | ||
1081 | return 1; | ||
1082 | } | ||
1083 | |||
1084 | //****************************************************************************** | ||
1085 | // Function: iiGetMailII(pB,mail) | ||
1086 | // Parameters: pB - pointer to board structure | ||
1087 | // | ||
1088 | // Returns: Mailbox data or NO_MAIL_HERE. | ||
1089 | // | ||
1090 | // Description: | ||
1091 | // | ||
1092 | // If no mail available, returns NO_MAIL_HERE otherwise returns the data from | ||
1093 | // the mailbox, which is guaranteed != NO_MAIL_HERE. | ||
1094 | // | ||
1095 | // This version operates on IntelliPort-II - style FIFO's | ||
1096 | // | ||
1097 | //****************************************************************************** | ||
1098 | static unsigned short | ||
1099 | iiGetMailII(i2eBordStrPtr pB) | ||
1100 | { | ||
1101 | if (I2_HAS_MAIL(pB)) { | ||
1102 | outb(SEL_INMAIL, pB->i2ePointer); | ||
1103 | return inb(pB->i2ePointer); | ||
1104 | } else { | ||
1105 | return NO_MAIL_HERE; | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1109 | //****************************************************************************** | ||
1110 | // Function: iiGetMailIIEX(pB,mail) | ||
1111 | // Parameters: pB - pointer to board structure | ||
1112 | // | ||
1113 | // Returns: Mailbox data or NO_MAIL_HERE. | ||
1114 | // | ||
1115 | // Description: | ||
1116 | // | ||
1117 | // If no mail available, returns NO_MAIL_HERE otherwise returns the data from | ||
1118 | // the mailbox, which is guaranteed != NO_MAIL_HERE. | ||
1119 | // | ||
1120 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1121 | // | ||
1122 | //****************************************************************************** | ||
1123 | static unsigned short | ||
1124 | iiGetMailIIEX(i2eBordStrPtr pB) | ||
1125 | { | ||
1126 | if (I2_HAS_MAIL(pB)) | ||
1127 | return inb(pB->i2eXMail); | ||
1128 | else | ||
1129 | return NO_MAIL_HERE; | ||
1130 | } | ||
1131 | |||
1132 | //****************************************************************************** | ||
1133 | // Function: iiEnableMailIrqII(pB) | ||
1134 | // Parameters: pB - pointer to board structure | ||
1135 | // | ||
1136 | // Returns: Nothing | ||
1137 | // | ||
1138 | // Description: | ||
1139 | // | ||
1140 | // Enables board to interrupt host (only) by writing to host's in-bound mailbox. | ||
1141 | // | ||
1142 | // This version operates on IntelliPort-II - style FIFO's | ||
1143 | // | ||
1144 | //****************************************************************************** | ||
1145 | static void | ||
1146 | iiEnableMailIrqII(i2eBordStrPtr pB) | ||
1147 | { | ||
1148 | outb(SEL_MASK, pB->i2ePointer); | ||
1149 | outb(ST_IN_MAIL, pB->i2ePointer); | ||
1150 | } | ||
1151 | |||
1152 | //****************************************************************************** | ||
1153 | // Function: iiEnableMailIrqIIEX(pB) | ||
1154 | // Parameters: pB - pointer to board structure | ||
1155 | // | ||
1156 | // Returns: Nothing | ||
1157 | // | ||
1158 | // Description: | ||
1159 | // | ||
1160 | // Enables board to interrupt host (only) by writing to host's in-bound mailbox. | ||
1161 | // | ||
1162 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1163 | // | ||
1164 | //****************************************************************************** | ||
1165 | static void | ||
1166 | iiEnableMailIrqIIEX(i2eBordStrPtr pB) | ||
1167 | { | ||
1168 | outb(MX_IN_MAIL, pB->i2eXMask); | ||
1169 | } | ||
1170 | |||
1171 | //****************************************************************************** | ||
1172 | // Function: iiWriteMaskII(pB) | ||
1173 | // Parameters: pB - pointer to board structure | ||
1174 | // | ||
1175 | // Returns: Nothing | ||
1176 | // | ||
1177 | // Description: | ||
1178 | // | ||
1179 | // Writes arbitrary value to the mask register. | ||
1180 | // | ||
1181 | // This version operates on IntelliPort-II - style FIFO's | ||
1182 | // | ||
1183 | //****************************************************************************** | ||
1184 | static void | ||
1185 | iiWriteMaskII(i2eBordStrPtr pB, unsigned char value) | ||
1186 | { | ||
1187 | outb(SEL_MASK, pB->i2ePointer); | ||
1188 | outb(value, pB->i2ePointer); | ||
1189 | } | ||
1190 | |||
1191 | //****************************************************************************** | ||
1192 | // Function: iiWriteMaskIIEX(pB) | ||
1193 | // Parameters: pB - pointer to board structure | ||
1194 | // | ||
1195 | // Returns: Nothing | ||
1196 | // | ||
1197 | // Description: | ||
1198 | // | ||
1199 | // Writes arbitrary value to the mask register. | ||
1200 | // | ||
1201 | // This version operates on IntelliPort-IIEX - style FIFO's | ||
1202 | // | ||
1203 | //****************************************************************************** | ||
1204 | static void | ||
1205 | iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value) | ||
1206 | { | ||
1207 | outb(value, pB->i2eXMask); | ||
1208 | } | ||
1209 | |||
1210 | //****************************************************************************** | ||
1211 | // Function: iiDownloadBlock(pB, pSource, isStandard) | ||
1212 | // Parameters: pB - pointer to board structure | ||
1213 | // pSource - loadware block to download | ||
1214 | // isStandard - True if "standard" loadware, else false. | ||
1215 | // | ||
1216 | // Returns: Success or Failure | ||
1217 | // | ||
1218 | // Description: | ||
1219 | // | ||
1220 | // Downloads a single block (at pSource)to the board referenced by pB. Caller | ||
1221 | // sets isStandard to true/false according to whether the "standard" loadware is | ||
1222 | // what's being loaded. The normal process, then, is to perform an iiInitialize | ||
1223 | // to the board, then perform some number of iiDownloadBlocks using the returned | ||
1224 | // state to determine when download is complete. | ||
1225 | // | ||
1226 | // Possible return values: (see I2ELLIS.H) | ||
1227 | // II_DOWN_BADVALID | ||
1228 | // II_DOWN_BADFILE | ||
1229 | // II_DOWN_CONTINUING | ||
1230 | // II_DOWN_GOOD | ||
1231 | // II_DOWN_BAD | ||
1232 | // II_DOWN_BADSTATE | ||
1233 | // II_DOWN_TIMEOUT | ||
1234 | // | ||
1235 | // Uses the i2eState and i2eToLoad fields (initialized at iiInitialize) to | ||
1236 | // determine whether this is the first block, whether to check for magic | ||
1237 | // numbers, how many blocks there are to go... | ||
1238 | // | ||
1239 | //****************************************************************************** | ||
1240 | static int | ||
1241 | iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard) | ||
1242 | { | ||
1243 | int itemp; | ||
1244 | int loadedFirst; | ||
1245 | |||
1246 | if (pB->i2eValid != I2E_MAGIC) return II_DOWN_BADVALID; | ||
1247 | |||
1248 | switch(pB->i2eState) | ||
1249 | { | ||
1250 | case II_STATE_READY: | ||
1251 | |||
1252 | // Loading the first block after reset. Must check the magic number of the | ||
1253 | // loadfile, store the number of blocks we expect to load. | ||
1254 | if (pSource->e.loadMagic != MAGIC_LOADFILE) | ||
1255 | { | ||
1256 | return II_DOWN_BADFILE; | ||
1257 | } | ||
1258 | |||
1259 | // Next we store the total number of blocks to load, including this one. | ||
1260 | pB->i2eToLoad = 1 + pSource->e.loadBlocksMore; | ||
1261 | |||
1262 | // Set the state, store the version numbers. ('Cause this may have come | ||
1263 | // from a file - we might want to report these versions and revisions in | ||
1264 | // case of an error! | ||
1265 | pB->i2eState = II_STATE_LOADING; | ||
1266 | pB->i2eLVersion = pSource->e.loadVersion; | ||
1267 | pB->i2eLRevision = pSource->e.loadRevision; | ||
1268 | pB->i2eLSub = pSource->e.loadSubRevision; | ||
1269 | |||
1270 | // The time and date of compilation is also available but don't bother | ||
1271 | // storing it for normal purposes. | ||
1272 | loadedFirst = 1; | ||
1273 | break; | ||
1274 | |||
1275 | case II_STATE_LOADING: | ||
1276 | loadedFirst = 0; | ||
1277 | break; | ||
1278 | |||
1279 | default: | ||
1280 | return II_DOWN_BADSTATE; | ||
1281 | } | ||
1282 | |||
1283 | // Now we must be in the II_STATE_LOADING state, and we assume i2eToLoad | ||
1284 | // must be positive still, because otherwise we would have cleaned up last | ||
1285 | // time and set the state to II_STATE_LOADED. | ||
1286 | if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { | ||
1287 | return II_DOWN_TIMEOUT; | ||
1288 | } | ||
1289 | |||
1290 | if (!iiWriteBuf(pB, pSource->c, LOADWARE_BLOCK_SIZE)) { | ||
1291 | return II_DOWN_BADVALID; | ||
1292 | } | ||
1293 | |||
1294 | // If we just loaded the first block, wait for the fifo to empty an extra | ||
1295 | // long time to allow for any special startup code in the firmware, like | ||
1296 | // sending status messages to the LCD's. | ||
1297 | |||
1298 | if (loadedFirst) { | ||
1299 | if (!iiWaitForTxEmpty(pB, MAX_DLOAD_START_TIME)) { | ||
1300 | return II_DOWN_TIMEOUT; | ||
1301 | } | ||
1302 | } | ||
1303 | |||
1304 | // Determine whether this was our last block! | ||
1305 | if (--(pB->i2eToLoad)) { | ||
1306 | return II_DOWN_CONTINUING; // more to come... | ||
1307 | } | ||
1308 | |||
1309 | // It WAS our last block: Clean up operations... | ||
1310 | // ...Wait for last buffer to drain from the board... | ||
1311 | if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) { | ||
1312 | return II_DOWN_TIMEOUT; | ||
1313 | } | ||
1314 | // If there were only a single block written, this would come back | ||
1315 | // immediately and be harmless, though not strictly necessary. | ||
1316 | itemp = MAX_DLOAD_ACK_TIME/10; | ||
1317 | while (--itemp) { | ||
1318 | if (I2_HAS_INPUT(pB)) { | ||
1319 | switch (inb(pB->i2eData)) { | ||
1320 | case LOADWARE_OK: | ||
1321 | pB->i2eState = | ||
1322 | isStandard ? II_STATE_STDLOADED :II_STATE_LOADED; | ||
1323 | |||
1324 | // Some revisions of the bootstrap firmware (e.g. ISA-8 1.0.2) | ||
1325 | // will, // if there is a debug port attached, require some | ||
1326 | // time to send information to the debug port now. It will do | ||
1327 | // this before // executing any of the code we just downloaded. | ||
1328 | // It may take up to 700 milliseconds. | ||
1329 | if (pB->i2ePom.e.porDiag2 & POR_DEBUG_PORT) { | ||
1330 | iiDelay(pB, 700); | ||
1331 | } | ||
1332 | |||
1333 | return II_DOWN_GOOD; | ||
1334 | |||
1335 | case LOADWARE_BAD: | ||
1336 | default: | ||
1337 | return II_DOWN_BAD; | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | iiDelay(pB, 10); // 10 mS granularity on checking condition | ||
1342 | } | ||
1343 | |||
1344 | // Drop-through --> timed out waiting for firmware confirmation | ||
1345 | |||
1346 | pB->i2eState = II_STATE_BADLOAD; | ||
1347 | return II_DOWN_TIMEOUT; | ||
1348 | } | ||
1349 | |||
1350 | //****************************************************************************** | ||
1351 | // Function: iiDownloadAll(pB, pSource, isStandard, size) | ||
1352 | // Parameters: pB - pointer to board structure | ||
1353 | // pSource - loadware block to download | ||
1354 | // isStandard - True if "standard" loadware, else false. | ||
1355 | // size - size of data to download (in bytes) | ||
1356 | // | ||
1357 | // Returns: Success or Failure | ||
1358 | // | ||
1359 | // Description: | ||
1360 | // | ||
1361 | // Given a pointer to a board structure, a pointer to the beginning of some | ||
1362 | // loadware, whether it is considered the "standard loadware", and the size of | ||
1363 | // the array in bytes loads the entire array to the board as loadware. | ||
1364 | // | ||
1365 | // Assumes the board has been freshly reset and the power-up reset message read. | ||
1366 | // (i.e., in II_STATE_READY). Complains if state is bad, or if there seems to be | ||
1367 | // too much or too little data to load, or if iiDownloadBlock complains. | ||
1368 | //****************************************************************************** | ||
1369 | static int | ||
1370 | iiDownloadAll(i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard, int size) | ||
1371 | { | ||
1372 | int status; | ||
1373 | |||
1374 | // We know (from context) board should be ready for the first block of | ||
1375 | // download. Complain if not. | ||
1376 | if (pB->i2eState != II_STATE_READY) return II_DOWN_BADSTATE; | ||
1377 | |||
1378 | while (size > 0) { | ||
1379 | size -= LOADWARE_BLOCK_SIZE; // How much data should there be left to | ||
1380 | // load after the following operation ? | ||
1381 | |||
1382 | // Note we just bump pSource by "one", because its size is actually that | ||
1383 | // of an entire block, same as LOADWARE_BLOCK_SIZE. | ||
1384 | status = iiDownloadBlock(pB, pSource++, isStandard); | ||
1385 | |||
1386 | switch(status) | ||
1387 | { | ||
1388 | case II_DOWN_GOOD: | ||
1389 | return ( (size > 0) ? II_DOWN_OVER : II_DOWN_GOOD); | ||
1390 | |||
1391 | case II_DOWN_CONTINUING: | ||
1392 | break; | ||
1393 | |||
1394 | default: | ||
1395 | return status; | ||
1396 | } | ||
1397 | } | ||
1398 | |||
1399 | // We shouldn't drop out: it means "while" caught us with nothing left to | ||
1400 | // download, yet the previous DownloadBlock did not return complete. Ergo, | ||
1401 | // not enough data to match the size byte in the header. | ||
1402 | return II_DOWN_UNDER; | ||
1403 | } | ||
diff --git a/drivers/char/ip2/i2ellis.h b/drivers/char/ip2/i2ellis.h deleted file mode 100644 index fb6df2456018..000000000000 --- a/drivers/char/ip2/i2ellis.h +++ /dev/null | |||
@@ -1,566 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Mainline code for the device driver | ||
12 | * | ||
13 | *******************************************************************************/ | ||
14 | //------------------------------------------------------------------------------ | ||
15 | // i2ellis.h | ||
16 | // | ||
17 | // IntelliPort-II and IntelliPort-IIEX | ||
18 | // | ||
19 | // Extremely | ||
20 | // Low | ||
21 | // Level | ||
22 | // Interface | ||
23 | // Services | ||
24 | // | ||
25 | // Structure Definitions and declarations for "ELLIS" service routines found in | ||
26 | // i2ellis.c | ||
27 | // | ||
28 | // These routines are based on properties of the IntelliPort-II and -IIEX | ||
29 | // hardware and bootstrap firmware, and are not sensitive to particular | ||
30 | // conventions of any particular loadware. | ||
31 | // | ||
32 | // Unlike i2hw.h, which provides IRONCLAD hardware definitions, the material | ||
33 | // here and in i2ellis.c is intended to provice a useful, but not required, | ||
34 | // layer of insulation from the hardware specifics. | ||
35 | //------------------------------------------------------------------------------ | ||
36 | #ifndef I2ELLIS_H /* To prevent multiple includes */ | ||
37 | #define I2ELLIS_H 1 | ||
38 | //------------------------------------------------ | ||
39 | // Revision History: | ||
40 | // | ||
41 | // 30 September 1991 MAG First Draft Started | ||
42 | // 12 October 1991 ...continued... | ||
43 | // | ||
44 | // 20 December 1996 AKM Linux version | ||
45 | //------------------------------------------------- | ||
46 | |||
47 | //---------------------- | ||
48 | // Mandatory Includes: | ||
49 | //---------------------- | ||
50 | #include "ip2types.h" | ||
51 | #include "i2hw.h" // The hardware definitions | ||
52 | |||
53 | //------------------------------------------ | ||
54 | // STAT_BOXIDS packets | ||
55 | //------------------------------------------ | ||
56 | #define MAX_BOX 4 | ||
57 | |||
58 | typedef struct _bidStat | ||
59 | { | ||
60 | unsigned char bid_value[MAX_BOX]; | ||
61 | } bidStat, *bidStatPtr; | ||
62 | |||
63 | // This packet is sent in response to a CMD_GET_BOXIDS bypass command. For -IIEX | ||
64 | // boards, reports the hardware-specific "asynchronous resource register" on | ||
65 | // each expansion box. Boxes not present report 0xff. For -II boards, the first | ||
66 | // element contains 0x80 for 8-port, 0x40 for 4-port boards. | ||
67 | |||
68 | // Box IDs aka ARR or Async Resource Register (more than you want to know) | ||
69 | // 7 6 5 4 3 2 1 0 | ||
70 | // F F N N L S S S | ||
71 | // ============================= | ||
72 | // F F - Product Family Designator | ||
73 | // =====+++++++++++++++++++++++++++++++ | ||
74 | // 0 0 - Intelliport II EX / ISA-8 | ||
75 | // 1 0 - IntelliServer | ||
76 | // 0 1 - SAC - Port Device (Intelliport III ??? ) | ||
77 | // =====+++++++++++++++++++++++++++++++++++++++ | ||
78 | // N N - Number of Ports | ||
79 | // 0 0 - 8 (eight) | ||
80 | // 0 1 - 4 (four) | ||
81 | // 1 0 - 12 (twelve) | ||
82 | // 1 1 - 16 (sixteen) | ||
83 | // =++++++++++++++++++++++++++++++++++ | ||
84 | // L - LCD Display Module Present | ||
85 | // 0 - No | ||
86 | // 1 - LCD module present | ||
87 | // =========+++++++++++++++++++++++++++++++++++++ | ||
88 | // S S S - Async Signals Supported Designator | ||
89 | // 0 0 0 - 8dss, Mod DCE DB25 Female | ||
90 | // 0 0 1 - 6dss, RJ-45 | ||
91 | // 0 1 0 - RS-232/422 dss, DB25 Female | ||
92 | // 0 1 1 - RS-232/422 dss, separate 232/422 DB25 Female | ||
93 | // 1 0 0 - 6dss, 921.6 I/F with ST654's | ||
94 | // 1 0 1 - RS-423/232 8dss, RJ-45 10Pin | ||
95 | // 1 1 0 - 6dss, Mod DCE DB25 Female | ||
96 | // 1 1 1 - NO BOX PRESENT | ||
97 | |||
98 | #define FF(c) ((c & 0xC0) >> 6) | ||
99 | #define NN(c) ((c & 0x30) >> 4) | ||
100 | #define L(c) ((c & 0x08) >> 3) | ||
101 | #define SSS(c) (c & 0x07) | ||
102 | |||
103 | #define BID_HAS_654(x) (SSS(x) == 0x04) | ||
104 | #define BID_NO_BOX 0xff /* no box */ | ||
105 | #define BID_8PORT 0x80 /* IP2-8 port */ | ||
106 | #define BID_4PORT 0x81 /* IP2-4 port */ | ||
107 | #define BID_EXP_MASK 0x30 /* IP2-EX */ | ||
108 | #define BID_EXP_8PORT 0x00 /* 8, */ | ||
109 | #define BID_EXP_4PORT 0x10 /* 4, */ | ||
110 | #define BID_EXP_UNDEF 0x20 /* UNDEF, */ | ||
111 | #define BID_EXP_16PORT 0x30 /* 16, */ | ||
112 | #define BID_LCD_CTRL 0x08 /* LCD Controller */ | ||
113 | #define BID_LCD_NONE 0x00 /* - no controller present */ | ||
114 | #define BID_LCD_PRES 0x08 /* - controller present */ | ||
115 | #define BID_CON_MASK 0x07 /* - connector pinouts */ | ||
116 | #define BID_CON_DB25 0x00 /* - DB-25 F */ | ||
117 | #define BID_CON_RJ45 0x01 /* - rj45 */ | ||
118 | |||
119 | //------------------------------------------------------------------------------ | ||
120 | // i2eBordStr | ||
121 | // | ||
122 | // This structure contains all the information the ELLIS routines require in | ||
123 | // dealing with a particular board. | ||
124 | //------------------------------------------------------------------------------ | ||
125 | // There are some queues here which are guaranteed to never contain the entry | ||
126 | // for a single channel twice. So they must be slightly larger to allow | ||
127 | // unambiguous full/empty management | ||
128 | // | ||
129 | #define CH_QUEUE_SIZE ABS_MOST_PORTS+2 | ||
130 | |||
131 | typedef struct _i2eBordStr | ||
132 | { | ||
133 | porStr i2ePom; // Structure containing the power-on message. | ||
134 | |||
135 | unsigned short i2ePomSize; | ||
136 | // The number of bytes actually read if | ||
137 | // different from sizeof i2ePom, indicates | ||
138 | // there is an error! | ||
139 | |||
140 | unsigned short i2eStartMail; | ||
141 | // Contains whatever inbound mailbox data | ||
142 | // present at startup. NO_MAIL_HERE indicates | ||
143 | // nothing was present. No special | ||
144 | // significance as of this writing, but may be | ||
145 | // useful for diagnostic reasons. | ||
146 | |||
147 | unsigned short i2eValid; | ||
148 | // Indicates validity of the structure; if | ||
149 | // i2eValid == I2E_MAGIC, then we can trust | ||
150 | // the other fields. Some (especially | ||
151 | // initialization) functions are good about | ||
152 | // checking for validity. Many functions do | ||
153 | // not, it being assumed that the larger | ||
154 | // context assures we are using a valid | ||
155 | // i2eBordStrPtr. | ||
156 | |||
157 | unsigned short i2eError; | ||
158 | // Used for returning an error condition from | ||
159 | // several functions which use i2eBordStrPtr | ||
160 | // as an argument. | ||
161 | |||
162 | // Accelerators to characterize separate features of a board, derived from a | ||
163 | // number of sources. | ||
164 | |||
165 | unsigned short i2eFifoSize; | ||
166 | // Always, the size of the FIFO. For | ||
167 | // IntelliPort-II, always the same, for -IIEX | ||
168 | // taken from the Power-On reset message. | ||
169 | |||
170 | volatile | ||
171 | unsigned short i2eFifoRemains; | ||
172 | // Used during normal operation to indicate a | ||
173 | // lower bound on the amount of data which | ||
174 | // might be in the outbound fifo. | ||
175 | |||
176 | unsigned char i2eFifoStyle; | ||
177 | // Accelerator which tells which style (-II or | ||
178 | // -IIEX) FIFO we are using. | ||
179 | |||
180 | unsigned char i2eDataWidth16; | ||
181 | // Accelerator which tells whether we should | ||
182 | // do 8 or 16-bit data transfers. | ||
183 | |||
184 | unsigned char i2eMaxIrq; | ||
185 | // The highest allowable IRQ, based on the | ||
186 | // slot size. | ||
187 | |||
188 | // Accelerators for various addresses on the board | ||
189 | int i2eBase; // I/O Address of the Board | ||
190 | int i2eData; // From here data transfers happen | ||
191 | int i2eStatus; // From here status reads happen | ||
192 | int i2ePointer; // (IntelliPort-II: pointer/commands) | ||
193 | int i2eXMail; // (IntelliPOrt-IIEX: mailboxes | ||
194 | int i2eXMask; // (IntelliPort-IIEX: mask write | ||
195 | |||
196 | //------------------------------------------------------- | ||
197 | // Information presented in a common format across boards | ||
198 | // For each box, bit map of the channels present. Box closest to | ||
199 | // the host is box 0. LSB is channel 0. IntelliPort-II (non-expandable) | ||
200 | // is taken to be box 0. These are derived from product i.d. registers. | ||
201 | |||
202 | unsigned short i2eChannelMap[ABS_MAX_BOXES]; | ||
203 | |||
204 | // Same as above, except each is derived from firmware attempting to detect | ||
205 | // the uart presence (by reading a valid GFRCR register). If bits are set in | ||
206 | // i2eChannelMap and not in i2eGoodMap, there is a potential problem. | ||
207 | |||
208 | unsigned short i2eGoodMap[ABS_MAX_BOXES]; | ||
209 | |||
210 | // --------------------------- | ||
211 | // For indirect function calls | ||
212 | |||
213 | // Routine to cause an N-millisecond delay: Patched by the ii2Initialize | ||
214 | // function. | ||
215 | |||
216 | void (*i2eDelay)(unsigned int); | ||
217 | |||
218 | // Routine to write N bytes to the board through the FIFO. Returns true if | ||
219 | // all copacetic, otherwise returns false and error is in i2eError field. | ||
220 | // IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER. | ||
221 | |||
222 | int (*i2eWriteBuf)(struct _i2eBordStr *, unsigned char *, int); | ||
223 | |||
224 | // Routine to read N bytes from the board through the FIFO. Returns true if | ||
225 | // copacetic, otherwise returns false and error in i2eError. | ||
226 | // IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER. | ||
227 | |||
228 | int (*i2eReadBuf)(struct _i2eBordStr *, unsigned char *, int); | ||
229 | |||
230 | // Returns a word from FIFO. Will use 2 byte operations if needed. | ||
231 | |||
232 | unsigned short (*i2eReadWord)(struct _i2eBordStr *); | ||
233 | |||
234 | // Writes a word to FIFO. Will use 2 byte operations if needed. | ||
235 | |||
236 | void (*i2eWriteWord)(struct _i2eBordStr *, unsigned short); | ||
237 | |||
238 | // Waits specified time for the Transmit FIFO to go empty. Returns true if | ||
239 | // ok, otherwise returns false and error in i2eError. | ||
240 | |||
241 | int (*i2eWaitForTxEmpty)(struct _i2eBordStr *, int); | ||
242 | |||
243 | // Returns true or false according to whether the outgoing mailbox is empty. | ||
244 | |||
245 | int (*i2eTxMailEmpty)(struct _i2eBordStr *); | ||
246 | |||
247 | // Checks whether outgoing mailbox is empty. If so, sends mail and returns | ||
248 | // true. Otherwise returns false. | ||
249 | |||
250 | int (*i2eTrySendMail)(struct _i2eBordStr *, unsigned char); | ||
251 | |||
252 | // If no mail available, returns NO_MAIL_HERE, else returns the value in the | ||
253 | // mailbox (guaranteed can't be NO_MAIL_HERE). | ||
254 | |||
255 | unsigned short (*i2eGetMail)(struct _i2eBordStr *); | ||
256 | |||
257 | // Enables the board to interrupt the host when it writes to the mailbox. | ||
258 | // Irqs will not occur, however, until the loadware separately enables | ||
259 | // interrupt generation to the host. The standard loadware does this in | ||
260 | // response to a command packet sent by the host. (Also, disables | ||
261 | // any other potential interrupt sources from the board -- other than the | ||
262 | // inbound mailbox). | ||
263 | |||
264 | void (*i2eEnableMailIrq)(struct _i2eBordStr *); | ||
265 | |||
266 | // Writes an arbitrary value to the mask register. | ||
267 | |||
268 | void (*i2eWriteMask)(struct _i2eBordStr *, unsigned char); | ||
269 | |||
270 | |||
271 | // State information | ||
272 | |||
273 | // During downloading, indicates the number of blocks remaining to download | ||
274 | // to the board. | ||
275 | |||
276 | short i2eToLoad; | ||
277 | |||
278 | // State of board (see manifests below) (e.g., whether in reset condition, | ||
279 | // whether standard loadware is installed, etc. | ||
280 | |||
281 | unsigned char i2eState; | ||
282 | |||
283 | // These three fields are only valid when there is loadware running on the | ||
284 | // board. (i2eState == II_STATE_LOADED or i2eState == II_STATE_STDLOADED ) | ||
285 | |||
286 | unsigned char i2eLVersion; // Loadware version | ||
287 | unsigned char i2eLRevision; // Loadware revision | ||
288 | unsigned char i2eLSub; // Loadware subrevision | ||
289 | |||
290 | // Flags which only have meaning in the context of the standard loadware. | ||
291 | // Somewhat violates the layering concept, but there is so little additional | ||
292 | // needed at the board level (while much additional at the channel level), | ||
293 | // that this beats maintaining two different per-board structures. | ||
294 | |||
295 | // Indicates which IRQ the board has been initialized (from software) to use | ||
296 | // For MicroChannel boards, any value different from IRQ_UNDEFINED means | ||
297 | // that the software command has been sent to enable interrupts (or specify | ||
298 | // they are disabled). Special value: IRQ_UNDEFINED indicates that the | ||
299 | // software command to select the interrupt has not yet been sent, therefore | ||
300 | // (since the standard loadware insists that it be sent before any other | ||
301 | // packets are sent) no other packets should be sent yet. | ||
302 | |||
303 | unsigned short i2eUsingIrq; | ||
304 | |||
305 | // This is set when we hit the MB_OUT_STUFFED mailbox, which prevents us | ||
306 | // putting more in the mailbox until an appropriate mailbox message is | ||
307 | // received. | ||
308 | |||
309 | unsigned char i2eWaitingForEmptyFifo; | ||
310 | |||
311 | // Any mailbox bits waiting to be sent to the board are OR'ed in here. | ||
312 | |||
313 | unsigned char i2eOutMailWaiting; | ||
314 | |||
315 | // The head of any incoming packet is read into here, is then examined and | ||
316 | // we dispatch accordingly. | ||
317 | |||
318 | unsigned short i2eLeadoffWord[1]; | ||
319 | |||
320 | // Running counter of interrupts where the mailbox indicated incoming data. | ||
321 | |||
322 | unsigned short i2eFifoInInts; | ||
323 | |||
324 | // Running counter of interrupts where the mailbox indicated outgoing data | ||
325 | // had been stripped. | ||
326 | |||
327 | unsigned short i2eFifoOutInts; | ||
328 | |||
329 | // If not void, gives the address of a routine to call if fatal board error | ||
330 | // is found (only applies to standard l/w). | ||
331 | |||
332 | void (*i2eFatalTrap)(struct _i2eBordStr *); | ||
333 | |||
334 | // Will point to an array of some sort of channel structures (whose format | ||
335 | // is unknown at this level, being a function of what loadware is | ||
336 | // installed and the code configuration (max sizes of buffers, etc.)). | ||
337 | |||
338 | void *i2eChannelPtr; | ||
339 | |||
340 | // Set indicates that the board has gone fatal. | ||
341 | |||
342 | unsigned short i2eFatal; | ||
343 | |||
344 | // The number of elements pointed to by i2eChannelPtr. | ||
345 | |||
346 | unsigned short i2eChannelCnt; | ||
347 | |||
348 | // Ring-buffers of channel structures whose channels have particular needs. | ||
349 | |||
350 | rwlock_t Fbuf_spinlock; | ||
351 | volatile | ||
352 | unsigned short i2Fbuf_strip; // Strip index | ||
353 | volatile | ||
354 | unsigned short i2Fbuf_stuff; // Stuff index | ||
355 | void *i2Fbuf[CH_QUEUE_SIZE]; // An array of channel pointers | ||
356 | // of channels who need to send | ||
357 | // flow control packets. | ||
358 | rwlock_t Dbuf_spinlock; | ||
359 | volatile | ||
360 | unsigned short i2Dbuf_strip; // Strip index | ||
361 | volatile | ||
362 | unsigned short i2Dbuf_stuff; // Stuff index | ||
363 | void *i2Dbuf[CH_QUEUE_SIZE]; // An array of channel pointers | ||
364 | // of channels who need to send | ||
365 | // data or in-line command packets. | ||
366 | rwlock_t Bbuf_spinlock; | ||
367 | volatile | ||
368 | unsigned short i2Bbuf_strip; // Strip index | ||
369 | volatile | ||
370 | unsigned short i2Bbuf_stuff; // Stuff index | ||
371 | void *i2Bbuf[CH_QUEUE_SIZE]; // An array of channel pointers | ||
372 | // of channels who need to send | ||
373 | // bypass command packets. | ||
374 | |||
375 | /* | ||
376 | * A set of flags to indicate that certain events have occurred on at least | ||
377 | * one of the ports on this board. We use this to decide whether to spin | ||
378 | * through the channels looking for breaks, etc. | ||
379 | */ | ||
380 | int got_input; | ||
381 | int status_change; | ||
382 | bidStat channelBtypes; | ||
383 | |||
384 | /* | ||
385 | * Debugging counters, etc. | ||
386 | */ | ||
387 | unsigned long debugFlowQueued; | ||
388 | unsigned long debugInlineQueued; | ||
389 | unsigned long debugDataQueued; | ||
390 | unsigned long debugBypassQueued; | ||
391 | unsigned long debugFlowCount; | ||
392 | unsigned long debugInlineCount; | ||
393 | unsigned long debugBypassCount; | ||
394 | |||
395 | rwlock_t read_fifo_spinlock; | ||
396 | rwlock_t write_fifo_spinlock; | ||
397 | |||
398 | // For queuing interrupt bottom half handlers. /\/\|=mhw=|\/\/ | ||
399 | struct work_struct tqueue_interrupt; | ||
400 | |||
401 | struct timer_list SendPendingTimer; // Used by iiSendPending | ||
402 | unsigned int SendPendingRetry; | ||
403 | } i2eBordStr, *i2eBordStrPtr; | ||
404 | |||
405 | //------------------------------------------------------------------- | ||
406 | // Macro Definitions for the indirect calls defined in the i2eBordStr | ||
407 | //------------------------------------------------------------------- | ||
408 | // | ||
409 | #define iiDelay(a,b) (*(a)->i2eDelay)(b) | ||
410 | #define iiWriteBuf(a,b,c) (*(a)->i2eWriteBuf)(a,b,c) | ||
411 | #define iiReadBuf(a,b,c) (*(a)->i2eReadBuf)(a,b,c) | ||
412 | |||
413 | #define iiWriteWord(a,b) (*(a)->i2eWriteWord)(a,b) | ||
414 | #define iiReadWord(a) (*(a)->i2eReadWord)(a) | ||
415 | |||
416 | #define iiWaitForTxEmpty(a,b) (*(a)->i2eWaitForTxEmpty)(a,b) | ||
417 | |||
418 | #define iiTxMailEmpty(a) (*(a)->i2eTxMailEmpty)(a) | ||
419 | #define iiTrySendMail(a,b) (*(a)->i2eTrySendMail)(a,b) | ||
420 | |||
421 | #define iiGetMail(a) (*(a)->i2eGetMail)(a) | ||
422 | #define iiEnableMailIrq(a) (*(a)->i2eEnableMailIrq)(a) | ||
423 | #define iiDisableMailIrq(a) (*(a)->i2eWriteMask)(a,0) | ||
424 | #define iiWriteMask(a,b) (*(a)->i2eWriteMask)(a,b) | ||
425 | |||
426 | //------------------------------------------- | ||
427 | // Manifests for i2eBordStr: | ||
428 | //------------------------------------------- | ||
429 | |||
430 | typedef void (*delayFunc_t)(unsigned int); | ||
431 | |||
432 | // i2eValid | ||
433 | // | ||
434 | #define I2E_MAGIC 0x4251 // Structure is valid. | ||
435 | #define I2E_INCOMPLETE 0x1122 // Structure failed during init. | ||
436 | |||
437 | |||
438 | // i2eError | ||
439 | // | ||
440 | #define I2EE_GOOD 0 // Operation successful | ||
441 | #define I2EE_BADADDR 1 // Address out of range | ||
442 | #define I2EE_BADSTATE 2 // Attempt to perform a function when the board | ||
443 | // structure was in the incorrect state | ||
444 | #define I2EE_BADMAGIC 3 // Bad magic number from Power On test (i2ePomSize | ||
445 | // reflects what was read | ||
446 | #define I2EE_PORM_SHORT 4 // Power On message too short | ||
447 | #define I2EE_PORM_LONG 5 // Power On message too long | ||
448 | #define I2EE_BAD_FAMILY 6 // Un-supported board family type | ||
449 | #define I2EE_INCONSIST 7 // Firmware reports something impossible, | ||
450 | // e.g. unexpected number of ports... Almost no | ||
451 | // excuse other than bad FIFO... | ||
452 | #define I2EE_POSTERR 8 // Power-On self test reported a bad error | ||
453 | #define I2EE_BADBUS 9 // Unknown Bus type declared in message | ||
454 | #define I2EE_TXE_TIME 10 // Timed out waiting for TX Fifo to empty | ||
455 | #define I2EE_INVALID 11 // i2eValid field does not indicate a valid and | ||
456 | // complete board structure (for functions which | ||
457 | // require this be so.) | ||
458 | #define I2EE_BAD_PORT 12 // Discrepancy between channels actually found and | ||
459 | // what the product is supposed to have. Check | ||
460 | // i2eGoodMap vs i2eChannelMap for details. | ||
461 | #define I2EE_BAD_IRQ 13 // Someone specified an unsupported IRQ | ||
462 | #define I2EE_NOCHANNELS 14 // No channel structures have been defined (for | ||
463 | // functions requiring this). | ||
464 | |||
465 | // i2eFifoStyle | ||
466 | // | ||
467 | #define FIFO_II 0 /* IntelliPort-II style: see also i2hw.h */ | ||
468 | #define FIFO_IIEX 1 /* IntelliPort-IIEX style */ | ||
469 | |||
470 | // i2eGetMail | ||
471 | // | ||
472 | #define NO_MAIL_HERE 0x1111 // Since mail is unsigned char, cannot possibly | ||
473 | // promote to 0x1111. | ||
474 | // i2eState | ||
475 | // | ||
476 | #define II_STATE_COLD 0 // Addresses have been defined, but board not even | ||
477 | // reset yet. | ||
478 | #define II_STATE_RESET 1 // Board,if it exists, has just been reset | ||
479 | #define II_STATE_READY 2 // Board ready for its first block | ||
480 | #define II_STATE_LOADING 3 // Board continuing load | ||
481 | #define II_STATE_LOADED 4 // Board has finished load: status ok | ||
482 | #define II_STATE_BADLOAD 5 // Board has finished load: failed! | ||
483 | #define II_STATE_STDLOADED 6 // Board has finished load: standard firmware | ||
484 | |||
485 | // i2eUsingIrq | ||
486 | // | ||
487 | #define I2_IRQ_UNDEFINED 0x1352 /* No valid irq (or polling = 0) can | ||
488 | * ever promote to this! */ | ||
489 | //------------------------------------------ | ||
490 | // Handy Macros for i2ellis.c and others | ||
491 | // Note these are common to -II and -IIEX | ||
492 | //------------------------------------------ | ||
493 | |||
494 | // Given a pointer to the board structure, does the input FIFO have any data or | ||
495 | // not? | ||
496 | // | ||
497 | #define I2_HAS_INPUT(pB) !(inb(pB->i2eStatus) & ST_IN_EMPTY) | ||
498 | |||
499 | // Given a pointer to the board structure, is there anything in the incoming | ||
500 | // mailbox? | ||
501 | // | ||
502 | #define I2_HAS_MAIL(pB) (inb(pB->i2eStatus) & ST_IN_MAIL) | ||
503 | |||
504 | #define I2_UPDATE_FIFO_ROOM(pB) ((pB)->i2eFifoRemains = (pB)->i2eFifoSize) | ||
505 | |||
506 | //------------------------------------------ | ||
507 | // Function Declarations for i2ellis.c | ||
508 | //------------------------------------------ | ||
509 | // | ||
510 | // Functions called directly | ||
511 | // | ||
512 | // Initialization of a board & structure is in four (five!) parts: | ||
513 | // | ||
514 | // 1) iiSetAddress() - Define the board address & delay function for a board. | ||
515 | // 2) iiReset() - Reset the board (provided it exists) | ||
516 | // -- Note you may do this to several boards -- | ||
517 | // 3) iiResetDelay() - Delay for 2 seconds (once for all boards) | ||
518 | // 4) iiInitialize() - Attempt to read Power-up message; further initialize | ||
519 | // accelerators | ||
520 | // | ||
521 | // Then you may use iiDownloadAll() or iiDownloadFile() (in i2file.c) to write | ||
522 | // loadware. To change loadware, you must begin again with step 2, resetting | ||
523 | // the board again (step 1 not needed). | ||
524 | |||
525 | static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t ); | ||
526 | static int iiReset(i2eBordStrPtr); | ||
527 | static int iiResetDelay(i2eBordStrPtr); | ||
528 | static int iiInitialize(i2eBordStrPtr); | ||
529 | |||
530 | // Routine to validate that all channels expected are there. | ||
531 | // | ||
532 | extern int iiValidateChannels(i2eBordStrPtr); | ||
533 | |||
534 | // Routine used to download a block of loadware. | ||
535 | // | ||
536 | static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int); | ||
537 | |||
538 | // Return values given by iiDownloadBlock, iiDownloadAll, iiDownloadFile: | ||
539 | // | ||
540 | #define II_DOWN_BADVALID 0 // board structure is invalid | ||
541 | #define II_DOWN_CONTINUING 1 // So far, so good, firmware expects more | ||
542 | #define II_DOWN_GOOD 2 // Download complete, CRC good | ||
543 | #define II_DOWN_BAD 3 // Download complete, but CRC bad | ||
544 | #define II_DOWN_BADFILE 4 // Bad magic number in loadware file | ||
545 | #define II_DOWN_BADSTATE 5 // Board is in an inappropriate state for | ||
546 | // downloading loadware. (see i2eState) | ||
547 | #define II_DOWN_TIMEOUT 6 // Timeout waiting for firmware | ||
548 | #define II_DOWN_OVER 7 // Too much data | ||
549 | #define II_DOWN_UNDER 8 // Not enough data | ||
550 | #define II_DOWN_NOFILE 9 // Loadware file not found | ||
551 | |||
552 | // Routine to download an entire loadware module: Return values are a subset of | ||
553 | // iiDownloadBlock's, excluding, of course, II_DOWN_CONTINUING | ||
554 | // | ||
555 | static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int); | ||
556 | |||
557 | // Many functions defined here return True if good, False otherwise, with an | ||
558 | // error code in i2eError field. Here is a handy macro for setting the error | ||
559 | // code and returning. | ||
560 | // | ||
561 | #define I2_COMPLETE(pB,code) do { \ | ||
562 | pB->i2eError = code; \ | ||
563 | return (code == I2EE_GOOD);\ | ||
564 | } while (0) | ||
565 | |||
566 | #endif // I2ELLIS_H | ||
diff --git a/drivers/char/ip2/i2hw.h b/drivers/char/ip2/i2hw.h deleted file mode 100644 index c0ba6c05f0cd..000000000000 --- a/drivers/char/ip2/i2hw.h +++ /dev/null | |||
@@ -1,652 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Definitions limited to properties of the hardware or the | ||
12 | * bootstrap firmware. As such, they are applicable regardless of | ||
13 | * operating system or loadware (standard or diagnostic). | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | #ifndef I2HW_H | ||
17 | #define I2HW_H 1 | ||
18 | //------------------------------------------------------------------------------ | ||
19 | // Revision History: | ||
20 | // | ||
21 | // 23 September 1991 MAG First Draft Started...through... | ||
22 | // 11 October 1991 ... Continuing development... | ||
23 | // 6 August 1993 Added support for ISA-4 (asic) which is architected | ||
24 | // as an ISA-CEX with a single 4-port box. | ||
25 | // | ||
26 | // 20 December 1996 AKM Version for Linux | ||
27 | // | ||
28 | //------------------------------------------------------------------------------ | ||
29 | /*------------------------------------------------------------------------------ | ||
30 | |||
31 | HARDWARE DESCRIPTION: | ||
32 | |||
33 | Introduction: | ||
34 | |||
35 | The IntelliPort-II and IntelliPort-IIEX products occupy a block of eight (8) | ||
36 | addresses in the host's I/O space. | ||
37 | |||
38 | Some addresses are used to transfer data to/from the board, some to transfer | ||
39 | so-called "mailbox" messages, and some to read bit-mapped status information. | ||
40 | While all the products in the line are functionally similar, some use a 16-bit | ||
41 | data path to transfer data while others use an 8-bit path. Also, the use of | ||
42 | command /status/mailbox registers differs slightly between the II and IIEX | ||
43 | branches of the family. | ||
44 | |||
45 | The host determines what type of board it is dealing with by reading a string of | ||
46 | sixteen characters from the board. These characters are always placed in the | ||
47 | fifo by the board's local processor whenever the board is reset (either from | ||
48 | power-on or under software control) and are known as the "Power-on Reset | ||
49 | Message." In order that this message can be read from either type of board, the | ||
50 | hardware registers used in reading this message are the same. Once this message | ||
51 | has been read by the host, then it has the information required to operate. | ||
52 | |||
53 | General Differences between boards: | ||
54 | |||
55 | The greatest structural difference is between the -II and -IIEX families of | ||
56 | product. The -II boards use the Am4701 dual 512x8 bidirectional fifo to support | ||
57 | the data path, mailbox registers, and status registers. This chip contains some | ||
58 | features which are not used in the IntelliPort-II products; a description of | ||
59 | these is omitted here. Because of these many features, it contains many | ||
60 | registers, too many to access directly within a small address space. They are | ||
61 | accessed by first writing a value to a "pointer" register. This value selects | ||
62 | the register to be accessed. The next read or write to that address accesses | ||
63 | the selected register rather than the pointer register. | ||
64 | |||
65 | The -IIEX boards use a proprietary design similar to the Am4701 in function. But | ||
66 | because of a simpler, more streamlined design it doesn't require so many | ||
67 | registers. This means they can be accessed directly in single operations rather | ||
68 | than through a pointer register. | ||
69 | |||
70 | Besides these differences, there are differences in whether 8-bit or 16-bit | ||
71 | transfers are used to move data to the board. | ||
72 | |||
73 | The -II boards are capable only of 8-bit data transfers, while the -IIEX boards | ||
74 | may be configured for either 8-bit or 16-bit data transfers. If the on-board DIP | ||
75 | switch #8 is ON, and the card has been installed in a 16-bit slot, 16-bit | ||
76 | transfers are supported (and will be expected by the standard loadware). The | ||
77 | on-board firmware can determine the position of the switch, and whether the | ||
78 | board is installed in a 16-bit slot; it supplies this information to the host as | ||
79 | part of the power-up reset message. | ||
80 | |||
81 | The configuration switch (#8) and slot selection do not directly configure the | ||
82 | hardware. It is up to the on-board loadware and host-based drivers to act | ||
83 | according to the selected options. That is, loadware and drivers could be | ||
84 | written to perform 8-bit transfers regardless of the state of the DIP switch or | ||
85 | slot (and in a diagnostic environment might well do so). Likewise, 16-bit | ||
86 | transfers could be performed as long as the card is in a 16-bit slot. | ||
87 | |||
88 | Note the slot selection and DIP switch selection are provided separately: a | ||
89 | board running in 8-bit mode in a 16-bit slot has a greater range of possible | ||
90 | interrupts to choose from; information of potential use to the host. | ||
91 | |||
92 | All 8-bit data transfers are done in the same way, regardless of whether on a | ||
93 | -II board or a -IIEX board. | ||
94 | |||
95 | The host must consider two things then: 1) whether a -II or -IIEX product is | ||
96 | being used, and 2) whether an 8-bit or 16-bit data path is used. | ||
97 | |||
98 | A further difference is that -II boards always have a 512-byte fifo operating in | ||
99 | each direction. -IIEX boards may use fifos of varying size; this size is | ||
100 | reported as part of the power-up message. | ||
101 | |||
102 | I/O Map Of IntelliPort-II and IntelliPort-IIEX boards: | ||
103 | (Relative to the chosen base address) | ||
104 | |||
105 | Addr R/W IntelliPort-II IntelliPort-IIEX | ||
106 | ---- --- -------------- ---------------- | ||
107 | 0 R/W Data Port (byte) Data Port (byte or word) | ||
108 | 1 R/W (Not used) (MSB of word-wide data written to Data Port) | ||
109 | 2 R Status Register Status Register | ||
110 | 2 W Pointer Register Interrupt Mask Register | ||
111 | 3 R/W (Not used) Mailbox Registers (6 bits: 11111100) | ||
112 | 4,5 -- Reserved for future products | ||
113 | 6 -- Reserved for future products | ||
114 | 7 R Guaranteed to have no effect | ||
115 | 7 W Hardware reset of board. | ||
116 | |||
117 | |||
118 | Rules: | ||
119 | All data transfers are performed using the even i/o address. If byte-wide data | ||
120 | transfers are being used, do INB/OUTB operations on the data port. If word-wide | ||
121 | transfers are used, do INW/OUTW operations. In some circumstances (such as | ||
122 | reading the power-up message) you will do INB from the data port, but in this | ||
123 | case the MSB of each word read is lost. When accessing all other unreserved | ||
124 | registers, use byte operations only. | ||
125 | ------------------------------------------------------------------------------*/ | ||
126 | |||
127 | //------------------------------------------------ | ||
128 | // Mandatory Includes: | ||
129 | //------------------------------------------------ | ||
130 | // | ||
131 | #include "ip2types.h" | ||
132 | |||
133 | //------------------------------------------------------------------------- | ||
134 | // Manifests for the I/O map: | ||
135 | //------------------------------------------------------------------------- | ||
136 | // R/W: Data port (byte) for IntelliPort-II, | ||
137 | // R/W: Data port (byte or word) for IntelliPort-IIEX | ||
138 | // Incoming or outgoing data passes through a FIFO, the status of which is | ||
139 | // available in some of the bits in FIFO_STATUS. This (bidirectional) FIFO is | ||
140 | // the primary means of transferring data, commands, flow-control, and status | ||
141 | // information between the host and board. | ||
142 | // | ||
143 | #define FIFO_DATA 0 | ||
144 | |||
145 | // Another way of passing information between the board and the host is | ||
146 | // through "mailboxes". Unlike a FIFO, a mailbox holds only a single byte of | ||
147 | // data. Writing data to the mailbox causes a status bit to be set, and | ||
148 | // potentially interrupting the intended receiver. The sender has some way to | ||
149 | // determine whether the data has been read yet; as soon as it has, it may send | ||
150 | // more. The mailboxes are handled differently on -II and -IIEX products, as | ||
151 | // suggested below. | ||
152 | //------------------------------------------------------------------------------ | ||
153 | // Read: Status Register for IntelliPort-II or -IIEX | ||
154 | // The presence of any bit set here will cause an interrupt to the host, | ||
155 | // provided the corresponding bit has been unmasked in the interrupt mask | ||
156 | // register. Furthermore, interrupts to the host are disabled globally until the | ||
157 | // loadware selects the irq line to use. With the exception of STN_MR, the bits | ||
158 | // remain set so long as the associated condition is true. | ||
159 | // | ||
160 | #define FIFO_STATUS 2 | ||
161 | |||
162 | // Bit map of status bits which are identical for -II and -IIEX | ||
163 | // | ||
164 | #define ST_OUT_FULL 0x40 // Outbound FIFO full | ||
165 | #define ST_IN_EMPTY 0x20 // Inbound FIFO empty | ||
166 | #define ST_IN_MAIL 0x04 // Inbound Mailbox full | ||
167 | |||
168 | // The following exists only on the Intelliport-IIEX, and indicates that the | ||
169 | // board has not read the last outgoing mailbox data yet. In the IntelliPort-II, | ||
170 | // the outgoing mailbox may be read back: a zero indicates the board has read | ||
171 | // the data. | ||
172 | // | ||
173 | #define STE_OUT_MAIL 0x80 // Outbound mailbox full (!) | ||
174 | |||
175 | // The following bits are defined differently for -II and -IIEX boards. Code | ||
176 | // which relies on these bits will need to be functionally different for the two | ||
177 | // types of boards and should be generally avoided because of the additional | ||
178 | // complexity this creates: | ||
179 | |||
180 | // Bit map of status bits only on -II | ||
181 | |||
182 | // Fifo has been RESET (cleared when the status register is read). Note that | ||
183 | // this condition cannot be masked and would always interrupt the host, except | ||
184 | // that the hardware reset also disables interrupts globally from the board | ||
185 | // until re-enabled by loadware. This could also arise from the | ||
186 | // Am4701-supported command to reset the chip, but this command is generally not | ||
187 | // used here. | ||
188 | // | ||
189 | #define STN_MR 0x80 | ||
190 | |||
191 | // See the AMD Am4701 data sheet for details on the following four bits. They | ||
192 | // are not presently used by Computone drivers. | ||
193 | // | ||
194 | #define STN_OUT_AF 0x10 // Outbound FIFO almost full (programmable) | ||
195 | #define STN_IN_AE 0x08 // Inbound FIFO almost empty (programmable) | ||
196 | #define STN_BD 0x02 // Inbound byte detected | ||
197 | #define STN_PE 0x01 // Parity/Framing condition detected | ||
198 | |||
199 | // Bit-map of status bits only on -IIEX | ||
200 | // | ||
201 | #define STE_OUT_HF 0x10 // Outbound FIFO half full | ||
202 | #define STE_IN_HF 0x08 // Inbound FIFO half full | ||
203 | #define STE_IN_FULL 0x02 // Inbound FIFO full | ||
204 | #define STE_OUT_MT 0x01 // Outbound FIFO empty | ||
205 | |||
206 | //------------------------------------------------------------------------------ | ||
207 | |||
208 | // Intelliport-II -- Write Only: the pointer register. | ||
209 | // Values are written to this register to select the Am4701 internal register to | ||
210 | // be accessed on the next operation. | ||
211 | // | ||
212 | #define FIFO_PTR 0x02 | ||
213 | |||
214 | // Values for the pointer register | ||
215 | // | ||
216 | #define SEL_COMMAND 0x1 // Selects the Am4701 command register | ||
217 | |||
218 | // Some possible commands: | ||
219 | // | ||
220 | #define SEL_CMD_MR 0x80 // Am4701 command to reset the chip | ||
221 | #define SEL_CMD_SH 0x40 // Am4701 command to map the "other" port into the | ||
222 | // status register. | ||
223 | #define SEL_CMD_UNSH 0 // Am4701 command to "unshift": port maps into its | ||
224 | // own status register. | ||
225 | #define SEL_MASK 0x2 // Selects the Am4701 interrupt mask register. The | ||
226 | // interrupt mask register is bit-mapped to match | ||
227 | // the status register (FIFO_STATUS) except for | ||
228 | // STN_MR. (See above.) | ||
229 | #define SEL_BYTE_DET 0x3 // Selects the Am4701 byte-detect register. (Not | ||
230 | // normally used except in diagnostics.) | ||
231 | #define SEL_OUTMAIL 0x4 // Selects the outbound mailbox (R/W). Reading back | ||
232 | // a value of zero indicates that the mailbox has | ||
233 | // been read by the board and is available for more | ||
234 | // data./ Writing to the mailbox optionally | ||
235 | // interrupts the board, depending on the loadware's | ||
236 | // setting of its interrupt mask register. | ||
237 | #define SEL_AEAF 0x5 // Selects AE/AF threshold register. | ||
238 | #define SEL_INMAIL 0x6 // Selects the inbound mailbox (Read) | ||
239 | |||
240 | //------------------------------------------------------------------------------ | ||
241 | // IntelliPort-IIEX -- Write Only: interrupt mask (and misc flags) register: | ||
242 | // Unlike IntelliPort-II, bit assignments do NOT match those of the status | ||
243 | // register. | ||
244 | // | ||
245 | #define FIFO_MASK 0x2 | ||
246 | |||
247 | // Mailbox readback select: | ||
248 | // If set, reads to FIFO_MAIL will read the OUTBOUND mailbox (host to board). If | ||
249 | // clear (default on reset) reads to FIFO_MAIL will read the INBOUND mailbox. | ||
250 | // This is the normal situation. The clearing of a mailbox is determined on | ||
251 | // -IIEX boards by waiting for the STE_OUT_MAIL bit to clear. Readback | ||
252 | // capability is provided for diagnostic purposes only. | ||
253 | // | ||
254 | #define MX_OUTMAIL_RSEL 0x80 | ||
255 | |||
256 | #define MX_IN_MAIL 0x40 // Enables interrupts when incoming mailbox goes | ||
257 | // full (ST_IN_MAIL set). | ||
258 | #define MX_IN_FULL 0x20 // Enables interrupts when incoming FIFO goes full | ||
259 | // (STE_IN_FULL). | ||
260 | #define MX_IN_MT 0x08 // Enables interrupts when incoming FIFO goes empty | ||
261 | // (ST_IN_MT). | ||
262 | #define MX_OUT_FULL 0x04 // Enables interrupts when outgoing FIFO goes full | ||
263 | // (ST_OUT_FULL). | ||
264 | #define MX_OUT_MT 0x01 // Enables interrupts when outgoing FIFO goes empty | ||
265 | // (STE_OUT_MT). | ||
266 | |||
267 | // Any remaining bits are reserved, and should be written to ZERO for | ||
268 | // compatibility with future Computone products. | ||
269 | |||
270 | //------------------------------------------------------------------------------ | ||
271 | // IntelliPort-IIEX: -- These are only 6-bit mailboxes !!! -- 11111100 (low two | ||
272 | // bits always read back 0). | ||
273 | // Read: One of the mailboxes, usually Inbound. | ||
274 | // Inbound Mailbox (MX_OUTMAIL_RSEL = 0) | ||
275 | // Outbound Mailbox (MX_OUTMAIL_RSEL = 1) | ||
276 | // Write: Outbound Mailbox | ||
277 | // For the IntelliPort-II boards, the outbound mailbox is read back to determine | ||
278 | // whether the board has read the data (0 --> data has been read). For the | ||
279 | // IntelliPort-IIEX, this is done by reading a status register. To determine | ||
280 | // whether mailbox is available for more outbound data, use the STE_OUT_MAIL bit | ||
281 | // in FIFO_STATUS. Moreover, although the Outbound Mailbox can be read back by | ||
282 | // setting MX_OUTMAIL_RSEL, it is NOT cleared when the board reads it, as is the | ||
283 | // case with the -II boards. For this reason, FIFO_MAIL is normally used to read | ||
284 | // the inbound FIFO, and MX_OUTMAIL_RSEL kept clear. (See above for | ||
285 | // MX_OUTMAIL_RSEL description.) | ||
286 | // | ||
287 | #define FIFO_MAIL 0x3 | ||
288 | |||
289 | //------------------------------------------------------------------------------ | ||
290 | // WRITE ONLY: Resets the board. (Data doesn't matter). | ||
291 | // | ||
292 | #define FIFO_RESET 0x7 | ||
293 | |||
294 | //------------------------------------------------------------------------------ | ||
295 | // READ ONLY: Will have no effect. (Data is undefined.) | ||
296 | // Actually, there will be an effect, in that the operation is sure to generate | ||
297 | // a bus cycle: viz., an I/O byte Read. This fact can be used to enforce short | ||
298 | // delays when no comparable time constant is available. | ||
299 | // | ||
300 | #define FIFO_NOP 0x7 | ||
301 | |||
302 | //------------------------------------------------------------------------------ | ||
303 | // RESET & POWER-ON RESET MESSAGE | ||
304 | /*------------------------------------------------------------------------------ | ||
305 | RESET: | ||
306 | |||
307 | The IntelliPort-II and -IIEX boards are reset in three ways: Power-up, channel | ||
308 | reset, and via a write to the reset register described above. For products using | ||
309 | the ISA bus, these three sources of reset are equvalent. For MCA and EISA buses, | ||
310 | the Power-up and channel reset sources cause additional hardware initialization | ||
311 | which should only occur at system startup time. | ||
312 | |||
313 | The third type of reset, called a "command reset", is done by writing any data | ||
314 | to the FIFO_RESET address described above. This resets the on-board processor, | ||
315 | FIFO, UARTS, and associated hardware. | ||
316 | |||
317 | This passes control of the board to the bootstrap firmware, which performs a | ||
318 | Power-On Self Test and which detects its current configuration. For example, | ||
319 | -IIEX products determine the size of FIFO which has been installed, and the | ||
320 | number and type of expansion boxes attached. | ||
321 | |||
322 | This and other information is then written to the FIFO in a 16-byte data block | ||
323 | to be read by the host. This block is guaranteed to be present within two (2) | ||
324 | seconds of having received the command reset. The firmware is now ready to | ||
325 | receive loadware from the host. | ||
326 | |||
327 | It is good practice to perform a command reset to the board explicitly as part | ||
328 | of your software initialization. This allows your code to properly restart from | ||
329 | a soft boot. (Many systems do not issue channel reset on soft boot). | ||
330 | |||
331 | Because of a hardware reset problem on some of the Cirrus Logic 1400's which are | ||
332 | used on the product, it is recommended that you reset the board twice, separated | ||
333 | by an approximately 50 milliseconds delay. (VERY approximately: probably ok to | ||
334 | be off by a factor of five. The important point is that the first command reset | ||
335 | in fact generates a reset pulse on the board. This pulse is guaranteed to last | ||
336 | less than 10 milliseconds. The additional delay ensures the 1400 has had the | ||
337 | chance to respond sufficiently to the first reset. Why not a longer delay? Much | ||
338 | more than 50 milliseconds gets to be noticable, but the board would still work. | ||
339 | |||
340 | Once all 16 bytes of the Power-on Reset Message have been read, the bootstrap | ||
341 | firmware is ready to receive loadware. | ||
342 | |||
343 | Note on Power-on Reset Message format: | ||
344 | The various fields have been designed with future expansion in view. | ||
345 | Combinations of bitfields and values have been defined which define products | ||
346 | which may not currently exist. This has been done to allow drivers to anticipate | ||
347 | the possible introduction of products in a systematic fashion. This is not | ||
348 | intended to suggest that each potential product is actually under consideration. | ||
349 | ------------------------------------------------------------------------------*/ | ||
350 | |||
351 | //---------------------------------------- | ||
352 | // Format of Power-on Reset Message | ||
353 | //---------------------------------------- | ||
354 | |||
355 | typedef union _porStr // "por" stands for Power On Reset | ||
356 | { | ||
357 | unsigned char c[16]; // array used when considering the message as a | ||
358 | // string of undifferentiated characters | ||
359 | |||
360 | struct // Elements used when considering values | ||
361 | { | ||
362 | // The first two bytes out of the FIFO are two magic numbers. These are | ||
363 | // intended to establish that there is indeed a member of the | ||
364 | // IntelliPort-II(EX) family present. The remaining bytes may be | ||
365 | // expected // to be valid. When reading the Power-on Reset message, | ||
366 | // if the magic numbers do not match it is probably best to stop | ||
367 | // reading immediately. You are certainly not reading our board (unless | ||
368 | // hardware is faulty), and may in fact be reading some other piece of | ||
369 | // hardware. | ||
370 | |||
371 | unsigned char porMagic1; // magic number: first byte == POR_MAGIC_1 | ||
372 | unsigned char porMagic2; // magic number: second byte == POR_MAGIC_2 | ||
373 | |||
374 | // The Version, Revision, and Subrevision are stored as absolute numbers | ||
375 | // and would normally be displayed in the format V.R.S (e.g. 1.0.2) | ||
376 | |||
377 | unsigned char porVersion; // Bootstrap firmware version number | ||
378 | unsigned char porRevision; // Bootstrap firmware revision number | ||
379 | unsigned char porSubRev; // Bootstrap firmware sub-revision number | ||
380 | |||
381 | unsigned char porID; // Product ID: Bit-mapped according to | ||
382 | // conventions described below. Among other | ||
383 | // things, this allows us to distinguish | ||
384 | // IntelliPort-II boards from IntelliPort-IIEX | ||
385 | // boards. | ||
386 | |||
387 | unsigned char porBus; // IntelliPort-II: Unused | ||
388 | // IntelliPort-IIEX: Bus Information: | ||
389 | // Bit-mapped below | ||
390 | |||
391 | unsigned char porMemory; // On-board DRAM size: in 32k blocks | ||
392 | |||
393 | // porPorts1 (and porPorts2) are used to determine the ports which are | ||
394 | // available to the board. For non-expandable product, a single number | ||
395 | // is sufficient. For expandable product, the board may be connected | ||
396 | // to as many as four boxes. Each box may be (so far) either a 16-port | ||
397 | // or an 8-port size. Whenever an 8-port box is used, the remaining 8 | ||
398 | // ports leave gaps between existing channels. For that reason, | ||
399 | // expandable products must report a MAP of available channels. Since | ||
400 | // each UART supports four ports, we represent each UART found by a | ||
401 | // single bit. Using two bytes to supply the mapping information we | ||
402 | // report the presense or absense of up to 16 UARTS, or 64 ports in | ||
403 | // steps of 4 ports. For -IIEX products, the ports are numbered | ||
404 | // starting at the box closest to the controller in the "chain". | ||
405 | |||
406 | // Interpreted Differently for IntelliPort-II and -IIEX. | ||
407 | // -II: Number of ports (Derived actually from product ID). See | ||
408 | // Diag1&2 to indicate if uart was actually detected. | ||
409 | // -IIEX: Bit-map of UARTS found, LSB (see below for MSB of this). This | ||
410 | // bitmap is based on detecting the uarts themselves; | ||
411 | // see porFlags for information from the box i.d's. | ||
412 | unsigned char porPorts1; | ||
413 | |||
414 | unsigned char porDiag1; // Results of on-board P.O.S.T, 1st byte | ||
415 | unsigned char porDiag2; // Results of on-board P.O.S.T, 2nd byte | ||
416 | unsigned char porSpeed; // Speed of local CPU: given as MHz x10 | ||
417 | // e.g., 16.0 MHz CPU is reported as 160 | ||
418 | unsigned char porFlags; // Misc information (see manifests below) | ||
419 | // Bit-mapped: CPU type, UART's present | ||
420 | |||
421 | unsigned char porPorts2; // -II: Undefined | ||
422 | // -IIEX: Bit-map of UARTS found, MSB (see | ||
423 | // above for LSB) | ||
424 | |||
425 | // IntelliPort-II: undefined | ||
426 | // IntelliPort-IIEX: 1 << porFifoSize gives the size, in bytes, of the | ||
427 | // host interface FIFO, in each direction. When running the -IIEX in | ||
428 | // 8-bit mode, fifo capacity is halved. The bootstrap firmware will | ||
429 | // have already accounted for this fact in generating this number. | ||
430 | unsigned char porFifoSize; | ||
431 | |||
432 | // IntelliPort-II: undefined | ||
433 | // IntelliPort-IIEX: The number of boxes connected. (Presently 1-4) | ||
434 | unsigned char porNumBoxes; | ||
435 | } e; | ||
436 | } porStr, *porStrPtr; | ||
437 | |||
438 | //-------------------------- | ||
439 | // Values for porStr fields | ||
440 | //-------------------------- | ||
441 | |||
442 | //--------------------- | ||
443 | // porMagic1, porMagic2 | ||
444 | //---------------------- | ||
445 | // | ||
446 | #define POR_MAGIC_1 0x96 // The only valid value for porMagic1 | ||
447 | #define POR_MAGIC_2 0x35 // The only valid value for porMagic2 | ||
448 | #define POR_1_INDEX 0 // Byte position of POR_MAGIC_1 | ||
449 | #define POR_2_INDEX 1 // Ditto for POR_MAGIC_2 | ||
450 | |||
451 | //---------------------- | ||
452 | // porID | ||
453 | //---------------------- | ||
454 | // | ||
455 | #define POR_ID_FAMILY 0xc0 // These bits indicate the general family of | ||
456 | // product. | ||
457 | #define POR_ID_FII 0x00 // Family is "IntelliPort-II" | ||
458 | #define POR_ID_FIIEX 0x40 // Family is "IntelliPort-IIEX" | ||
459 | |||
460 | // These bits are reserved, presently zero. May be used at a later date to | ||
461 | // convey other product information. | ||
462 | // | ||
463 | #define POR_ID_RESERVED 0x3c | ||
464 | |||
465 | #define POR_ID_SIZE 0x03 // Remaining bits indicate number of ports & | ||
466 | // Connector information. | ||
467 | #define POR_ID_II_8 0x00 // For IntelliPort-II, indicates 8-port using | ||
468 | // standard brick. | ||
469 | #define POR_ID_II_8R 0x01 // For IntelliPort-II, indicates 8-port using | ||
470 | // RJ11's (no CTS) | ||
471 | #define POR_ID_II_6 0x02 // For IntelliPort-II, indicates 6-port using | ||
472 | // RJ45's | ||
473 | #define POR_ID_II_4 0x03 // For IntelliPort-II, indicates 4-port using | ||
474 | // 4xRJ45 connectors | ||
475 | #define POR_ID_EX 0x00 // For IntelliPort-IIEX, indicates standard | ||
476 | // expandable controller (other values reserved) | ||
477 | |||
478 | //---------------------- | ||
479 | // porBus | ||
480 | //---------------------- | ||
481 | |||
482 | // IntelliPort-IIEX only: Board is installed in a 16-bit slot | ||
483 | // | ||
484 | #define POR_BUS_SLOT16 0x20 | ||
485 | |||
486 | // IntelliPort-IIEX only: DIP switch #8 is on, selecting 16-bit host interface | ||
487 | // operation. | ||
488 | // | ||
489 | #define POR_BUS_DIP16 0x10 | ||
490 | |||
491 | // Bits 0-2 indicate type of bus: This information is stored in the bootstrap | ||
492 | // loadware, different loadware being used on different products for different | ||
493 | // buses. For most situations, the drivers do not need this information; but it | ||
494 | // is handy in a diagnostic environment. For example, on microchannel boards, | ||
495 | // you would not want to try to test several interrupts, only the one for which | ||
496 | // you were configured. | ||
497 | // | ||
498 | #define POR_BUS_TYPE 0x07 | ||
499 | |||
500 | // Unknown: this product doesn't know what bus it is running in. (e.g. if same | ||
501 | // bootstrap firmware were wanted for two different buses.) | ||
502 | // | ||
503 | #define POR_BUS_T_UNK 0 | ||
504 | |||
505 | // Note: existing firmware for ISA-8 and MC-8 currently report the POR_BUS_T_UNK | ||
506 | // state, since the same bootstrap firmware is used for each. | ||
507 | |||
508 | #define POR_BUS_T_MCA 1 // MCA BUS */ | ||
509 | #define POR_BUS_T_EISA 2 // EISA BUS */ | ||
510 | #define POR_BUS_T_ISA 3 // ISA BUS */ | ||
511 | |||
512 | // Values 4-7 Reserved | ||
513 | |||
514 | // Remaining bits are reserved | ||
515 | |||
516 | //---------------------- | ||
517 | // porDiag1 | ||
518 | //---------------------- | ||
519 | |||
520 | #define POR_BAD_MAPPER 0x80 // HW failure on P.O.S.T: Chip mapper failed | ||
521 | |||
522 | // These two bits valid only for the IntelliPort-II | ||
523 | // | ||
524 | #define POR_BAD_UART1 0x01 // First 1400 bad | ||
525 | #define POR_BAD_UART2 0x02 // Second 1400 bad | ||
526 | |||
527 | //---------------------- | ||
528 | // porDiag2 | ||
529 | //---------------------- | ||
530 | |||
531 | #define POR_DEBUG_PORT 0x80 // debug port was detected by the P.O.S.T | ||
532 | #define POR_DIAG_OK 0x00 // Indicates passage: Failure codes not yet | ||
533 | // available. | ||
534 | // Other bits undefined. | ||
535 | //---------------------- | ||
536 | // porFlags | ||
537 | //---------------------- | ||
538 | |||
539 | #define POR_CPU 0x03 // These bits indicate supposed CPU type | ||
540 | #define POR_CPU_8 0x01 // Board uses an 80188 (no such thing yet) | ||
541 | #define POR_CPU_6 0x02 // Board uses an 80186 (all existing products) | ||
542 | #define POR_CEX4 0x04 // If set, this is an ISA-CEX/4: An ISA-4 (asic) | ||
543 | // which is architected like an ISA-CEX connected | ||
544 | // to a (hitherto impossible) 4-port box. | ||
545 | #define POR_BOXES 0xf0 // Valid for IntelliPort-IIEX only: Map of Box | ||
546 | // sizes based on box I.D. | ||
547 | #define POR_BOX_16 0x10 // Set indicates 16-port, clear 8-port | ||
548 | |||
549 | //------------------------------------- | ||
550 | // LOADWARE and DOWNLOADING CODE | ||
551 | //------------------------------------- | ||
552 | |||
553 | /* | ||
554 | Loadware may be sent to the board in two ways: | ||
555 | 1) It may be read from a (binary image) data file block by block as each block | ||
556 | is sent to the board. This is only possible when the initialization is | ||
557 | performed by code which can access your file system. This is most suitable | ||
558 | for diagnostics and appications which use the interface library directly. | ||
559 | |||
560 | 2) It may be hard-coded into your source by including a .h file (typically | ||
561 | supplied by Computone), which declares a data array and initializes every | ||
562 | element. This achieves the same result as if an entire loadware file had | ||
563 | been read into the array. | ||
564 | |||
565 | This requires more data space in your program, but access to the file system | ||
566 | is not required. This method is more suited to driver code, which typically | ||
567 | is running at a level too low to access the file system directly. | ||
568 | |||
569 | At present, loadware can only be generated at Computone. | ||
570 | |||
571 | All Loadware begins with a header area which has a particular format. This | ||
572 | includes a magic number which identifies the file as being (purportedly) | ||
573 | loadware, CRC (for the loader), and version information. | ||
574 | */ | ||
575 | |||
576 | |||
577 | //----------------------------------------------------------------------------- | ||
578 | // Format of loadware block | ||
579 | // | ||
580 | // This is defined as a union so we can pass a pointer to one of these items | ||
581 | // and (if it is the first block) pick out the version information, etc. | ||
582 | // | ||
583 | // Otherwise, to deal with this as a simple character array | ||
584 | //------------------------------------------------------------------------------ | ||
585 | |||
586 | #define LOADWARE_BLOCK_SIZE 512 // Number of bytes in each block of loadware | ||
587 | |||
588 | typedef union _loadHdrStr | ||
589 | { | ||
590 | unsigned char c[LOADWARE_BLOCK_SIZE]; // Valid for every block | ||
591 | |||
592 | struct // These fields are valid for only the first block of loadware. | ||
593 | { | ||
594 | unsigned char loadMagic; // Magic number: see below | ||
595 | unsigned char loadBlocksMore; // How many more blocks? | ||
596 | unsigned char loadCRC[2]; // Two CRC bytes: used by loader | ||
597 | unsigned char loadVersion; // Version number | ||
598 | unsigned char loadRevision; // Revision number | ||
599 | unsigned char loadSubRevision; // Sub-revision number | ||
600 | unsigned char loadSpares[9]; // Presently unused | ||
601 | unsigned char loadDates[32]; // Null-terminated string which can give | ||
602 | // date and time of compilation | ||
603 | } e; | ||
604 | } loadHdrStr, *loadHdrStrPtr; | ||
605 | |||
606 | //------------------------------------ | ||
607 | // Defines for downloading code: | ||
608 | //------------------------------------ | ||
609 | |||
610 | // The loadMagic field in the first block of the loadfile must be this, else the | ||
611 | // file is not valid. | ||
612 | // | ||
613 | #define MAGIC_LOADFILE 0x3c | ||
614 | |||
615 | // How do we know the load was successful? On completion of the load, the | ||
616 | // bootstrap firmware returns a code to indicate whether it thought the download | ||
617 | // was valid and intends to execute it. These are the only possible valid codes: | ||
618 | // | ||
619 | #define LOADWARE_OK 0xc3 // Download was ok | ||
620 | #define LOADWARE_BAD 0x5a // Download was bad (CRC error) | ||
621 | |||
622 | // Constants applicable to writing blocks of loadware: | ||
623 | // The first block of loadware might take 600 mS to load, in extreme cases. | ||
624 | // (Expandable board: worst case for sending startup messages to the LCD's). | ||
625 | // The 600mS figure is not really a calculation, but a conservative | ||
626 | // guess/guarantee. Usually this will be within 100 mS, like subsequent blocks. | ||
627 | // | ||
628 | #define MAX_DLOAD_START_TIME 1000 // 1000 mS | ||
629 | #define MAX_DLOAD_READ_TIME 100 // 100 mS | ||
630 | |||
631 | // Firmware should respond with status (see above) within this long of host | ||
632 | // having sent the final block. | ||
633 | // | ||
634 | #define MAX_DLOAD_ACK_TIME 100 // 100 mS, again! | ||
635 | |||
636 | //------------------------------------------------------ | ||
637 | // MAXIMUM NUMBER OF PORTS PER BOARD: | ||
638 | // This is fixed for now (with the expandable), but may | ||
639 | // be expanding according to even newer products. | ||
640 | //------------------------------------------------------ | ||
641 | // | ||
642 | #define ABS_MAX_BOXES 4 // Absolute most boxes per board | ||
643 | #define ABS_BIGGEST_BOX 16 // Absolute the most ports per box | ||
644 | #define ABS_MOST_PORTS (ABS_MAX_BOXES * ABS_BIGGEST_BOX) | ||
645 | |||
646 | #define I2_OUTSW(port, addr, count) outsw((port), (addr), (((count)+1)/2)) | ||
647 | #define I2_OUTSB(port, addr, count) outsb((port), (addr), (((count)+1))&-2) | ||
648 | #define I2_INSW(port, addr, count) insw((port), (addr), (((count)+1)/2)) | ||
649 | #define I2_INSB(port, addr, count) insb((port), (addr), (((count)+1))&-2) | ||
650 | |||
651 | #endif // I2HW_H | ||
652 | |||
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c deleted file mode 100644 index 0d10b89218ed..000000000000 --- a/drivers/char/ip2/i2lib.c +++ /dev/null | |||
@@ -1,2214 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: High-level interface code for the device driver. Uses the | ||
12 | * Extremely Low Level Interface Support (i2ellis.c). Provides an | ||
13 | * interface to the standard loadware, to support drivers or | ||
14 | * application code. (This is included source code, not a separate | ||
15 | * compilation module.) | ||
16 | * | ||
17 | *******************************************************************************/ | ||
18 | //------------------------------------------------------------------------------ | ||
19 | // Note on Strategy: | ||
20 | // Once the board has been initialized, it will interrupt us when: | ||
21 | // 1) It has something in the fifo for us to read (incoming data, flow control | ||
22 | // packets, or whatever). | ||
23 | // 2) It has stripped whatever we have sent last time in the FIFO (and | ||
24 | // consequently is ready for more). | ||
25 | // | ||
26 | // Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This | ||
27 | // worsens performance considerably, but is done so that a great many channels | ||
28 | // might use only a little memory. | ||
29 | //------------------------------------------------------------------------------ | ||
30 | |||
31 | //------------------------------------------------------------------------------ | ||
32 | // Revision History: | ||
33 | // | ||
34 | // 0.00 - 4/16/91 --- First Draft | ||
35 | // 0.01 - 4/29/91 --- 1st beta release | ||
36 | // 0.02 - 6/14/91 --- Changes to allow small model compilation | ||
37 | // 0.03 - 6/17/91 MAG Break reporting protected from interrupts routines with | ||
38 | // in-line asm added for moving data to/from ring buffers, | ||
39 | // replacing a variety of methods used previously. | ||
40 | // 0.04 - 6/21/91 MAG Initial flow-control packets not queued until | ||
41 | // i2_enable_interrupts time. Former versions would enqueue | ||
42 | // them at i2_init_channel time, before we knew how many | ||
43 | // channels were supposed to exist! | ||
44 | // 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now; | ||
45 | // supports new 16-bit protocol and expandable boards. | ||
46 | // - 10/24/91 MAG Most changes in place and stable. | ||
47 | // 0.06 - 2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no | ||
48 | // argument. | ||
49 | // 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt | ||
50 | // level (mostly responses to specific commands.) | ||
51 | // 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet | ||
52 | // 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE | ||
53 | // turning on the interrupt. | ||
54 | // 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check | ||
55 | // some incoming. | ||
56 | // | ||
57 | // 1.1 - 12/25/96 AKM Linux version. | ||
58 | // - 10/09/98 DMC Revised Linux version. | ||
59 | //------------------------------------------------------------------------------ | ||
60 | |||
61 | //************ | ||
62 | //* Includes * | ||
63 | //************ | ||
64 | |||
65 | #include <linux/sched.h> | ||
66 | #include "i2lib.h" | ||
67 | |||
68 | |||
69 | //*********************** | ||
70 | //* Function Prototypes * | ||
71 | //*********************** | ||
72 | static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int); | ||
73 | static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int ); | ||
74 | static void i2StripFifo(i2eBordStrPtr); | ||
75 | static void i2StuffFifoBypass(i2eBordStrPtr); | ||
76 | static void i2StuffFifoFlow(i2eBordStrPtr); | ||
77 | static void i2StuffFifoInline(i2eBordStrPtr); | ||
78 | static int i2RetryFlushOutput(i2ChanStrPtr); | ||
79 | |||
80 | // Not a documented part of the library routines (careful...) but the Diagnostic | ||
81 | // i2diag.c finds them useful to help the throughput in certain limited | ||
82 | // single-threaded operations. | ||
83 | static void iiSendPendingMail(i2eBordStrPtr); | ||
84 | static void serviceOutgoingFifo(i2eBordStrPtr); | ||
85 | |||
86 | // Functions defined in ip2.c as part of interrupt handling | ||
87 | static void do_input(struct work_struct *); | ||
88 | static void do_status(struct work_struct *); | ||
89 | |||
90 | //*************** | ||
91 | //* Debug Data * | ||
92 | //*************** | ||
93 | #ifdef DEBUG_FIFO | ||
94 | |||
95 | unsigned char DBGBuf[0x4000]; | ||
96 | unsigned short I = 0; | ||
97 | |||
98 | static void | ||
99 | WriteDBGBuf(char *s, unsigned char *src, unsigned short n ) | ||
100 | { | ||
101 | char *p = src; | ||
102 | |||
103 | // XXX: We need a spin lock here if we ever use this again | ||
104 | |||
105 | while (*s) { // copy label | ||
106 | DBGBuf[I] = *s++; | ||
107 | I = I++ & 0x3fff; | ||
108 | } | ||
109 | while (n--) { // copy data | ||
110 | DBGBuf[I] = *p++; | ||
111 | I = I++ & 0x3fff; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static void | ||
116 | fatality(i2eBordStrPtr pB ) | ||
117 | { | ||
118 | int i; | ||
119 | |||
120 | for (i=0;i<sizeof(DBGBuf);i++) { | ||
121 | if ((i%16) == 0) | ||
122 | printk("\n%4x:",i); | ||
123 | printk("%02x ",DBGBuf[i]); | ||
124 | } | ||
125 | printk("\n"); | ||
126 | for (i=0;i<sizeof(DBGBuf);i++) { | ||
127 | if ((i%16) == 0) | ||
128 | printk("\n%4x:",i); | ||
129 | if (DBGBuf[i] >= ' ' && DBGBuf[i] <= '~') { | ||
130 | printk(" %c ",DBGBuf[i]); | ||
131 | } else { | ||
132 | printk(" . "); | ||
133 | } | ||
134 | } | ||
135 | printk("\n"); | ||
136 | printk("Last index %x\n",I); | ||
137 | } | ||
138 | #endif /* DEBUG_FIFO */ | ||
139 | |||
140 | //******** | ||
141 | //* Code * | ||
142 | //******** | ||
143 | |||
144 | static inline int | ||
145 | i2Validate ( i2ChanStrPtr pCh ) | ||
146 | { | ||
147 | //ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity, | ||
148 | // (CHANNEL_MAGIC | CHANNEL_SUPPORT)); | ||
149 | return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) | ||
150 | == (CHANNEL_MAGIC | CHANNEL_SUPPORT)); | ||
151 | } | ||
152 | |||
153 | static void iiSendPendingMail_t(unsigned long data) | ||
154 | { | ||
155 | i2eBordStrPtr pB = (i2eBordStrPtr)data; | ||
156 | |||
157 | iiSendPendingMail(pB); | ||
158 | } | ||
159 | |||
160 | //****************************************************************************** | ||
161 | // Function: iiSendPendingMail(pB) | ||
162 | // Parameters: Pointer to a board structure | ||
163 | // Returns: Nothing | ||
164 | // | ||
165 | // Description: | ||
166 | // If any outgoing mail bits are set and there is outgoing mailbox is empty, | ||
167 | // send the mail and clear the bits. | ||
168 | //****************************************************************************** | ||
169 | static void | ||
170 | iiSendPendingMail(i2eBordStrPtr pB) | ||
171 | { | ||
172 | if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) ) | ||
173 | { | ||
174 | if (iiTrySendMail(pB, pB->i2eOutMailWaiting)) | ||
175 | { | ||
176 | /* If we were already waiting for fifo to empty, | ||
177 | * or just sent MB_OUT_STUFFED, then we are | ||
178 | * still waiting for it to empty, until we should | ||
179 | * receive an MB_IN_STRIPPED from the board. | ||
180 | */ | ||
181 | pB->i2eWaitingForEmptyFifo |= | ||
182 | (pB->i2eOutMailWaiting & MB_OUT_STUFFED); | ||
183 | pB->i2eOutMailWaiting = 0; | ||
184 | pB->SendPendingRetry = 0; | ||
185 | } else { | ||
186 | /* The only time we hit this area is when "iiTrySendMail" has | ||
187 | failed. That only occurs when the outbound mailbox is | ||
188 | still busy with the last message. We take a short breather | ||
189 | to let the board catch up with itself and then try again. | ||
190 | 16 Retries is the limit - then we got a borked board. | ||
191 | /\/\|=mhw=|\/\/ */ | ||
192 | |||
193 | if( ++pB->SendPendingRetry < 16 ) { | ||
194 | setup_timer(&pB->SendPendingTimer, | ||
195 | iiSendPendingMail_t, (unsigned long)pB); | ||
196 | mod_timer(&pB->SendPendingTimer, jiffies + 1); | ||
197 | } else { | ||
198 | printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" ); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | } | ||
203 | |||
204 | //****************************************************************************** | ||
205 | // Function: i2InitChannels(pB, nChannels, pCh) | ||
206 | // Parameters: Pointer to Ellis Board structure | ||
207 | // Number of channels to initialize | ||
208 | // Pointer to first element in an array of channel structures | ||
209 | // Returns: Success or failure | ||
210 | // | ||
211 | // Description: | ||
212 | // | ||
213 | // This function patches pointers, back-pointers, and initializes all the | ||
214 | // elements in the channel structure array. | ||
215 | // | ||
216 | // This should be run after the board structure is initialized, through having | ||
217 | // loaded the standard loadware (otherwise it complains). | ||
218 | // | ||
219 | // In any case, it must be done before any serious work begins initializing the | ||
220 | // irq's or sending commands... | ||
221 | // | ||
222 | //****************************************************************************** | ||
223 | static int | ||
224 | i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh) | ||
225 | { | ||
226 | int index, stuffIndex; | ||
227 | i2ChanStrPtr *ppCh; | ||
228 | |||
229 | if (pB->i2eValid != I2E_MAGIC) { | ||
230 | I2_COMPLETE(pB, I2EE_BADMAGIC); | ||
231 | } | ||
232 | if (pB->i2eState != II_STATE_STDLOADED) { | ||
233 | I2_COMPLETE(pB, I2EE_BADSTATE); | ||
234 | } | ||
235 | |||
236 | rwlock_init(&pB->read_fifo_spinlock); | ||
237 | rwlock_init(&pB->write_fifo_spinlock); | ||
238 | rwlock_init(&pB->Dbuf_spinlock); | ||
239 | rwlock_init(&pB->Bbuf_spinlock); | ||
240 | rwlock_init(&pB->Fbuf_spinlock); | ||
241 | |||
242 | // NO LOCK needed yet - this is init | ||
243 | |||
244 | pB->i2eChannelPtr = pCh; | ||
245 | pB->i2eChannelCnt = nChannels; | ||
246 | |||
247 | pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0; | ||
248 | pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0; | ||
249 | pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0; | ||
250 | |||
251 | pB->SendPendingRetry = 0; | ||
252 | |||
253 | memset ( pCh, 0, sizeof (i2ChanStr) * nChannels ); | ||
254 | |||
255 | for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf); | ||
256 | nChannels && index < ABS_MOST_PORTS; | ||
257 | index++) | ||
258 | { | ||
259 | if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) { | ||
260 | continue; | ||
261 | } | ||
262 | rwlock_init(&pCh->Ibuf_spinlock); | ||
263 | rwlock_init(&pCh->Obuf_spinlock); | ||
264 | rwlock_init(&pCh->Cbuf_spinlock); | ||
265 | rwlock_init(&pCh->Pbuf_spinlock); | ||
266 | // NO LOCK needed yet - this is init | ||
267 | // Set up validity flag according to support level | ||
268 | if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) { | ||
269 | pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT; | ||
270 | } else { | ||
271 | pCh->validity = CHANNEL_MAGIC; | ||
272 | } | ||
273 | pCh->pMyBord = pB; /* Back-pointer */ | ||
274 | |||
275 | // Prepare an outgoing flow-control packet to send as soon as the chance | ||
276 | // occurs. | ||
277 | if ( pCh->validity & CHANNEL_SUPPORT ) { | ||
278 | pCh->infl.hd.i2sChannel = index; | ||
279 | pCh->infl.hd.i2sCount = 5; | ||
280 | pCh->infl.hd.i2sType = PTYPE_BYPASS; | ||
281 | pCh->infl.fcmd = 37; | ||
282 | pCh->infl.asof = 0; | ||
283 | pCh->infl.room = IBUF_SIZE - 1; | ||
284 | |||
285 | pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full | ||
286 | |||
287 | // The following is similar to calling i2QueueNeeds, except that this | ||
288 | // is done in longhand, since we are setting up initial conditions on | ||
289 | // many channels at once. | ||
290 | pCh->channelNeeds = NEED_FLOW; // Since starting from scratch | ||
291 | pCh->sinceLastFlow = 0; // No bytes received since last flow | ||
292 | // control packet was queued | ||
293 | stuffIndex++; | ||
294 | *ppCh++ = pCh; // List this channel as needing | ||
295 | // initial flow control packet sent | ||
296 | } | ||
297 | |||
298 | // Don't allow anything to be sent until the status packets come in from | ||
299 | // the board. | ||
300 | |||
301 | pCh->outfl.asof = 0; | ||
302 | pCh->outfl.room = 0; | ||
303 | |||
304 | // Initialize all the ring buffers | ||
305 | |||
306 | pCh->Ibuf_stuff = pCh->Ibuf_strip = 0; | ||
307 | pCh->Obuf_stuff = pCh->Obuf_strip = 0; | ||
308 | pCh->Cbuf_stuff = pCh->Cbuf_strip = 0; | ||
309 | |||
310 | memset( &pCh->icount, 0, sizeof (struct async_icount) ); | ||
311 | pCh->hotKeyIn = HOT_CLEAR; | ||
312 | pCh->channelOptions = 0; | ||
313 | pCh->bookMarks = 0; | ||
314 | init_waitqueue_head(&pCh->pBookmarkWait); | ||
315 | |||
316 | init_waitqueue_head(&pCh->open_wait); | ||
317 | init_waitqueue_head(&pCh->close_wait); | ||
318 | init_waitqueue_head(&pCh->delta_msr_wait); | ||
319 | |||
320 | // Set base and divisor so default custom rate is 9600 | ||
321 | pCh->BaudBase = 921600; // MAX for ST654, changed after we get | ||
322 | pCh->BaudDivisor = 96; // the boxids (UART types) later | ||
323 | |||
324 | pCh->dataSetIn = 0; | ||
325 | pCh->dataSetOut = 0; | ||
326 | |||
327 | pCh->wopen = 0; | ||
328 | pCh->throttled = 0; | ||
329 | |||
330 | pCh->speed = CBR_9600; | ||
331 | |||
332 | pCh->flags = 0; | ||
333 | |||
334 | pCh->ClosingDelay = 5*HZ/10; | ||
335 | pCh->ClosingWaitTime = 30*HZ; | ||
336 | |||
337 | // Initialize task queue objects | ||
338 | INIT_WORK(&pCh->tqueue_input, do_input); | ||
339 | INIT_WORK(&pCh->tqueue_status, do_status); | ||
340 | |||
341 | #ifdef IP2DEBUG_TRACE | ||
342 | pCh->trace = ip2trace; | ||
343 | #endif | ||
344 | |||
345 | ++pCh; | ||
346 | --nChannels; | ||
347 | } | ||
348 | // No need to check for wrap here; this is initialization. | ||
349 | pB->i2Fbuf_stuff = stuffIndex; | ||
350 | I2_COMPLETE(pB, I2EE_GOOD); | ||
351 | |||
352 | } | ||
353 | |||
354 | //****************************************************************************** | ||
355 | // Function: i2DeQueueNeeds(pB, type) | ||
356 | // Parameters: Pointer to a board structure | ||
357 | // type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW | ||
358 | // Returns: | ||
359 | // Pointer to a channel structure | ||
360 | // | ||
361 | // Description: Returns pointer struct of next channel that needs service of | ||
362 | // the type specified. Otherwise returns a NULL reference. | ||
363 | // | ||
364 | //****************************************************************************** | ||
365 | static i2ChanStrPtr | ||
366 | i2DeQueueNeeds(i2eBordStrPtr pB, int type) | ||
367 | { | ||
368 | unsigned short queueIndex; | ||
369 | unsigned long flags; | ||
370 | |||
371 | i2ChanStrPtr pCh = NULL; | ||
372 | |||
373 | switch(type) { | ||
374 | |||
375 | case NEED_INLINE: | ||
376 | |||
377 | write_lock_irqsave(&pB->Dbuf_spinlock, flags); | ||
378 | if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip) | ||
379 | { | ||
380 | queueIndex = pB->i2Dbuf_strip; | ||
381 | pCh = pB->i2Dbuf[queueIndex]; | ||
382 | queueIndex++; | ||
383 | if (queueIndex >= CH_QUEUE_SIZE) { | ||
384 | queueIndex = 0; | ||
385 | } | ||
386 | pB->i2Dbuf_strip = queueIndex; | ||
387 | pCh->channelNeeds &= ~NEED_INLINE; | ||
388 | } | ||
389 | write_unlock_irqrestore(&pB->Dbuf_spinlock, flags); | ||
390 | break; | ||
391 | |||
392 | case NEED_BYPASS: | ||
393 | |||
394 | write_lock_irqsave(&pB->Bbuf_spinlock, flags); | ||
395 | if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip) | ||
396 | { | ||
397 | queueIndex = pB->i2Bbuf_strip; | ||
398 | pCh = pB->i2Bbuf[queueIndex]; | ||
399 | queueIndex++; | ||
400 | if (queueIndex >= CH_QUEUE_SIZE) { | ||
401 | queueIndex = 0; | ||
402 | } | ||
403 | pB->i2Bbuf_strip = queueIndex; | ||
404 | pCh->channelNeeds &= ~NEED_BYPASS; | ||
405 | } | ||
406 | write_unlock_irqrestore(&pB->Bbuf_spinlock, flags); | ||
407 | break; | ||
408 | |||
409 | case NEED_FLOW: | ||
410 | |||
411 | write_lock_irqsave(&pB->Fbuf_spinlock, flags); | ||
412 | if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip) | ||
413 | { | ||
414 | queueIndex = pB->i2Fbuf_strip; | ||
415 | pCh = pB->i2Fbuf[queueIndex]; | ||
416 | queueIndex++; | ||
417 | if (queueIndex >= CH_QUEUE_SIZE) { | ||
418 | queueIndex = 0; | ||
419 | } | ||
420 | pB->i2Fbuf_strip = queueIndex; | ||
421 | pCh->channelNeeds &= ~NEED_FLOW; | ||
422 | } | ||
423 | write_unlock_irqrestore(&pB->Fbuf_spinlock, flags); | ||
424 | break; | ||
425 | default: | ||
426 | printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type); | ||
427 | break; | ||
428 | } | ||
429 | return pCh; | ||
430 | } | ||
431 | |||
432 | //****************************************************************************** | ||
433 | // Function: i2QueueNeeds(pB, pCh, type) | ||
434 | // Parameters: Pointer to a board structure | ||
435 | // Pointer to a channel structure | ||
436 | // type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW | ||
437 | // Returns: Nothing | ||
438 | // | ||
439 | // Description: | ||
440 | // For each type of need selected, if the given channel is not already in the | ||
441 | // queue, adds it, and sets the flag indicating it is in the queue. | ||
442 | //****************************************************************************** | ||
443 | static void | ||
444 | i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type) | ||
445 | { | ||
446 | unsigned short queueIndex; | ||
447 | unsigned long flags; | ||
448 | |||
449 | // We turn off all the interrupts during this brief process, since the | ||
450 | // interrupt-level code might want to put things on the queue as well. | ||
451 | |||
452 | switch (type) { | ||
453 | |||
454 | case NEED_INLINE: | ||
455 | |||
456 | write_lock_irqsave(&pB->Dbuf_spinlock, flags); | ||
457 | if ( !(pCh->channelNeeds & NEED_INLINE) ) | ||
458 | { | ||
459 | pCh->channelNeeds |= NEED_INLINE; | ||
460 | queueIndex = pB->i2Dbuf_stuff; | ||
461 | pB->i2Dbuf[queueIndex++] = pCh; | ||
462 | if (queueIndex >= CH_QUEUE_SIZE) | ||
463 | queueIndex = 0; | ||
464 | pB->i2Dbuf_stuff = queueIndex; | ||
465 | } | ||
466 | write_unlock_irqrestore(&pB->Dbuf_spinlock, flags); | ||
467 | break; | ||
468 | |||
469 | case NEED_BYPASS: | ||
470 | |||
471 | write_lock_irqsave(&pB->Bbuf_spinlock, flags); | ||
472 | if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS)) | ||
473 | { | ||
474 | pCh->channelNeeds |= NEED_BYPASS; | ||
475 | queueIndex = pB->i2Bbuf_stuff; | ||
476 | pB->i2Bbuf[queueIndex++] = pCh; | ||
477 | if (queueIndex >= CH_QUEUE_SIZE) | ||
478 | queueIndex = 0; | ||
479 | pB->i2Bbuf_stuff = queueIndex; | ||
480 | } | ||
481 | write_unlock_irqrestore(&pB->Bbuf_spinlock, flags); | ||
482 | break; | ||
483 | |||
484 | case NEED_FLOW: | ||
485 | |||
486 | write_lock_irqsave(&pB->Fbuf_spinlock, flags); | ||
487 | if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW)) | ||
488 | { | ||
489 | pCh->channelNeeds |= NEED_FLOW; | ||
490 | queueIndex = pB->i2Fbuf_stuff; | ||
491 | pB->i2Fbuf[queueIndex++] = pCh; | ||
492 | if (queueIndex >= CH_QUEUE_SIZE) | ||
493 | queueIndex = 0; | ||
494 | pB->i2Fbuf_stuff = queueIndex; | ||
495 | } | ||
496 | write_unlock_irqrestore(&pB->Fbuf_spinlock, flags); | ||
497 | break; | ||
498 | |||
499 | case NEED_CREDIT: | ||
500 | pCh->channelNeeds |= NEED_CREDIT; | ||
501 | break; | ||
502 | default: | ||
503 | printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type); | ||
504 | break; | ||
505 | } | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | //****************************************************************************** | ||
510 | // Function: i2QueueCommands(type, pCh, timeout, nCommands, pCs,...) | ||
511 | // Parameters: type - PTYPE_BYPASS or PTYPE_INLINE | ||
512 | // pointer to the channel structure | ||
513 | // maximum period to wait | ||
514 | // number of commands (n) | ||
515 | // n commands | ||
516 | // Returns: Number of commands sent, or -1 for error | ||
517 | // | ||
518 | // get board lock before calling | ||
519 | // | ||
520 | // Description: | ||
521 | // Queues up some commands to be sent to a channel. To send possibly several | ||
522 | // bypass or inline commands to the given channel. The timeout parameter | ||
523 | // indicates how many HUNDREDTHS OF SECONDS to wait until there is room: | ||
524 | // 0 = return immediately if no room, -ive = wait forever, +ive = number of | ||
525 | // 1/100 seconds to wait. Return values: | ||
526 | // -1 Some kind of nasty error: bad channel structure or invalid arguments. | ||
527 | // 0 No room to send all the commands | ||
528 | // (+) Number of commands sent | ||
529 | //****************************************************************************** | ||
530 | static int | ||
531 | i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands, | ||
532 | cmdSyntaxPtr pCs0,...) | ||
533 | { | ||
534 | int totalsize = 0; | ||
535 | int blocksize; | ||
536 | int lastended; | ||
537 | cmdSyntaxPtr *ppCs; | ||
538 | cmdSyntaxPtr pCs; | ||
539 | int count; | ||
540 | int flag; | ||
541 | i2eBordStrPtr pB; | ||
542 | |||
543 | unsigned short maxBlock; | ||
544 | unsigned short maxBuff; | ||
545 | short bufroom; | ||
546 | unsigned short stuffIndex; | ||
547 | unsigned char *pBuf; | ||
548 | unsigned char *pInsert; | ||
549 | unsigned char *pDest, *pSource; | ||
550 | unsigned short channel; | ||
551 | int cnt; | ||
552 | unsigned long flags = 0; | ||
553 | rwlock_t *lock_var_p = NULL; | ||
554 | |||
555 | // Make sure the channel exists, otherwise do nothing | ||
556 | if ( !i2Validate ( pCh ) ) { | ||
557 | return -1; | ||
558 | } | ||
559 | |||
560 | ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 ); | ||
561 | |||
562 | pB = pCh->pMyBord; | ||
563 | |||
564 | // Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT | ||
565 | if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED) | ||
566 | return -2; | ||
567 | // If the board has gone fatal, return bad, and also hit the trap routine if | ||
568 | // it exists. | ||
569 | if (pB->i2eFatal) { | ||
570 | if ( pB->i2eFatalTrap ) { | ||
571 | (*(pB)->i2eFatalTrap)(pB); | ||
572 | } | ||
573 | return -3; | ||
574 | } | ||
575 | // Set up some variables, Which buffers are we using? How big are they? | ||
576 | switch(type) | ||
577 | { | ||
578 | case PTYPE_INLINE: | ||
579 | flag = INL; | ||
580 | maxBlock = MAX_OBUF_BLOCK; | ||
581 | maxBuff = OBUF_SIZE; | ||
582 | pBuf = pCh->Obuf; | ||
583 | break; | ||
584 | case PTYPE_BYPASS: | ||
585 | flag = BYP; | ||
586 | maxBlock = MAX_CBUF_BLOCK; | ||
587 | maxBuff = CBUF_SIZE; | ||
588 | pBuf = pCh->Cbuf; | ||
589 | break; | ||
590 | default: | ||
591 | return -4; | ||
592 | } | ||
593 | // Determine the total size required for all the commands | ||
594 | totalsize = blocksize = sizeof(i2CmdHeader); | ||
595 | lastended = 0; | ||
596 | ppCs = &pCs0; | ||
597 | for ( count = nCommands; count; count--, ppCs++) | ||
598 | { | ||
599 | pCs = *ppCs; | ||
600 | cnt = pCs->length; | ||
601 | // Will a new block be needed for this one? | ||
602 | // Two possible reasons: too | ||
603 | // big or previous command has to be at the end of a packet. | ||
604 | if ((blocksize + cnt > maxBlock) || lastended) { | ||
605 | blocksize = sizeof(i2CmdHeader); | ||
606 | totalsize += sizeof(i2CmdHeader); | ||
607 | } | ||
608 | totalsize += cnt; | ||
609 | blocksize += cnt; | ||
610 | |||
611 | // If this command had to end a block, then we will make sure to | ||
612 | // account for it should there be any more blocks. | ||
613 | lastended = pCs->flags & END; | ||
614 | } | ||
615 | for (;;) { | ||
616 | // Make sure any pending flush commands go out before we add more data. | ||
617 | if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) { | ||
618 | // How much room (this time through) ? | ||
619 | switch(type) { | ||
620 | case PTYPE_INLINE: | ||
621 | lock_var_p = &pCh->Obuf_spinlock; | ||
622 | write_lock_irqsave(lock_var_p, flags); | ||
623 | stuffIndex = pCh->Obuf_stuff; | ||
624 | bufroom = pCh->Obuf_strip - stuffIndex; | ||
625 | break; | ||
626 | case PTYPE_BYPASS: | ||
627 | lock_var_p = &pCh->Cbuf_spinlock; | ||
628 | write_lock_irqsave(lock_var_p, flags); | ||
629 | stuffIndex = pCh->Cbuf_stuff; | ||
630 | bufroom = pCh->Cbuf_strip - stuffIndex; | ||
631 | break; | ||
632 | default: | ||
633 | return -5; | ||
634 | } | ||
635 | if (--bufroom < 0) { | ||
636 | bufroom += maxBuff; | ||
637 | } | ||
638 | |||
639 | ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom ); | ||
640 | |||
641 | // Check for overflow | ||
642 | if (totalsize <= bufroom) { | ||
643 | // Normal Expected path - We still hold LOCK | ||
644 | break; /* from for()- Enough room: goto proceed */ | ||
645 | } | ||
646 | ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); | ||
647 | write_unlock_irqrestore(lock_var_p, flags); | ||
648 | } else | ||
649 | ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize); | ||
650 | |||
651 | /* Prepare to wait for buffers to empty */ | ||
652 | serviceOutgoingFifo(pB); // Dump what we got | ||
653 | |||
654 | if (timeout == 0) { | ||
655 | return 0; // Tired of waiting | ||
656 | } | ||
657 | if (timeout > 0) | ||
658 | timeout--; // So negative values == forever | ||
659 | |||
660 | if (!in_interrupt()) { | ||
661 | schedule_timeout_interruptible(1); // short nap | ||
662 | } else { | ||
663 | // we cannot sched/sleep in interrupt silly | ||
664 | return 0; | ||
665 | } | ||
666 | if (signal_pending(current)) { | ||
667 | return 0; // Wake up! Time to die!!! | ||
668 | } | ||
669 | |||
670 | ip2trace (CHANN, ITRC_QUEUE, 4, 0 ); | ||
671 | |||
672 | } // end of for(;;) | ||
673 | |||
674 | // At this point we have room and the lock - stick them in. | ||
675 | channel = pCh->infl.hd.i2sChannel; | ||
676 | pInsert = &pBuf[stuffIndex]; // Pointer to start of packet | ||
677 | pDest = CMD_OF(pInsert); // Pointer to start of command | ||
678 | |||
679 | // When we start counting, the block is the size of the header | ||
680 | for (blocksize = sizeof(i2CmdHeader), count = nCommands, | ||
681 | lastended = 0, ppCs = &pCs0; | ||
682 | count; | ||
683 | count--, ppCs++) | ||
684 | { | ||
685 | pCs = *ppCs; // Points to command protocol structure | ||
686 | |||
687 | // If this is a bookmark request command, post the fact that a bookmark | ||
688 | // request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ | ||
689 | // has no parameters! The more general solution would be to reference | ||
690 | // pCs->cmd[0]. | ||
691 | if (pCs == CMD_BMARK_REQ) { | ||
692 | pCh->bookMarks++; | ||
693 | |||
694 | ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks ); | ||
695 | |||
696 | } | ||
697 | cnt = pCs->length; | ||
698 | |||
699 | // If this command would put us over the maximum block size or | ||
700 | // if the last command had to be at the end of a block, we end | ||
701 | // the existing block here and start a new one. | ||
702 | if ((blocksize + cnt > maxBlock) || lastended) { | ||
703 | |||
704 | ip2trace (CHANN, ITRC_QUEUE, 5, 0 ); | ||
705 | |||
706 | PTYPE_OF(pInsert) = type; | ||
707 | CHANNEL_OF(pInsert) = channel; | ||
708 | // count here does not include the header | ||
709 | CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); | ||
710 | stuffIndex += blocksize; | ||
711 | if(stuffIndex >= maxBuff) { | ||
712 | stuffIndex = 0; | ||
713 | pInsert = pBuf; | ||
714 | } | ||
715 | pInsert = &pBuf[stuffIndex]; // Pointer to start of next pkt | ||
716 | pDest = CMD_OF(pInsert); | ||
717 | blocksize = sizeof(i2CmdHeader); | ||
718 | } | ||
719 | // Now we know there is room for this one in the current block | ||
720 | |||
721 | blocksize += cnt; // Total bytes in this command | ||
722 | pSource = pCs->cmd; // Copy the command into the buffer | ||
723 | while (cnt--) { | ||
724 | *pDest++ = *pSource++; | ||
725 | } | ||
726 | // If this command had to end a block, then we will make sure to account | ||
727 | // for it should there be any more blocks. | ||
728 | lastended = pCs->flags & END; | ||
729 | } // end for | ||
730 | // Clean up the final block by writing header, etc | ||
731 | |||
732 | PTYPE_OF(pInsert) = type; | ||
733 | CHANNEL_OF(pInsert) = channel; | ||
734 | // count here does not include the header | ||
735 | CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader); | ||
736 | stuffIndex += blocksize; | ||
737 | if(stuffIndex >= maxBuff) { | ||
738 | stuffIndex = 0; | ||
739 | pInsert = pBuf; | ||
740 | } | ||
741 | // Updates the index, and post the need for service. When adding these to | ||
742 | // the queue of channels, we turn off the interrupt while doing so, | ||
743 | // because at interrupt level we might want to push a channel back to the | ||
744 | // end of the queue. | ||
745 | switch(type) | ||
746 | { | ||
747 | case PTYPE_INLINE: | ||
748 | pCh->Obuf_stuff = stuffIndex; // Store buffer pointer | ||
749 | write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
750 | |||
751 | pB->debugInlineQueued++; | ||
752 | // Add the channel pointer to list of channels needing service (first | ||
753 | // come...), if it's not already there. | ||
754 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
755 | break; | ||
756 | |||
757 | case PTYPE_BYPASS: | ||
758 | pCh->Cbuf_stuff = stuffIndex; // Store buffer pointer | ||
759 | write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags); | ||
760 | |||
761 | pB->debugBypassQueued++; | ||
762 | // Add the channel pointer to list of channels needing service (first | ||
763 | // come...), if it's not already there. | ||
764 | i2QueueNeeds(pB, pCh, NEED_BYPASS); | ||
765 | break; | ||
766 | } | ||
767 | |||
768 | ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands ); | ||
769 | |||
770 | return nCommands; // Good status: number of commands sent | ||
771 | } | ||
772 | |||
773 | //****************************************************************************** | ||
774 | // Function: i2GetStatus(pCh,resetBits) | ||
775 | // Parameters: Pointer to a channel structure | ||
776 | // Bit map of status bits to clear | ||
777 | // Returns: Bit map of current status bits | ||
778 | // | ||
779 | // Description: | ||
780 | // Returns the state of data set signals, and whether a break has been received, | ||
781 | // (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status | ||
782 | // bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared | ||
783 | // AFTER the condition is passed. If pCh does not point to a valid channel, | ||
784 | // returns -1 (which would be impossible otherwise. | ||
785 | //****************************************************************************** | ||
786 | static int | ||
787 | i2GetStatus(i2ChanStrPtr pCh, int resetBits) | ||
788 | { | ||
789 | unsigned short status; | ||
790 | i2eBordStrPtr pB; | ||
791 | |||
792 | ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits ); | ||
793 | |||
794 | // Make sure the channel exists, otherwise do nothing */ | ||
795 | if ( !i2Validate ( pCh ) ) | ||
796 | return -1; | ||
797 | |||
798 | pB = pCh->pMyBord; | ||
799 | |||
800 | status = pCh->dataSetIn; | ||
801 | |||
802 | // Clear any specified error bits: but note that only actual error bits can | ||
803 | // be cleared, regardless of the value passed. | ||
804 | if (resetBits) | ||
805 | { | ||
806 | pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR)); | ||
807 | pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI); | ||
808 | } | ||
809 | |||
810 | ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn ); | ||
811 | |||
812 | return status; | ||
813 | } | ||
814 | |||
815 | //****************************************************************************** | ||
816 | // Function: i2Input(pChpDest,count) | ||
817 | // Parameters: Pointer to a channel structure | ||
818 | // Pointer to data buffer | ||
819 | // Number of bytes to read | ||
820 | // Returns: Number of bytes read, or -1 for error | ||
821 | // | ||
822 | // Description: | ||
823 | // Strips data from the input buffer and writes it to pDest. If there is a | ||
824 | // collosal blunder, (invalid structure pointers or the like), returns -1. | ||
825 | // Otherwise, returns the number of bytes read. | ||
826 | //****************************************************************************** | ||
827 | static int | ||
828 | i2Input(i2ChanStrPtr pCh) | ||
829 | { | ||
830 | int amountToMove; | ||
831 | unsigned short stripIndex; | ||
832 | int count; | ||
833 | unsigned long flags = 0; | ||
834 | |||
835 | ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0); | ||
836 | |||
837 | // Ensure channel structure seems real | ||
838 | if ( !i2Validate( pCh ) ) { | ||
839 | count = -1; | ||
840 | goto i2Input_exit; | ||
841 | } | ||
842 | write_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
843 | |||
844 | // initialize some accelerators and private copies | ||
845 | stripIndex = pCh->Ibuf_strip; | ||
846 | |||
847 | count = pCh->Ibuf_stuff - stripIndex; | ||
848 | |||
849 | // If buffer is empty or requested data count was 0, (trivial case) return | ||
850 | // without any further thought. | ||
851 | if ( count == 0 ) { | ||
852 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
853 | goto i2Input_exit; | ||
854 | } | ||
855 | // Adjust for buffer wrap | ||
856 | if ( count < 0 ) { | ||
857 | count += IBUF_SIZE; | ||
858 | } | ||
859 | // Don't give more than can be taken by the line discipline | ||
860 | amountToMove = pCh->pTTY->receive_room; | ||
861 | if (count > amountToMove) { | ||
862 | count = amountToMove; | ||
863 | } | ||
864 | // How much could we copy without a wrap? | ||
865 | amountToMove = IBUF_SIZE - stripIndex; | ||
866 | |||
867 | if (amountToMove > count) { | ||
868 | amountToMove = count; | ||
869 | } | ||
870 | // Move the first block | ||
871 | pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, | ||
872 | &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); | ||
873 | // If we needed to wrap, do the second data move | ||
874 | if (count > amountToMove) { | ||
875 | pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, | ||
876 | pCh->Ibuf, NULL, count - amountToMove ); | ||
877 | } | ||
878 | // Bump and wrap the stripIndex all at once by the amount of data read. This | ||
879 | // method is good regardless of whether the data was in one or two pieces. | ||
880 | stripIndex += count; | ||
881 | if (stripIndex >= IBUF_SIZE) { | ||
882 | stripIndex -= IBUF_SIZE; | ||
883 | } | ||
884 | pCh->Ibuf_strip = stripIndex; | ||
885 | |||
886 | // Update our flow control information and possibly queue ourselves to send | ||
887 | // it, depending on how much data has been stripped since the last time a | ||
888 | // packet was sent. | ||
889 | pCh->infl.asof += count; | ||
890 | |||
891 | if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) { | ||
892 | pCh->sinceLastFlow -= pCh->whenSendFlow; | ||
893 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
894 | i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); | ||
895 | } else { | ||
896 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
897 | } | ||
898 | |||
899 | i2Input_exit: | ||
900 | |||
901 | ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count); | ||
902 | |||
903 | return count; | ||
904 | } | ||
905 | |||
906 | //****************************************************************************** | ||
907 | // Function: i2InputFlush(pCh) | ||
908 | // Parameters: Pointer to a channel structure | ||
909 | // Returns: Number of bytes stripped, or -1 for error | ||
910 | // | ||
911 | // Description: | ||
912 | // Strips any data from the input buffer. If there is a collosal blunder, | ||
913 | // (invalid structure pointers or the like), returns -1. Otherwise, returns the | ||
914 | // number of bytes stripped. | ||
915 | //****************************************************************************** | ||
916 | static int | ||
917 | i2InputFlush(i2ChanStrPtr pCh) | ||
918 | { | ||
919 | int count; | ||
920 | unsigned long flags; | ||
921 | |||
922 | // Ensure channel structure seems real | ||
923 | if ( !i2Validate ( pCh ) ) | ||
924 | return -1; | ||
925 | |||
926 | ip2trace (CHANN, ITRC_INPUT, 10, 0); | ||
927 | |||
928 | write_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
929 | count = pCh->Ibuf_stuff - pCh->Ibuf_strip; | ||
930 | |||
931 | // Adjust for buffer wrap | ||
932 | if (count < 0) { | ||
933 | count += IBUF_SIZE; | ||
934 | } | ||
935 | |||
936 | // Expedient way to zero out the buffer | ||
937 | pCh->Ibuf_strip = pCh->Ibuf_stuff; | ||
938 | |||
939 | |||
940 | // Update our flow control information and possibly queue ourselves to send | ||
941 | // it, depending on how much data has been stripped since the last time a | ||
942 | // packet was sent. | ||
943 | |||
944 | pCh->infl.asof += count; | ||
945 | |||
946 | if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow ) | ||
947 | { | ||
948 | pCh->sinceLastFlow -= pCh->whenSendFlow; | ||
949 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
950 | i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW); | ||
951 | } else { | ||
952 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
953 | } | ||
954 | |||
955 | ip2trace (CHANN, ITRC_INPUT, 19, 1, count); | ||
956 | |||
957 | return count; | ||
958 | } | ||
959 | |||
960 | //****************************************************************************** | ||
961 | // Function: i2InputAvailable(pCh) | ||
962 | // Parameters: Pointer to a channel structure | ||
963 | // Returns: Number of bytes available, or -1 for error | ||
964 | // | ||
965 | // Description: | ||
966 | // If there is a collosal blunder, (invalid structure pointers or the like), | ||
967 | // returns -1. Otherwise, returns the number of bytes stripped. Otherwise, | ||
968 | // returns the number of bytes available in the buffer. | ||
969 | //****************************************************************************** | ||
970 | #if 0 | ||
971 | static int | ||
972 | i2InputAvailable(i2ChanStrPtr pCh) | ||
973 | { | ||
974 | int count; | ||
975 | |||
976 | // Ensure channel structure seems real | ||
977 | if ( !i2Validate ( pCh ) ) return -1; | ||
978 | |||
979 | |||
980 | // initialize some accelerators and private copies | ||
981 | read_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
982 | count = pCh->Ibuf_stuff - pCh->Ibuf_strip; | ||
983 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
984 | |||
985 | // Adjust for buffer wrap | ||
986 | if (count < 0) | ||
987 | { | ||
988 | count += IBUF_SIZE; | ||
989 | } | ||
990 | |||
991 | return count; | ||
992 | } | ||
993 | #endif | ||
994 | |||
995 | //****************************************************************************** | ||
996 | // Function: i2Output(pCh, pSource, count) | ||
997 | // Parameters: Pointer to channel structure | ||
998 | // Pointer to source data | ||
999 | // Number of bytes to send | ||
1000 | // Returns: Number of bytes sent, or -1 for error | ||
1001 | // | ||
1002 | // Description: | ||
1003 | // Queues the data at pSource to be sent as data packets to the board. If there | ||
1004 | // is a collosal blunder, (invalid structure pointers or the like), returns -1. | ||
1005 | // Otherwise, returns the number of bytes written. What if there is not enough | ||
1006 | // room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then | ||
1007 | // we transfer as many characters as we can now, then return. If this bit is | ||
1008 | // clear (default), routine will spin along until all the data is buffered. | ||
1009 | // Should this occur, the 1-ms delay routine is called while waiting to avoid | ||
1010 | // applications that one cannot break out of. | ||
1011 | //****************************************************************************** | ||
1012 | static int | ||
1013 | i2Output(i2ChanStrPtr pCh, const char *pSource, int count) | ||
1014 | { | ||
1015 | i2eBordStrPtr pB; | ||
1016 | unsigned char *pInsert; | ||
1017 | int amountToMove; | ||
1018 | int countOriginal = count; | ||
1019 | unsigned short channel; | ||
1020 | unsigned short stuffIndex; | ||
1021 | unsigned long flags; | ||
1022 | |||
1023 | int bailout = 10; | ||
1024 | |||
1025 | ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 ); | ||
1026 | |||
1027 | // Ensure channel structure seems real | ||
1028 | if ( !i2Validate ( pCh ) ) | ||
1029 | return -1; | ||
1030 | |||
1031 | // initialize some accelerators and private copies | ||
1032 | pB = pCh->pMyBord; | ||
1033 | channel = pCh->infl.hd.i2sChannel; | ||
1034 | |||
1035 | // If the board has gone fatal, return bad, and also hit the trap routine if | ||
1036 | // it exists. | ||
1037 | if (pB->i2eFatal) { | ||
1038 | if (pB->i2eFatalTrap) { | ||
1039 | (*(pB)->i2eFatalTrap)(pB); | ||
1040 | } | ||
1041 | return -1; | ||
1042 | } | ||
1043 | // Proceed as though we would do everything | ||
1044 | while ( count > 0 ) { | ||
1045 | |||
1046 | // How much room in output buffer is there? | ||
1047 | read_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
1048 | amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; | ||
1049 | read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
1050 | if (amountToMove < 0) { | ||
1051 | amountToMove += OBUF_SIZE; | ||
1052 | } | ||
1053 | // Subtract off the headers size and see how much room there is for real | ||
1054 | // data. If this is negative, we will discover later. | ||
1055 | amountToMove -= sizeof (i2DataHeader); | ||
1056 | |||
1057 | // Don't move more (now) than can go in a single packet | ||
1058 | if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) { | ||
1059 | amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader); | ||
1060 | } | ||
1061 | // Don't move more than the count we were given | ||
1062 | if (amountToMove > count) { | ||
1063 | amountToMove = count; | ||
1064 | } | ||
1065 | // Now we know how much we must move: NB because the ring buffers have | ||
1066 | // an overflow area at the end, we needn't worry about wrapping in the | ||
1067 | // middle of a packet. | ||
1068 | |||
1069 | // Small WINDOW here with no LOCK but I can't call Flush with LOCK | ||
1070 | // We would be flushing (or ending flush) anyway | ||
1071 | |||
1072 | ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove ); | ||
1073 | |||
1074 | if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) | ||
1075 | && amountToMove > 0 ) | ||
1076 | { | ||
1077 | write_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
1078 | stuffIndex = pCh->Obuf_stuff; | ||
1079 | |||
1080 | // Had room to move some data: don't know whether the block size, | ||
1081 | // buffer space, or what was the limiting factor... | ||
1082 | pInsert = &(pCh->Obuf[stuffIndex]); | ||
1083 | |||
1084 | // Set up the header | ||
1085 | CHANNEL_OF(pInsert) = channel; | ||
1086 | PTYPE_OF(pInsert) = PTYPE_DATA; | ||
1087 | TAG_OF(pInsert) = 0; | ||
1088 | ID_OF(pInsert) = ID_ORDINARY_DATA; | ||
1089 | DATA_COUNT_OF(pInsert) = amountToMove; | ||
1090 | |||
1091 | // Move the data | ||
1092 | memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove ); | ||
1093 | // Adjust pointers and indices | ||
1094 | pSource += amountToMove; | ||
1095 | pCh->Obuf_char_count += amountToMove; | ||
1096 | stuffIndex += amountToMove + sizeof(i2DataHeader); | ||
1097 | count -= amountToMove; | ||
1098 | |||
1099 | if (stuffIndex >= OBUF_SIZE) { | ||
1100 | stuffIndex = 0; | ||
1101 | } | ||
1102 | pCh->Obuf_stuff = stuffIndex; | ||
1103 | |||
1104 | write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
1105 | |||
1106 | ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex ); | ||
1107 | |||
1108 | } else { | ||
1109 | |||
1110 | // Cannot move data | ||
1111 | // becuz we need to stuff a flush | ||
1112 | // or amount to move is <= 0 | ||
1113 | |||
1114 | ip2trace(CHANN, ITRC_OUTPUT, 14, 3, | ||
1115 | amountToMove, pB->i2eFifoRemains, | ||
1116 | pB->i2eWaitingForEmptyFifo ); | ||
1117 | |||
1118 | // Put this channel back on queue | ||
1119 | // this ultimatly gets more data or wakes write output | ||
1120 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
1121 | |||
1122 | if ( pB->i2eWaitingForEmptyFifo ) { | ||
1123 | |||
1124 | ip2trace (CHANN, ITRC_OUTPUT, 16, 0 ); | ||
1125 | |||
1126 | // or schedule | ||
1127 | if (!in_interrupt()) { | ||
1128 | |||
1129 | ip2trace (CHANN, ITRC_OUTPUT, 61, 0 ); | ||
1130 | |||
1131 | schedule_timeout_interruptible(2); | ||
1132 | if (signal_pending(current)) { | ||
1133 | break; | ||
1134 | } | ||
1135 | continue; | ||
1136 | } else { | ||
1137 | |||
1138 | ip2trace (CHANN, ITRC_OUTPUT, 62, 0 ); | ||
1139 | |||
1140 | // let interrupt in = WAS restore_flags() | ||
1141 | // We hold no lock nor is irq off anymore??? | ||
1142 | |||
1143 | break; | ||
1144 | } | ||
1145 | break; // from while(count) | ||
1146 | } | ||
1147 | else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) ) | ||
1148 | { | ||
1149 | ip2trace (CHANN, ITRC_OUTPUT, 19, 2, | ||
1150 | pB->i2eFifoRemains, | ||
1151 | pB->i2eTxMailEmpty ); | ||
1152 | |||
1153 | break; // from while(count) | ||
1154 | } else if ( pCh->channelNeeds & NEED_CREDIT ) { | ||
1155 | |||
1156 | ip2trace (CHANN, ITRC_OUTPUT, 22, 0 ); | ||
1157 | |||
1158 | break; // from while(count) | ||
1159 | } else if ( --bailout) { | ||
1160 | |||
1161 | // Try to throw more things (maybe not us) in the fifo if we're | ||
1162 | // not already waiting for it. | ||
1163 | |||
1164 | ip2trace (CHANN, ITRC_OUTPUT, 20, 0 ); | ||
1165 | |||
1166 | serviceOutgoingFifo(pB); | ||
1167 | //break; CONTINUE; | ||
1168 | } else { | ||
1169 | ip2trace (CHANN, ITRC_OUTPUT, 21, 3, | ||
1170 | pB->i2eFifoRemains, | ||
1171 | pB->i2eOutMailWaiting, | ||
1172 | pB->i2eWaitingForEmptyFifo ); | ||
1173 | |||
1174 | break; // from while(count) | ||
1175 | } | ||
1176 | } | ||
1177 | } // End of while(count) | ||
1178 | |||
1179 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
1180 | |||
1181 | // We drop through either when the count expires, or when there is some | ||
1182 | // count left, but there was a non-blocking write. | ||
1183 | if (countOriginal > count) { | ||
1184 | |||
1185 | ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count ); | ||
1186 | |||
1187 | serviceOutgoingFifo( pB ); | ||
1188 | } | ||
1189 | |||
1190 | ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count ); | ||
1191 | |||
1192 | return countOriginal - count; | ||
1193 | } | ||
1194 | |||
1195 | //****************************************************************************** | ||
1196 | // Function: i2FlushOutput(pCh) | ||
1197 | // Parameters: Pointer to a channel structure | ||
1198 | // Returns: Nothing | ||
1199 | // | ||
1200 | // Description: | ||
1201 | // Sends bypass command to start flushing (waiting possibly forever until there | ||
1202 | // is room), then sends inline command to stop flushing output, (again waiting | ||
1203 | // possibly forever). | ||
1204 | //****************************************************************************** | ||
1205 | static inline void | ||
1206 | i2FlushOutput(i2ChanStrPtr pCh) | ||
1207 | { | ||
1208 | |||
1209 | ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags ); | ||
1210 | |||
1211 | if (pCh->flush_flags) | ||
1212 | return; | ||
1213 | |||
1214 | if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { | ||
1215 | pCh->flush_flags = STARTFL_FLAG; // Failed - flag for later | ||
1216 | |||
1217 | ip2trace (CHANN, ITRC_FLUSH, 2, 0 ); | ||
1218 | |||
1219 | } else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) { | ||
1220 | pCh->flush_flags = STOPFL_FLAG; // Failed - flag for later | ||
1221 | |||
1222 | ip2trace (CHANN, ITRC_FLUSH, 3, 0 ); | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | static int | ||
1227 | i2RetryFlushOutput(i2ChanStrPtr pCh) | ||
1228 | { | ||
1229 | int old_flags = pCh->flush_flags; | ||
1230 | |||
1231 | ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags ); | ||
1232 | |||
1233 | pCh->flush_flags = 0; // Clear flag so we can avoid recursion | ||
1234 | // and queue the commands | ||
1235 | |||
1236 | if ( old_flags & STARTFL_FLAG ) { | ||
1237 | if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) { | ||
1238 | old_flags = STOPFL_FLAG; //Success - send stop flush | ||
1239 | } else { | ||
1240 | old_flags = STARTFL_FLAG; //Failure - Flag for retry later | ||
1241 | } | ||
1242 | |||
1243 | ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags ); | ||
1244 | |||
1245 | } | ||
1246 | if ( old_flags & STOPFL_FLAG ) { | ||
1247 | if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) { | ||
1248 | old_flags = 0; // Success - clear flags | ||
1249 | } | ||
1250 | |||
1251 | ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags ); | ||
1252 | } | ||
1253 | pCh->flush_flags = old_flags; | ||
1254 | |||
1255 | ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags ); | ||
1256 | |||
1257 | return old_flags; | ||
1258 | } | ||
1259 | |||
1260 | //****************************************************************************** | ||
1261 | // Function: i2DrainOutput(pCh,timeout) | ||
1262 | // Parameters: Pointer to a channel structure | ||
1263 | // Maximum period to wait | ||
1264 | // Returns: ? | ||
1265 | // | ||
1266 | // Description: | ||
1267 | // Uses the bookmark request command to ask the board to send a bookmark back as | ||
1268 | // soon as all the data is completely sent. | ||
1269 | //****************************************************************************** | ||
1270 | static void | ||
1271 | i2DrainWakeup(unsigned long d) | ||
1272 | { | ||
1273 | i2ChanStrPtr pCh = (i2ChanStrPtr)d; | ||
1274 | |||
1275 | ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires ); | ||
1276 | |||
1277 | pCh->BookmarkTimer.expires = 0; | ||
1278 | wake_up_interruptible( &pCh->pBookmarkWait ); | ||
1279 | } | ||
1280 | |||
1281 | static void | ||
1282 | i2DrainOutput(i2ChanStrPtr pCh, int timeout) | ||
1283 | { | ||
1284 | wait_queue_t wait; | ||
1285 | i2eBordStrPtr pB; | ||
1286 | |||
1287 | ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires); | ||
1288 | |||
1289 | pB = pCh->pMyBord; | ||
1290 | // If the board has gone fatal, return bad, | ||
1291 | // and also hit the trap routine if it exists. | ||
1292 | if (pB->i2eFatal) { | ||
1293 | if (pB->i2eFatalTrap) { | ||
1294 | (*(pB)->i2eFatalTrap)(pB); | ||
1295 | } | ||
1296 | return; | ||
1297 | } | ||
1298 | if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) { | ||
1299 | // One per customer (channel) | ||
1300 | setup_timer(&pCh->BookmarkTimer, i2DrainWakeup, | ||
1301 | (unsigned long)pCh); | ||
1302 | |||
1303 | ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires ); | ||
1304 | |||
1305 | mod_timer(&pCh->BookmarkTimer, jiffies + timeout); | ||
1306 | } | ||
1307 | |||
1308 | i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ ); | ||
1309 | |||
1310 | init_waitqueue_entry(&wait, current); | ||
1311 | add_wait_queue(&(pCh->pBookmarkWait), &wait); | ||
1312 | set_current_state( TASK_INTERRUPTIBLE ); | ||
1313 | |||
1314 | serviceOutgoingFifo( pB ); | ||
1315 | |||
1316 | schedule(); // Now we take our interruptible sleep on | ||
1317 | |||
1318 | // Clean up the queue | ||
1319 | set_current_state( TASK_RUNNING ); | ||
1320 | remove_wait_queue(&(pCh->pBookmarkWait), &wait); | ||
1321 | |||
1322 | // if expires == 0 then timer poped, then do not need to del_timer | ||
1323 | if ((timeout > 0) && pCh->BookmarkTimer.expires && | ||
1324 | time_before(jiffies, pCh->BookmarkTimer.expires)) { | ||
1325 | del_timer( &(pCh->BookmarkTimer) ); | ||
1326 | pCh->BookmarkTimer.expires = 0; | ||
1327 | |||
1328 | ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires ); | ||
1329 | |||
1330 | } | ||
1331 | ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires ); | ||
1332 | return; | ||
1333 | } | ||
1334 | |||
1335 | //****************************************************************************** | ||
1336 | // Function: i2OutputFree(pCh) | ||
1337 | // Parameters: Pointer to a channel structure | ||
1338 | // Returns: Space in output buffer | ||
1339 | // | ||
1340 | // Description: | ||
1341 | // Returns -1 if very gross error. Otherwise returns the amount of bytes still | ||
1342 | // free in the output buffer. | ||
1343 | //****************************************************************************** | ||
1344 | static int | ||
1345 | i2OutputFree(i2ChanStrPtr pCh) | ||
1346 | { | ||
1347 | int amountToMove; | ||
1348 | unsigned long flags; | ||
1349 | |||
1350 | // Ensure channel structure seems real | ||
1351 | if ( !i2Validate ( pCh ) ) { | ||
1352 | return -1; | ||
1353 | } | ||
1354 | read_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
1355 | amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1; | ||
1356 | read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
1357 | |||
1358 | if (amountToMove < 0) { | ||
1359 | amountToMove += OBUF_SIZE; | ||
1360 | } | ||
1361 | // If this is negative, we will discover later | ||
1362 | amountToMove -= sizeof(i2DataHeader); | ||
1363 | |||
1364 | return (amountToMove < 0) ? 0 : amountToMove; | ||
1365 | } | ||
1366 | static void | ||
1367 | |||
1368 | ip2_owake( PTTY tp) | ||
1369 | { | ||
1370 | i2ChanStrPtr pCh; | ||
1371 | |||
1372 | if (tp == NULL) return; | ||
1373 | |||
1374 | pCh = tp->driver_data; | ||
1375 | |||
1376 | ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags, | ||
1377 | (1 << TTY_DO_WRITE_WAKEUP) ); | ||
1378 | |||
1379 | tty_wakeup(tp); | ||
1380 | } | ||
1381 | |||
1382 | static inline void | ||
1383 | set_baud_params(i2eBordStrPtr pB) | ||
1384 | { | ||
1385 | int i,j; | ||
1386 | i2ChanStrPtr *pCh; | ||
1387 | |||
1388 | pCh = (i2ChanStrPtr *) pB->i2eChannelPtr; | ||
1389 | |||
1390 | for (i = 0; i < ABS_MAX_BOXES; i++) { | ||
1391 | if (pB->channelBtypes.bid_value[i]) { | ||
1392 | if (BID_HAS_654(pB->channelBtypes.bid_value[i])) { | ||
1393 | for (j = 0; j < ABS_BIGGEST_BOX; j++) { | ||
1394 | if (pCh[i*16+j] == NULL) | ||
1395 | break; | ||
1396 | (pCh[i*16+j])->BaudBase = 921600; // MAX for ST654 | ||
1397 | (pCh[i*16+j])->BaudDivisor = 96; | ||
1398 | } | ||
1399 | } else { // has cirrus cd1400 | ||
1400 | for (j = 0; j < ABS_BIGGEST_BOX; j++) { | ||
1401 | if (pCh[i*16+j] == NULL) | ||
1402 | break; | ||
1403 | (pCh[i*16+j])->BaudBase = 115200; // MAX for CD1400 | ||
1404 | (pCh[i*16+j])->BaudDivisor = 12; | ||
1405 | } | ||
1406 | } | ||
1407 | } | ||
1408 | } | ||
1409 | } | ||
1410 | |||
1411 | //****************************************************************************** | ||
1412 | // Function: i2StripFifo(pB) | ||
1413 | // Parameters: Pointer to a board structure | ||
1414 | // Returns: ? | ||
1415 | // | ||
1416 | // Description: | ||
1417 | // Strips all the available data from the incoming FIFO, identifies the type of | ||
1418 | // packet, and either buffers the data or does what needs to be done. | ||
1419 | // | ||
1420 | // Note there is no overflow checking here: if the board sends more data than it | ||
1421 | // ought to, we will not detect it here, but blindly overflow... | ||
1422 | //****************************************************************************** | ||
1423 | |||
1424 | // A buffer for reading in blocks for unknown channels | ||
1425 | static unsigned char junkBuffer[IBUF_SIZE]; | ||
1426 | |||
1427 | // A buffer to read in a status packet. Because of the size of the count field | ||
1428 | // for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE | ||
1429 | static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4]; | ||
1430 | |||
1431 | // This table changes the bit order from MSR order given by STAT_MODEM packet to | ||
1432 | // status bits used in our library. | ||
1433 | static char xlatDss[16] = { | ||
1434 | 0 | 0 | 0 | 0 , | ||
1435 | 0 | 0 | 0 | I2_CTS , | ||
1436 | 0 | 0 | I2_DSR | 0 , | ||
1437 | 0 | 0 | I2_DSR | I2_CTS , | ||
1438 | 0 | I2_RI | 0 | 0 , | ||
1439 | 0 | I2_RI | 0 | I2_CTS , | ||
1440 | 0 | I2_RI | I2_DSR | 0 , | ||
1441 | 0 | I2_RI | I2_DSR | I2_CTS , | ||
1442 | I2_DCD | 0 | 0 | 0 , | ||
1443 | I2_DCD | 0 | 0 | I2_CTS , | ||
1444 | I2_DCD | 0 | I2_DSR | 0 , | ||
1445 | I2_DCD | 0 | I2_DSR | I2_CTS , | ||
1446 | I2_DCD | I2_RI | 0 | 0 , | ||
1447 | I2_DCD | I2_RI | 0 | I2_CTS , | ||
1448 | I2_DCD | I2_RI | I2_DSR | 0 , | ||
1449 | I2_DCD | I2_RI | I2_DSR | I2_CTS }; | ||
1450 | |||
1451 | static inline void | ||
1452 | i2StripFifo(i2eBordStrPtr pB) | ||
1453 | { | ||
1454 | i2ChanStrPtr pCh; | ||
1455 | int channel; | ||
1456 | int count; | ||
1457 | unsigned short stuffIndex; | ||
1458 | int amountToRead; | ||
1459 | unsigned char *pc, *pcLimit; | ||
1460 | unsigned char uc; | ||
1461 | unsigned char dss_change; | ||
1462 | unsigned long bflags,cflags; | ||
1463 | |||
1464 | // ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 ); | ||
1465 | |||
1466 | while (I2_HAS_INPUT(pB)) { | ||
1467 | // ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 ); | ||
1468 | |||
1469 | // Process packet from fifo a one atomic unit | ||
1470 | write_lock_irqsave(&pB->read_fifo_spinlock, bflags); | ||
1471 | |||
1472 | // The first word (or two bytes) will have channel number and type of | ||
1473 | // packet, possibly other information | ||
1474 | pB->i2eLeadoffWord[0] = iiReadWord(pB); | ||
1475 | |||
1476 | switch(PTYPE_OF(pB->i2eLeadoffWord)) | ||
1477 | { | ||
1478 | case PTYPE_DATA: | ||
1479 | pB->got_input = 1; | ||
1480 | |||
1481 | // ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 ); | ||
1482 | |||
1483 | channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */ | ||
1484 | count = iiReadWord(pB); /* Count is in the next word */ | ||
1485 | |||
1486 | // NEW: Check the count for sanity! Should the hardware fail, our death | ||
1487 | // is more pleasant. While an oversize channel is acceptable (just more | ||
1488 | // than the driver supports), an over-length count clearly means we are | ||
1489 | // sick! | ||
1490 | if ( ((unsigned int)count) > IBUF_SIZE ) { | ||
1491 | pB->i2eFatal = 2; | ||
1492 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1493 | bflags); | ||
1494 | return; /* Bail out ASAP */ | ||
1495 | } | ||
1496 | // Channel is illegally big ? | ||
1497 | if ((channel >= pB->i2eChannelCnt) || | ||
1498 | (NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel]))) | ||
1499 | { | ||
1500 | iiReadBuf(pB, junkBuffer, count); | ||
1501 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1502 | bflags); | ||
1503 | break; /* From switch: ready for next packet */ | ||
1504 | } | ||
1505 | |||
1506 | // Channel should be valid, then | ||
1507 | |||
1508 | // If this is a hot-key, merely post its receipt for now. These are | ||
1509 | // always supposed to be 1-byte packets, so we won't even check the | ||
1510 | // count. Also we will post an acknowledgement to the board so that | ||
1511 | // more data can be forthcoming. Note that we are not trying to use | ||
1512 | // these sequences in this driver, merely to robustly ignore them. | ||
1513 | if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY) | ||
1514 | { | ||
1515 | pCh->hotKeyIn = iiReadWord(pB) & 0xff; | ||
1516 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1517 | bflags); | ||
1518 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK); | ||
1519 | break; /* From the switch: ready for next packet */ | ||
1520 | } | ||
1521 | |||
1522 | // Normal data! We crudely assume there is room for the data in our | ||
1523 | // buffer because the board wouldn't have exceeded his credit limit. | ||
1524 | write_lock_irqsave(&pCh->Ibuf_spinlock, cflags); | ||
1525 | // We have 2 locks now | ||
1526 | stuffIndex = pCh->Ibuf_stuff; | ||
1527 | amountToRead = IBUF_SIZE - stuffIndex; | ||
1528 | if (amountToRead > count) | ||
1529 | amountToRead = count; | ||
1530 | |||
1531 | // stuffIndex would have been already adjusted so there would | ||
1532 | // always be room for at least one, and count is always at least | ||
1533 | // one. | ||
1534 | |||
1535 | iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); | ||
1536 | pCh->icount.rx += amountToRead; | ||
1537 | |||
1538 | // Update the stuffIndex by the amount of data moved. Note we could | ||
1539 | // never ask for more data than would just fit. However, we might | ||
1540 | // have read in one more byte than we wanted because the read | ||
1541 | // rounds up to even bytes. If this byte is on the end of the | ||
1542 | // packet, and is padding, we ignore it. If the byte is part of | ||
1543 | // the actual data, we need to move it. | ||
1544 | |||
1545 | stuffIndex += amountToRead; | ||
1546 | |||
1547 | if (stuffIndex >= IBUF_SIZE) { | ||
1548 | if ((amountToRead & 1) && (count > amountToRead)) { | ||
1549 | pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE]; | ||
1550 | amountToRead++; | ||
1551 | stuffIndex = 1; | ||
1552 | } else { | ||
1553 | stuffIndex = 0; | ||
1554 | } | ||
1555 | } | ||
1556 | |||
1557 | // If there is anything left over, read it as well | ||
1558 | if (count > amountToRead) { | ||
1559 | amountToRead = count - amountToRead; | ||
1560 | iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead); | ||
1561 | pCh->icount.rx += amountToRead; | ||
1562 | stuffIndex += amountToRead; | ||
1563 | } | ||
1564 | |||
1565 | // Update stuff index | ||
1566 | pCh->Ibuf_stuff = stuffIndex; | ||
1567 | write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags); | ||
1568 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1569 | bflags); | ||
1570 | |||
1571 | #ifdef USE_IQ | ||
1572 | schedule_work(&pCh->tqueue_input); | ||
1573 | #else | ||
1574 | do_input(&pCh->tqueue_input); | ||
1575 | #endif | ||
1576 | |||
1577 | // Note we do not need to maintain any flow-control credits at this | ||
1578 | // time: if we were to increment .asof and decrement .room, there | ||
1579 | // would be no net effect. Instead, when we strip data, we will | ||
1580 | // increment .asof and leave .room unchanged. | ||
1581 | |||
1582 | break; // From switch: ready for next packet | ||
1583 | |||
1584 | case PTYPE_STATUS: | ||
1585 | ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 ); | ||
1586 | |||
1587 | count = CMD_COUNT_OF(pB->i2eLeadoffWord); | ||
1588 | |||
1589 | iiReadBuf(pB, cmdBuffer, count); | ||
1590 | // We can release early with buffer grab | ||
1591 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1592 | bflags); | ||
1593 | |||
1594 | pc = cmdBuffer; | ||
1595 | pcLimit = &(cmdBuffer[count]); | ||
1596 | |||
1597 | while (pc < pcLimit) { | ||
1598 | channel = *pc++; | ||
1599 | |||
1600 | ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc ); | ||
1601 | |||
1602 | /* check for valid channel */ | ||
1603 | if (channel < pB->i2eChannelCnt | ||
1604 | && | ||
1605 | (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL | ||
1606 | ) | ||
1607 | { | ||
1608 | dss_change = 0; | ||
1609 | |||
1610 | switch (uc = *pc++) | ||
1611 | { | ||
1612 | /* Breaks and modem signals are easy: just update status */ | ||
1613 | case STAT_CTS_UP: | ||
1614 | if ( !(pCh->dataSetIn & I2_CTS) ) | ||
1615 | { | ||
1616 | pCh->dataSetIn |= I2_DCTS; | ||
1617 | pCh->icount.cts++; | ||
1618 | dss_change = 1; | ||
1619 | } | ||
1620 | pCh->dataSetIn |= I2_CTS; | ||
1621 | break; | ||
1622 | |||
1623 | case STAT_CTS_DN: | ||
1624 | if ( pCh->dataSetIn & I2_CTS ) | ||
1625 | { | ||
1626 | pCh->dataSetIn |= I2_DCTS; | ||
1627 | pCh->icount.cts++; | ||
1628 | dss_change = 1; | ||
1629 | } | ||
1630 | pCh->dataSetIn &= ~I2_CTS; | ||
1631 | break; | ||
1632 | |||
1633 | case STAT_DCD_UP: | ||
1634 | ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn ); | ||
1635 | |||
1636 | if ( !(pCh->dataSetIn & I2_DCD) ) | ||
1637 | { | ||
1638 | ip2trace (CHANN, ITRC_MODEM, 2, 0 ); | ||
1639 | pCh->dataSetIn |= I2_DDCD; | ||
1640 | pCh->icount.dcd++; | ||
1641 | dss_change = 1; | ||
1642 | } | ||
1643 | pCh->dataSetIn |= I2_DCD; | ||
1644 | |||
1645 | ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn ); | ||
1646 | break; | ||
1647 | |||
1648 | case STAT_DCD_DN: | ||
1649 | ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn ); | ||
1650 | if ( pCh->dataSetIn & I2_DCD ) | ||
1651 | { | ||
1652 | ip2trace (channel, ITRC_MODEM, 5, 0 ); | ||
1653 | pCh->dataSetIn |= I2_DDCD; | ||
1654 | pCh->icount.dcd++; | ||
1655 | dss_change = 1; | ||
1656 | } | ||
1657 | pCh->dataSetIn &= ~I2_DCD; | ||
1658 | |||
1659 | ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn ); | ||
1660 | break; | ||
1661 | |||
1662 | case STAT_DSR_UP: | ||
1663 | if ( !(pCh->dataSetIn & I2_DSR) ) | ||
1664 | { | ||
1665 | pCh->dataSetIn |= I2_DDSR; | ||
1666 | pCh->icount.dsr++; | ||
1667 | dss_change = 1; | ||
1668 | } | ||
1669 | pCh->dataSetIn |= I2_DSR; | ||
1670 | break; | ||
1671 | |||
1672 | case STAT_DSR_DN: | ||
1673 | if ( pCh->dataSetIn & I2_DSR ) | ||
1674 | { | ||
1675 | pCh->dataSetIn |= I2_DDSR; | ||
1676 | pCh->icount.dsr++; | ||
1677 | dss_change = 1; | ||
1678 | } | ||
1679 | pCh->dataSetIn &= ~I2_DSR; | ||
1680 | break; | ||
1681 | |||
1682 | case STAT_RI_UP: | ||
1683 | if ( !(pCh->dataSetIn & I2_RI) ) | ||
1684 | { | ||
1685 | pCh->dataSetIn |= I2_DRI; | ||
1686 | pCh->icount.rng++; | ||
1687 | dss_change = 1; | ||
1688 | } | ||
1689 | pCh->dataSetIn |= I2_RI ; | ||
1690 | break; | ||
1691 | |||
1692 | case STAT_RI_DN: | ||
1693 | // to be compat with serial.c | ||
1694 | //if ( pCh->dataSetIn & I2_RI ) | ||
1695 | //{ | ||
1696 | // pCh->dataSetIn |= I2_DRI; | ||
1697 | // pCh->icount.rng++; | ||
1698 | // dss_change = 1; | ||
1699 | //} | ||
1700 | pCh->dataSetIn &= ~I2_RI ; | ||
1701 | break; | ||
1702 | |||
1703 | case STAT_BRK_DET: | ||
1704 | pCh->dataSetIn |= I2_BRK; | ||
1705 | pCh->icount.brk++; | ||
1706 | dss_change = 1; | ||
1707 | break; | ||
1708 | |||
1709 | // Bookmarks? one less request we're waiting for | ||
1710 | case STAT_BMARK: | ||
1711 | pCh->bookMarks--; | ||
1712 | if (pCh->bookMarks <= 0 ) { | ||
1713 | pCh->bookMarks = 0; | ||
1714 | wake_up_interruptible( &pCh->pBookmarkWait ); | ||
1715 | |||
1716 | ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires ); | ||
1717 | } | ||
1718 | break; | ||
1719 | |||
1720 | // Flow control packets? Update the new credits, and if | ||
1721 | // someone was waiting for output, queue him up again. | ||
1722 | case STAT_FLOW: | ||
1723 | pCh->outfl.room = | ||
1724 | ((flowStatPtr)pc)->room - | ||
1725 | (pCh->outfl.asof - ((flowStatPtr)pc)->asof); | ||
1726 | |||
1727 | ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room ); | ||
1728 | |||
1729 | if (pCh->channelNeeds & NEED_CREDIT) | ||
1730 | { | ||
1731 | ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds); | ||
1732 | |||
1733 | pCh->channelNeeds &= ~NEED_CREDIT; | ||
1734 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
1735 | if ( pCh->pTTY ) | ||
1736 | ip2_owake(pCh->pTTY); | ||
1737 | } | ||
1738 | |||
1739 | ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds); | ||
1740 | |||
1741 | pc += sizeof(flowStat); | ||
1742 | break; | ||
1743 | |||
1744 | /* Special packets: */ | ||
1745 | /* Just copy the information into the channel structure */ | ||
1746 | |||
1747 | case STAT_STATUS: | ||
1748 | |||
1749 | pCh->channelStatus = *((debugStatPtr)pc); | ||
1750 | pc += sizeof(debugStat); | ||
1751 | break; | ||
1752 | |||
1753 | case STAT_TXCNT: | ||
1754 | |||
1755 | pCh->channelTcount = *((cntStatPtr)pc); | ||
1756 | pc += sizeof(cntStat); | ||
1757 | break; | ||
1758 | |||
1759 | case STAT_RXCNT: | ||
1760 | |||
1761 | pCh->channelRcount = *((cntStatPtr)pc); | ||
1762 | pc += sizeof(cntStat); | ||
1763 | break; | ||
1764 | |||
1765 | case STAT_BOXIDS: | ||
1766 | pB->channelBtypes = *((bidStatPtr)pc); | ||
1767 | pc += sizeof(bidStat); | ||
1768 | set_baud_params(pB); | ||
1769 | break; | ||
1770 | |||
1771 | case STAT_HWFAIL: | ||
1772 | i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST); | ||
1773 | pCh->channelFail = *((failStatPtr)pc); | ||
1774 | pc += sizeof(failStat); | ||
1775 | break; | ||
1776 | |||
1777 | /* No explicit match? then | ||
1778 | * Might be an error packet... | ||
1779 | */ | ||
1780 | default: | ||
1781 | switch (uc & STAT_MOD_ERROR) | ||
1782 | { | ||
1783 | case STAT_ERROR: | ||
1784 | if (uc & STAT_E_PARITY) { | ||
1785 | pCh->dataSetIn |= I2_PAR; | ||
1786 | pCh->icount.parity++; | ||
1787 | } | ||
1788 | if (uc & STAT_E_FRAMING){ | ||
1789 | pCh->dataSetIn |= I2_FRA; | ||
1790 | pCh->icount.frame++; | ||
1791 | } | ||
1792 | if (uc & STAT_E_OVERRUN){ | ||
1793 | pCh->dataSetIn |= I2_OVR; | ||
1794 | pCh->icount.overrun++; | ||
1795 | } | ||
1796 | break; | ||
1797 | |||
1798 | case STAT_MODEM: | ||
1799 | // the answer to DSS_NOW request (not change) | ||
1800 | pCh->dataSetIn = (pCh->dataSetIn | ||
1801 | & ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) ) | ||
1802 | | xlatDss[uc & 0xf]; | ||
1803 | wake_up_interruptible ( &pCh->dss_now_wait ); | ||
1804 | default: | ||
1805 | break; | ||
1806 | } | ||
1807 | } /* End of switch on status type */ | ||
1808 | if (dss_change) { | ||
1809 | #ifdef USE_IQ | ||
1810 | schedule_work(&pCh->tqueue_status); | ||
1811 | #else | ||
1812 | do_status(&pCh->tqueue_status); | ||
1813 | #endif | ||
1814 | } | ||
1815 | } | ||
1816 | else /* Or else, channel is invalid */ | ||
1817 | { | ||
1818 | // Even though the channel is invalid, we must test the | ||
1819 | // status to see how much additional data it has (to be | ||
1820 | // skipped) | ||
1821 | switch (*pc++) | ||
1822 | { | ||
1823 | case STAT_FLOW: | ||
1824 | pc += 4; /* Skip the data */ | ||
1825 | break; | ||
1826 | |||
1827 | default: | ||
1828 | break; | ||
1829 | } | ||
1830 | } | ||
1831 | } // End of while (there is still some status packet left) | ||
1832 | break; | ||
1833 | |||
1834 | default: // Neither packet? should be impossible | ||
1835 | ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1, | ||
1836 | PTYPE_OF(pB->i2eLeadoffWord) ); | ||
1837 | write_unlock_irqrestore(&pB->read_fifo_spinlock, | ||
1838 | bflags); | ||
1839 | |||
1840 | break; | ||
1841 | } // End of switch on type of packets | ||
1842 | } /*while(board I2_HAS_INPUT)*/ | ||
1843 | |||
1844 | ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 ); | ||
1845 | |||
1846 | // Send acknowledgement to the board even if there was no data! | ||
1847 | pB->i2eOutMailWaiting |= MB_IN_STRIPPED; | ||
1848 | return; | ||
1849 | } | ||
1850 | |||
1851 | //****************************************************************************** | ||
1852 | // Function: i2Write2Fifo(pB,address,count) | ||
1853 | // Parameters: Pointer to a board structure, source address, byte count | ||
1854 | // Returns: bytes written | ||
1855 | // | ||
1856 | // Description: | ||
1857 | // Writes count bytes to board io address(implied) from source | ||
1858 | // Adjusts count, leaves reserve for next time around bypass cmds | ||
1859 | //****************************************************************************** | ||
1860 | static int | ||
1861 | i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve) | ||
1862 | { | ||
1863 | int rc = 0; | ||
1864 | unsigned long flags; | ||
1865 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
1866 | if (!pB->i2eWaitingForEmptyFifo) { | ||
1867 | if (pB->i2eFifoRemains > (count+reserve)) { | ||
1868 | pB->i2eFifoRemains -= count; | ||
1869 | iiWriteBuf(pB, source, count); | ||
1870 | pB->i2eOutMailWaiting |= MB_OUT_STUFFED; | ||
1871 | rc = count; | ||
1872 | } | ||
1873 | } | ||
1874 | write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); | ||
1875 | return rc; | ||
1876 | } | ||
1877 | //****************************************************************************** | ||
1878 | // Function: i2StuffFifoBypass(pB) | ||
1879 | // Parameters: Pointer to a board structure | ||
1880 | // Returns: Nothing | ||
1881 | // | ||
1882 | // Description: | ||
1883 | // Stuffs as many bypass commands into the fifo as possible. This is simpler | ||
1884 | // than stuffing data or inline commands to fifo, since we do not have | ||
1885 | // flow-control to deal with. | ||
1886 | //****************************************************************************** | ||
1887 | static inline void | ||
1888 | i2StuffFifoBypass(i2eBordStrPtr pB) | ||
1889 | { | ||
1890 | i2ChanStrPtr pCh; | ||
1891 | unsigned char *pRemove; | ||
1892 | unsigned short stripIndex; | ||
1893 | unsigned short packetSize; | ||
1894 | unsigned short paddedSize; | ||
1895 | unsigned short notClogged = 1; | ||
1896 | unsigned long flags; | ||
1897 | |||
1898 | int bailout = 1000; | ||
1899 | |||
1900 | // Continue processing so long as there are entries, or there is room in the | ||
1901 | // fifo. Each entry represents a channel with something to do. | ||
1902 | while ( --bailout && notClogged && | ||
1903 | (NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS)))) | ||
1904 | { | ||
1905 | write_lock_irqsave(&pCh->Cbuf_spinlock, flags); | ||
1906 | stripIndex = pCh->Cbuf_strip; | ||
1907 | |||
1908 | // as long as there are packets for this channel... | ||
1909 | |||
1910 | while (stripIndex != pCh->Cbuf_stuff) { | ||
1911 | pRemove = &(pCh->Cbuf[stripIndex]); | ||
1912 | packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader); | ||
1913 | paddedSize = roundup(packetSize, 2); | ||
1914 | |||
1915 | if (paddedSize > 0) { | ||
1916 | if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) { | ||
1917 | notClogged = 0; /* fifo full */ | ||
1918 | i2QueueNeeds(pB, pCh, NEED_BYPASS); // Put back on queue | ||
1919 | break; // Break from the channel | ||
1920 | } | ||
1921 | } | ||
1922 | #ifdef DEBUG_FIFO | ||
1923 | WriteDBGBuf("BYPS", pRemove, paddedSize); | ||
1924 | #endif /* DEBUG_FIFO */ | ||
1925 | pB->debugBypassCount++; | ||
1926 | |||
1927 | pRemove += packetSize; | ||
1928 | stripIndex += packetSize; | ||
1929 | if (stripIndex >= CBUF_SIZE) { | ||
1930 | stripIndex = 0; | ||
1931 | pRemove = pCh->Cbuf; | ||
1932 | } | ||
1933 | } | ||
1934 | // Done with this channel. Move to next, removing this one from | ||
1935 | // the queue of channels if we cleaned it out (i.e., didn't get clogged. | ||
1936 | pCh->Cbuf_strip = stripIndex; | ||
1937 | write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags); | ||
1938 | } // Either clogged or finished all the work | ||
1939 | |||
1940 | #ifdef IP2DEBUG_TRACE | ||
1941 | if ( !bailout ) { | ||
1942 | ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 ); | ||
1943 | } | ||
1944 | #endif | ||
1945 | } | ||
1946 | |||
1947 | //****************************************************************************** | ||
1948 | // Function: i2StuffFifoFlow(pB) | ||
1949 | // Parameters: Pointer to a board structure | ||
1950 | // Returns: Nothing | ||
1951 | // | ||
1952 | // Description: | ||
1953 | // Stuffs as many flow control packets into the fifo as possible. This is easier | ||
1954 | // even than doing normal bypass commands, because there is always at most one | ||
1955 | // packet, already assembled, for each channel. | ||
1956 | //****************************************************************************** | ||
1957 | static inline void | ||
1958 | i2StuffFifoFlow(i2eBordStrPtr pB) | ||
1959 | { | ||
1960 | i2ChanStrPtr pCh; | ||
1961 | unsigned short paddedSize = roundup(sizeof(flowIn), 2); | ||
1962 | |||
1963 | ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2, | ||
1964 | pB->i2eFifoRemains, paddedSize ); | ||
1965 | |||
1966 | // Continue processing so long as there are entries, or there is room in the | ||
1967 | // fifo. Each entry represents a channel with something to do. | ||
1968 | while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) { | ||
1969 | pB->debugFlowCount++; | ||
1970 | |||
1971 | // NO Chan LOCK needed ??? | ||
1972 | if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) { | ||
1973 | break; | ||
1974 | } | ||
1975 | #ifdef DEBUG_FIFO | ||
1976 | WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize); | ||
1977 | #endif /* DEBUG_FIFO */ | ||
1978 | |||
1979 | } // Either clogged or finished all the work | ||
1980 | |||
1981 | ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 ); | ||
1982 | } | ||
1983 | |||
1984 | //****************************************************************************** | ||
1985 | // Function: i2StuffFifoInline(pB) | ||
1986 | // Parameters: Pointer to a board structure | ||
1987 | // Returns: Nothing | ||
1988 | // | ||
1989 | // Description: | ||
1990 | // Stuffs as much data and inline commands into the fifo as possible. This is | ||
1991 | // the most complex fifo-stuffing operation, since there if now the channel | ||
1992 | // flow-control issue to deal with. | ||
1993 | //****************************************************************************** | ||
1994 | static inline void | ||
1995 | i2StuffFifoInline(i2eBordStrPtr pB) | ||
1996 | { | ||
1997 | i2ChanStrPtr pCh; | ||
1998 | unsigned char *pRemove; | ||
1999 | unsigned short stripIndex; | ||
2000 | unsigned short packetSize; | ||
2001 | unsigned short paddedSize; | ||
2002 | unsigned short notClogged = 1; | ||
2003 | unsigned short flowsize; | ||
2004 | unsigned long flags; | ||
2005 | |||
2006 | int bailout = 1000; | ||
2007 | int bailout2; | ||
2008 | |||
2009 | ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, | ||
2010 | pB->i2Dbuf_strip, pB->i2Dbuf_stuff ); | ||
2011 | |||
2012 | // Continue processing so long as there are entries, or there is room in the | ||
2013 | // fifo. Each entry represents a channel with something to do. | ||
2014 | while ( --bailout && notClogged && | ||
2015 | (NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) ) | ||
2016 | { | ||
2017 | write_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
2018 | stripIndex = pCh->Obuf_strip; | ||
2019 | |||
2020 | ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff ); | ||
2021 | |||
2022 | // as long as there are packets for this channel... | ||
2023 | bailout2 = 1000; | ||
2024 | while ( --bailout2 && stripIndex != pCh->Obuf_stuff) { | ||
2025 | pRemove = &(pCh->Obuf[stripIndex]); | ||
2026 | |||
2027 | // Must determine whether this be a data or command packet to | ||
2028 | // calculate correctly the header size and the amount of | ||
2029 | // flow-control credit this type of packet will use. | ||
2030 | if (PTYPE_OF(pRemove) == PTYPE_DATA) { | ||
2031 | flowsize = DATA_COUNT_OF(pRemove); | ||
2032 | packetSize = flowsize + sizeof(i2DataHeader); | ||
2033 | } else { | ||
2034 | flowsize = CMD_COUNT_OF(pRemove); | ||
2035 | packetSize = flowsize + sizeof(i2CmdHeader); | ||
2036 | } | ||
2037 | flowsize = CREDIT_USAGE(flowsize); | ||
2038 | paddedSize = roundup(packetSize, 2); | ||
2039 | |||
2040 | ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize ); | ||
2041 | |||
2042 | // If we don't have enough credits from the board to send the data, | ||
2043 | // flag the channel that we are waiting for flow control credit, and | ||
2044 | // break out. This will clean up this channel and remove us from the | ||
2045 | // queue of hot things to do. | ||
2046 | |||
2047 | ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize ); | ||
2048 | |||
2049 | if (pCh->outfl.room <= flowsize) { | ||
2050 | // Do Not have the credits to send this packet. | ||
2051 | i2QueueNeeds(pB, pCh, NEED_CREDIT); | ||
2052 | notClogged = 0; | ||
2053 | break; // So to do next channel | ||
2054 | } | ||
2055 | if ( (paddedSize > 0) | ||
2056 | && ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) { | ||
2057 | // Do Not have room in fifo to send this packet. | ||
2058 | notClogged = 0; | ||
2059 | i2QueueNeeds(pB, pCh, NEED_INLINE); | ||
2060 | break; // Break from the channel | ||
2061 | } | ||
2062 | #ifdef DEBUG_FIFO | ||
2063 | WriteDBGBuf("DATA", pRemove, paddedSize); | ||
2064 | #endif /* DEBUG_FIFO */ | ||
2065 | pB->debugInlineCount++; | ||
2066 | |||
2067 | pCh->icount.tx += flowsize; | ||
2068 | // Update current credits | ||
2069 | pCh->outfl.room -= flowsize; | ||
2070 | pCh->outfl.asof += flowsize; | ||
2071 | if (PTYPE_OF(pRemove) == PTYPE_DATA) { | ||
2072 | pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove); | ||
2073 | } | ||
2074 | pRemove += packetSize; | ||
2075 | stripIndex += packetSize; | ||
2076 | |||
2077 | ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip); | ||
2078 | |||
2079 | if (stripIndex >= OBUF_SIZE) { | ||
2080 | stripIndex = 0; | ||
2081 | pRemove = pCh->Obuf; | ||
2082 | |||
2083 | ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex ); | ||
2084 | |||
2085 | } | ||
2086 | } /* while */ | ||
2087 | if ( !bailout2 ) { | ||
2088 | ip2trace (CHANN, ITRC_ERROR, 3, 0 ); | ||
2089 | } | ||
2090 | // Done with this channel. Move to next, removing this one from the | ||
2091 | // queue of channels if we cleaned it out (i.e., didn't get clogged. | ||
2092 | pCh->Obuf_strip = stripIndex; | ||
2093 | write_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
2094 | if ( notClogged ) | ||
2095 | { | ||
2096 | |||
2097 | ip2trace (CHANN, ITRC_SICMD, 8, 0 ); | ||
2098 | |||
2099 | if ( pCh->pTTY ) { | ||
2100 | ip2_owake(pCh->pTTY); | ||
2101 | } | ||
2102 | } | ||
2103 | } // Either clogged or finished all the work | ||
2104 | |||
2105 | if ( !bailout ) { | ||
2106 | ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 ); | ||
2107 | } | ||
2108 | |||
2109 | ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip); | ||
2110 | } | ||
2111 | |||
2112 | //****************************************************************************** | ||
2113 | // Function: serviceOutgoingFifo(pB) | ||
2114 | // Parameters: Pointer to a board structure | ||
2115 | // Returns: Nothing | ||
2116 | // | ||
2117 | // Description: | ||
2118 | // Helper routine to put data in the outgoing fifo, if we aren't already waiting | ||
2119 | // for something to be there. If the fifo has only room for a very little data, | ||
2120 | // go head and hit the board with a mailbox hit immediately. Otherwise, it will | ||
2121 | // have to happen later in the interrupt processing. Since this routine may be | ||
2122 | // called both at interrupt and foreground time, we must turn off interrupts | ||
2123 | // during the entire process. | ||
2124 | //****************************************************************************** | ||
2125 | static void | ||
2126 | serviceOutgoingFifo(i2eBordStrPtr pB) | ||
2127 | { | ||
2128 | // If we aren't currently waiting for the board to empty our fifo, service | ||
2129 | // everything that is pending, in priority order (especially, Bypass before | ||
2130 | // Inline). | ||
2131 | if ( ! pB->i2eWaitingForEmptyFifo ) | ||
2132 | { | ||
2133 | i2StuffFifoFlow(pB); | ||
2134 | i2StuffFifoBypass(pB); | ||
2135 | i2StuffFifoInline(pB); | ||
2136 | |||
2137 | iiSendPendingMail(pB); | ||
2138 | } | ||
2139 | } | ||
2140 | |||
2141 | //****************************************************************************** | ||
2142 | // Function: i2ServiceBoard(pB) | ||
2143 | // Parameters: Pointer to a board structure | ||
2144 | // Returns: Nothing | ||
2145 | // | ||
2146 | // Description: | ||
2147 | // Normally this is called from interrupt level, but there is deliberately | ||
2148 | // nothing in here specific to being called from interrupt level. All the | ||
2149 | // hardware-specific, interrupt-specific things happen at the outer levels. | ||
2150 | // | ||
2151 | // For example, a timer interrupt could drive this routine for some sort of | ||
2152 | // polled operation. The only requirement is that the programmer deal with any | ||
2153 | // atomiticity/concurrency issues that result. | ||
2154 | // | ||
2155 | // This routine responds to the board's having sent mailbox information to the | ||
2156 | // host (which would normally cause an interrupt). This routine reads the | ||
2157 | // incoming mailbox. If there is no data in it, this board did not create the | ||
2158 | // interrupt and/or has nothing to be done to it. (Except, if we have been | ||
2159 | // waiting to write mailbox data to it, we may do so. | ||
2160 | // | ||
2161 | // Based on the value in the mailbox, we may take various actions. | ||
2162 | // | ||
2163 | // No checking here of pB validity: after all, it shouldn't have been called by | ||
2164 | // the handler unless pB were on the list. | ||
2165 | //****************************************************************************** | ||
2166 | static inline int | ||
2167 | i2ServiceBoard ( i2eBordStrPtr pB ) | ||
2168 | { | ||
2169 | unsigned inmail; | ||
2170 | unsigned long flags; | ||
2171 | |||
2172 | |||
2173 | /* This should be atomic because of the way we are called... */ | ||
2174 | if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) { | ||
2175 | inmail = iiGetMail(pB); | ||
2176 | } | ||
2177 | pB->i2eStartMail = NO_MAIL_HERE; | ||
2178 | |||
2179 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail ); | ||
2180 | |||
2181 | if (inmail != NO_MAIL_HERE) { | ||
2182 | // If the board has gone fatal, nothing to do but hit a bit that will | ||
2183 | // alert foreground tasks to protest! | ||
2184 | if ( inmail & MB_FATAL_ERROR ) { | ||
2185 | pB->i2eFatal = 1; | ||
2186 | goto exit_i2ServiceBoard; | ||
2187 | } | ||
2188 | |||
2189 | /* Assuming no fatal condition, we proceed to do work */ | ||
2190 | if ( inmail & MB_IN_STUFFED ) { | ||
2191 | pB->i2eFifoInInts++; | ||
2192 | i2StripFifo(pB); /* There might be incoming packets */ | ||
2193 | } | ||
2194 | |||
2195 | if (inmail & MB_OUT_STRIPPED) { | ||
2196 | pB->i2eFifoOutInts++; | ||
2197 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
2198 | pB->i2eFifoRemains = pB->i2eFifoSize; | ||
2199 | pB->i2eWaitingForEmptyFifo = 0; | ||
2200 | write_unlock_irqrestore(&pB->write_fifo_spinlock, | ||
2201 | flags); | ||
2202 | |||
2203 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains ); | ||
2204 | |||
2205 | } | ||
2206 | serviceOutgoingFifo(pB); | ||
2207 | } | ||
2208 | |||
2209 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 ); | ||
2210 | |||
2211 | exit_i2ServiceBoard: | ||
2212 | |||
2213 | return 0; | ||
2214 | } | ||
diff --git a/drivers/char/ip2/i2lib.h b/drivers/char/ip2/i2lib.h deleted file mode 100644 index e559e9bac06d..000000000000 --- a/drivers/char/ip2/i2lib.h +++ /dev/null | |||
@@ -1,351 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Header file for high level library functions | ||
12 | * | ||
13 | *******************************************************************************/ | ||
14 | #ifndef I2LIB_H | ||
15 | #define I2LIB_H 1 | ||
16 | //------------------------------------------------------------------------------ | ||
17 | // I2LIB.H | ||
18 | // | ||
19 | // IntelliPort-II and IntelliPort-IIEX | ||
20 | // | ||
21 | // Defines, structure definitions, and external declarations for i2lib.c | ||
22 | //------------------------------------------------------------------------------ | ||
23 | //-------------------------------------- | ||
24 | // Mandatory Includes: | ||
25 | //-------------------------------------- | ||
26 | #include "ip2types.h" | ||
27 | #include "i2ellis.h" | ||
28 | #include "i2pack.h" | ||
29 | #include "i2cmd.h" | ||
30 | #include <linux/workqueue.h> | ||
31 | |||
32 | //------------------------------------------------------------------------------ | ||
33 | // i2ChanStr -- Channel Structure: | ||
34 | // Used to track per-channel information for the library routines using standard | ||
35 | // loadware. Note also, a pointer to an array of these structures is patched | ||
36 | // into the i2eBordStr (see i2ellis.h) | ||
37 | //------------------------------------------------------------------------------ | ||
38 | // | ||
39 | // If we make some limits on the maximum block sizes, we can avoid dealing with | ||
40 | // buffer wrap. The wrapping of the buffer is based on where the start of the | ||
41 | // packet is. Then there is always room for the packet contiguously. | ||
42 | // | ||
43 | // Maximum total length of an outgoing data or in-line command block. The limit | ||
44 | // of 36 on data is quite arbitrary and based more on DOS memory limitations | ||
45 | // than the board interface. However, for commands, the maximum packet length is | ||
46 | // MAX_CMD_PACK_SIZE, because the field size for the count is only a few bits | ||
47 | // (see I2PACK.H) in such packets. For data packets, the count field size is not | ||
48 | // the limiting factor. As of this writing, MAX_OBUF_BLOCK < MAX_CMD_PACK_SIZE, | ||
49 | // but be careful if wanting to modify either. | ||
50 | // | ||
51 | #define MAX_OBUF_BLOCK 36 | ||
52 | |||
53 | // Another note on maximum block sizes: we are buffering packets here. Data is | ||
54 | // put into the buffer (if there is room) regardless of the credits from the | ||
55 | // board. The board sends new credits whenever it has removed from his buffers a | ||
56 | // number of characters equal to 80% of total buffer size. (Of course, the total | ||
57 | // buffer size is what is reported when the very first set of flow control | ||
58 | // status packets are received from the board. Therefore, to be robust, you must | ||
59 | // always fill the board to at least 80% of the current credit limit, else you | ||
60 | // might not give it enough to trigger a new report. These conditions are | ||
61 | // obtained here so long as the maximum output block size is less than 20% the | ||
62 | // size of the board's output buffers. This is true at present by "coincidence" | ||
63 | // or "infernal knowledge": the board's output buffers are at least 700 bytes | ||
64 | // long (20% = 140 bytes, at least). The 80% figure is "official", so the safest | ||
65 | // strategy might be to trap the first flow control report and guarantee that | ||
66 | // the effective maxObufBlock is the minimum of MAX_OBUF_BLOCK and 20% of first | ||
67 | // reported buffer credit. | ||
68 | // | ||
69 | #define MAX_CBUF_BLOCK 6 // Maximum total length of a bypass command block | ||
70 | |||
71 | #define IBUF_SIZE 512 // character capacity of input buffer per channel | ||
72 | #define OBUF_SIZE 1024// character capacity of output buffer per channel | ||
73 | #define CBUF_SIZE 10 // character capacity of output bypass buffer | ||
74 | |||
75 | typedef struct _i2ChanStr | ||
76 | { | ||
77 | // First, back-pointers so that given a pointer to this structure, you can | ||
78 | // determine the correct board and channel number to reference, (say, when | ||
79 | // issuing commands, etc. (Note, channel number is in infl.hd.i2sChannel.) | ||
80 | |||
81 | int port_index; // Index of port in channel structure array attached | ||
82 | // to board structure. | ||
83 | PTTY pTTY; // Pointer to tty structure for port (OS specific) | ||
84 | USHORT validity; // Indicates whether the given channel has been | ||
85 | // initialized, really exists (or is a missing | ||
86 | // channel, e.g. channel 9 on an 8-port box.) | ||
87 | |||
88 | i2eBordStrPtr pMyBord; // Back-pointer to this channel's board structure | ||
89 | |||
90 | int wopen; // waiting fer carrier | ||
91 | |||
92 | int throttled; // Set if upper layer can take no data | ||
93 | |||
94 | int flags; // Defined in tty.h | ||
95 | |||
96 | PWAITQ open_wait; // Pointer for OS sleep function. | ||
97 | PWAITQ close_wait; // Pointer for OS sleep function. | ||
98 | PWAITQ delta_msr_wait;// Pointer for OS sleep function. | ||
99 | PWAITQ dss_now_wait; // Pointer for OS sleep function. | ||
100 | |||
101 | struct timer_list BookmarkTimer; // Used by i2DrainOutput | ||
102 | wait_queue_head_t pBookmarkWait; // Used by i2DrainOutput | ||
103 | |||
104 | int BaudBase; | ||
105 | int BaudDivisor; | ||
106 | |||
107 | USHORT ClosingDelay; | ||
108 | USHORT ClosingWaitTime; | ||
109 | |||
110 | volatile | ||
111 | flowIn infl; // This structure is initialized as a completely | ||
112 | // formed flow-control command packet, and as such | ||
113 | // has the channel number, also the capacity and | ||
114 | // "as-of" data needed continuously. | ||
115 | |||
116 | USHORT sinceLastFlow; // Counts the number of characters read from input | ||
117 | // buffers, since the last time flow control info | ||
118 | // was sent. | ||
119 | |||
120 | USHORT whenSendFlow; // Determines when new flow control is to be sent to | ||
121 | // the board. Note unlike earlier manifestations of | ||
122 | // the driver, these packets can be sent from | ||
123 | // in-place. | ||
124 | |||
125 | USHORT channelNeeds; // Bit map of important things which must be done | ||
126 | // for this channel. (See bits below ) | ||
127 | |||
128 | volatile | ||
129 | flowStat outfl; // Same type of structure is used to hold current | ||
130 | // flow control information used to control our | ||
131 | // output. "asof" is kept updated as data is sent, | ||
132 | // and "room" never goes to zero. | ||
133 | |||
134 | // The incoming ring buffer | ||
135 | // Unlike the outgoing buffers, this holds raw data, not packets. The two | ||
136 | // extra bytes are used to hold the byte-padding when there is room for an | ||
137 | // odd number of bytes before we must wrap. | ||
138 | // | ||
139 | UCHAR Ibuf[IBUF_SIZE + 2]; | ||
140 | volatile | ||
141 | USHORT Ibuf_stuff; // Stuffing index | ||
142 | volatile | ||
143 | USHORT Ibuf_strip; // Stripping index | ||
144 | |||
145 | // The outgoing ring-buffer: Holds Data and command packets. N.B., even | ||
146 | // though these are in the channel structure, the channel is also written | ||
147 | // here, the easier to send it to the fifo when ready. HOWEVER, individual | ||
148 | // packets here are NOT padded to even length: the routines for writing | ||
149 | // blocks to the fifo will pad to even byte counts. | ||
150 | // | ||
151 | UCHAR Obuf[OBUF_SIZE+MAX_OBUF_BLOCK+4]; | ||
152 | volatile | ||
153 | USHORT Obuf_stuff; // Stuffing index | ||
154 | volatile | ||
155 | USHORT Obuf_strip; // Stripping index | ||
156 | int Obuf_char_count; | ||
157 | |||
158 | // The outgoing bypass-command buffer. Unlike earlier manifestations, the | ||
159 | // flow control packets are sent directly from the structures. As above, the | ||
160 | // channel number is included in the packet, but they are NOT padded to even | ||
161 | // size. | ||
162 | // | ||
163 | UCHAR Cbuf[CBUF_SIZE+MAX_CBUF_BLOCK+2]; | ||
164 | volatile | ||
165 | USHORT Cbuf_stuff; // Stuffing index | ||
166 | volatile | ||
167 | USHORT Cbuf_strip; // Stripping index | ||
168 | |||
169 | // The temporary buffer for the Linux tty driver PutChar entry. | ||
170 | // | ||
171 | UCHAR Pbuf[MAX_OBUF_BLOCK - sizeof (i2DataHeader)]; | ||
172 | volatile | ||
173 | USHORT Pbuf_stuff; // Stuffing index | ||
174 | |||
175 | // The state of incoming data-set signals | ||
176 | // | ||
177 | USHORT dataSetIn; // Bit-mapped according to below. Also indicates | ||
178 | // whether a break has been detected since last | ||
179 | // inquiry. | ||
180 | |||
181 | // The state of outcoming data-set signals (as far as we can tell!) | ||
182 | // | ||
183 | USHORT dataSetOut; // Bit-mapped according to below. | ||
184 | |||
185 | // Most recent hot-key identifier detected | ||
186 | // | ||
187 | USHORT hotKeyIn; // Hot key as sent by the board, HOT_CLEAR indicates | ||
188 | // no hot key detected since last examined. | ||
189 | |||
190 | // Counter of outstanding requests for bookmarks | ||
191 | // | ||
192 | short bookMarks; // Number of outstanding bookmark requests, (+ive | ||
193 | // whenever a bookmark request if queued up, -ive | ||
194 | // whenever a bookmark is received). | ||
195 | |||
196 | // Misc options | ||
197 | // | ||
198 | USHORT channelOptions; // See below | ||
199 | |||
200 | // To store various incoming special packets | ||
201 | // | ||
202 | debugStat channelStatus; | ||
203 | cntStat channelRcount; | ||
204 | cntStat channelTcount; | ||
205 | failStat channelFail; | ||
206 | |||
207 | // To store the last values for line characteristics we sent to the board. | ||
208 | // | ||
209 | int speed; | ||
210 | |||
211 | int flush_flags; | ||
212 | |||
213 | void (*trace)(unsigned short,unsigned char,unsigned char,unsigned long,...); | ||
214 | |||
215 | /* | ||
216 | * Kernel counters for the 4 input interrupts | ||
217 | */ | ||
218 | struct async_icount icount; | ||
219 | |||
220 | /* | ||
221 | * Task queues for processing input packets from the board. | ||
222 | */ | ||
223 | struct work_struct tqueue_input; | ||
224 | struct work_struct tqueue_status; | ||
225 | struct work_struct tqueue_hangup; | ||
226 | |||
227 | rwlock_t Ibuf_spinlock; | ||
228 | rwlock_t Obuf_spinlock; | ||
229 | rwlock_t Cbuf_spinlock; | ||
230 | rwlock_t Pbuf_spinlock; | ||
231 | |||
232 | } i2ChanStr, *i2ChanStrPtr; | ||
233 | |||
234 | //--------------------------------------------------- | ||
235 | // Manifests and bit-maps for elements in i2ChanStr | ||
236 | //--------------------------------------------------- | ||
237 | // | ||
238 | // flush flags | ||
239 | // | ||
240 | #define STARTFL_FLAG 1 | ||
241 | #define STOPFL_FLAG 2 | ||
242 | |||
243 | // validity | ||
244 | // | ||
245 | #define CHANNEL_MAGIC_BITS 0xff00 | ||
246 | #define CHANNEL_MAGIC 0x5300 // (validity & CHANNEL_MAGIC_BITS) == | ||
247 | // CHANNEL_MAGIC --> structure good | ||
248 | |||
249 | #define CHANNEL_SUPPORT 0x0001 // Indicates channel is supported, exists, | ||
250 | // and passed P.O.S.T. | ||
251 | |||
252 | // channelNeeds | ||
253 | // | ||
254 | #define NEED_FLOW 1 // Indicates flow control has been queued | ||
255 | #define NEED_INLINE 2 // Indicates inline commands or data queued | ||
256 | #define NEED_BYPASS 4 // Indicates bypass commands queued | ||
257 | #define NEED_CREDIT 8 // Indicates would be sending except has not sufficient | ||
258 | // credit. The data is still in the channel structure, | ||
259 | // but the channel is not enqueued in the board | ||
260 | // structure again until there is a credit received from | ||
261 | // the board. | ||
262 | |||
263 | // dataSetIn (Also the bits for i2GetStatus return value) | ||
264 | // | ||
265 | #define I2_DCD 1 | ||
266 | #define I2_CTS 2 | ||
267 | #define I2_DSR 4 | ||
268 | #define I2_RI 8 | ||
269 | |||
270 | // dataSetOut (Also the bits for i2GetStatus return value) | ||
271 | // | ||
272 | #define I2_DTR 1 | ||
273 | #define I2_RTS 2 | ||
274 | |||
275 | // i2GetStatus() can optionally clear these bits | ||
276 | // | ||
277 | #define I2_BRK 0x10 // A break was detected | ||
278 | #define I2_PAR 0x20 // A parity error was received | ||
279 | #define I2_FRA 0x40 // A framing error was received | ||
280 | #define I2_OVR 0x80 // An overrun error was received | ||
281 | |||
282 | // i2GetStatus() automatically clears these bits */ | ||
283 | // | ||
284 | #define I2_DDCD 0x100 // DCD changed from its former value | ||
285 | #define I2_DCTS 0x200 // CTS changed from its former value | ||
286 | #define I2_DDSR 0x400 // DSR changed from its former value | ||
287 | #define I2_DRI 0x800 // RI changed from its former value | ||
288 | |||
289 | // hotKeyIn | ||
290 | // | ||
291 | #define HOT_CLEAR 0x1322 // Indicates that no hot-key has been detected | ||
292 | |||
293 | // channelOptions | ||
294 | // | ||
295 | #define CO_NBLOCK_WRITE 1 // Writes don't block waiting for buffer. (Default | ||
296 | // is, they do wait.) | ||
297 | |||
298 | // fcmodes | ||
299 | // | ||
300 | #define I2_OUTFLOW_CTS 0x0001 | ||
301 | #define I2_INFLOW_RTS 0x0002 | ||
302 | #define I2_INFLOW_DSR 0x0004 | ||
303 | #define I2_INFLOW_DTR 0x0008 | ||
304 | #define I2_OUTFLOW_DSR 0x0010 | ||
305 | #define I2_OUTFLOW_DTR 0x0020 | ||
306 | #define I2_OUTFLOW_XON 0x0040 | ||
307 | #define I2_OUTFLOW_XANY 0x0080 | ||
308 | #define I2_INFLOW_XON 0x0100 | ||
309 | |||
310 | #define I2_CRTSCTS (I2_OUTFLOW_CTS|I2_INFLOW_RTS) | ||
311 | #define I2_IXANY_MODE (I2_OUTFLOW_XON|I2_OUTFLOW_XANY) | ||
312 | |||
313 | //------------------------------------------- | ||
314 | // Macros used from user level like functions | ||
315 | //------------------------------------------- | ||
316 | |||
317 | // Macros to set and clear channel options | ||
318 | // | ||
319 | #define i2SetOption(pCh, option) pCh->channelOptions |= option | ||
320 | #define i2ClrOption(pCh, option) pCh->channelOptions &= ~option | ||
321 | |||
322 | // Macro to set fatal-error trap | ||
323 | // | ||
324 | #define i2SetFatalTrap(pB, routine) pB->i2eFatalTrap = routine | ||
325 | |||
326 | //-------------------------------------------- | ||
327 | // Declarations and prototypes for i2lib.c | ||
328 | //-------------------------------------------- | ||
329 | // | ||
330 | static int i2InitChannels(i2eBordStrPtr, int, i2ChanStrPtr); | ||
331 | static int i2QueueCommands(int, i2ChanStrPtr, int, int, cmdSyntaxPtr,...); | ||
332 | static int i2GetStatus(i2ChanStrPtr, int); | ||
333 | static int i2Input(i2ChanStrPtr); | ||
334 | static int i2InputFlush(i2ChanStrPtr); | ||
335 | static int i2Output(i2ChanStrPtr, const char *, int); | ||
336 | static int i2OutputFree(i2ChanStrPtr); | ||
337 | static int i2ServiceBoard(i2eBordStrPtr); | ||
338 | static void i2DrainOutput(i2ChanStrPtr, int); | ||
339 | |||
340 | #ifdef IP2DEBUG_TRACE | ||
341 | void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...); | ||
342 | #else | ||
343 | #define ip2trace(a,b,c,d...) do {} while (0) | ||
344 | #endif | ||
345 | |||
346 | // Argument to i2QueueCommands | ||
347 | // | ||
348 | #define C_IN_LINE 1 | ||
349 | #define C_BYPASS 0 | ||
350 | |||
351 | #endif // I2LIB_H | ||
diff --git a/drivers/char/ip2/i2pack.h b/drivers/char/ip2/i2pack.h deleted file mode 100644 index 00342a677c90..000000000000 --- a/drivers/char/ip2/i2pack.h +++ /dev/null | |||
@@ -1,364 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Definitions of the packets used to transfer data and commands | ||
12 | * Host <--> Board. Information provided here is only applicable | ||
13 | * when the standard loadware is active. | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | #ifndef I2PACK_H | ||
17 | #define I2PACK_H 1 | ||
18 | |||
19 | //----------------------------------------------- | ||
20 | // Revision History: | ||
21 | // | ||
22 | // 10 October 1991 MAG First draft | ||
23 | // 24 February 1992 MAG Additions for 1.4.x loadware | ||
24 | // 11 March 1992 MAG New status packets | ||
25 | // | ||
26 | //----------------------------------------------- | ||
27 | |||
28 | //------------------------------------------------------------------------------ | ||
29 | // Packet Formats: | ||
30 | // | ||
31 | // Information passes between the host and board through the FIFO in packets. | ||
32 | // These have headers which indicate the type of packet. Because the fifo data | ||
33 | // path may be 16-bits wide, the protocol is constrained such that each packet | ||
34 | // is always padded to an even byte count. (The lower-level interface routines | ||
35 | // -- i2ellis.c -- are designed to do this). | ||
36 | // | ||
37 | // The sender (be it host or board) must place some number of complete packets | ||
38 | // in the fifo, then place a message in the mailbox that packets are available. | ||
39 | // Placing such a message interrupts the "receiver" (be it board or host), who | ||
40 | // reads the mailbox message and determines that there are incoming packets | ||
41 | // ready. Since there are no partial packets, and the length of a packet is | ||
42 | // given in the header, the remainder of the packet can be read without checking | ||
43 | // for FIFO empty condition. The process is repeated, packet by packet, until | ||
44 | // the incoming FIFO is empty. Then the receiver uses the outbound mailbox to | ||
45 | // signal the board that it has read the data. Only then can the sender place | ||
46 | // additional data in the fifo. | ||
47 | //------------------------------------------------------------------------------ | ||
48 | // | ||
49 | //------------------------------------------------ | ||
50 | // Definition of Packet Header Area | ||
51 | //------------------------------------------------ | ||
52 | // | ||
53 | // Caution: these only define header areas. In actual use the data runs off | ||
54 | // beyond the end of these structures. | ||
55 | // | ||
56 | // Since these structures are based on sequences of bytes which go to the board, | ||
57 | // there cannot be ANY padding between the elements. | ||
58 | #pragma pack(1) | ||
59 | |||
60 | //---------------------------- | ||
61 | // DATA PACKETS | ||
62 | //---------------------------- | ||
63 | |||
64 | typedef struct _i2DataHeader | ||
65 | { | ||
66 | unsigned char i2sChannel; /* The channel number: 0-255 */ | ||
67 | |||
68 | // -- Bitfields are allocated LSB first -- | ||
69 | |||
70 | // For incoming data, indicates whether this is an ordinary packet or a | ||
71 | // special one (e.g., hot key hit). | ||
72 | unsigned i2sId : 2 __attribute__ ((__packed__)); | ||
73 | |||
74 | // For tagging data packets. There are flush commands which flush only data | ||
75 | // packets bearing a particular tag. (used in implementing IntelliView and | ||
76 | // IntelliPrint). THE TAG VALUE 0xf is RESERVED and must not be used (it has | ||
77 | // meaning internally to the loadware). | ||
78 | unsigned i2sTag : 4; | ||
79 | |||
80 | // These two bits determine the type of packet sent/received. | ||
81 | unsigned i2sType : 2; | ||
82 | |||
83 | // The count of data to follow: does not include the possible additional | ||
84 | // padding byte. MAXIMUM COUNT: 4094. The top four bits must be 0. | ||
85 | unsigned short i2sCount; | ||
86 | |||
87 | } i2DataHeader, *i2DataHeaderPtr; | ||
88 | |||
89 | // Structure is immediately followed by the data, proper. | ||
90 | |||
91 | //---------------------------- | ||
92 | // NON-DATA PACKETS | ||
93 | //---------------------------- | ||
94 | |||
95 | typedef struct _i2CmdHeader | ||
96 | { | ||
97 | unsigned char i2sChannel; // The channel number: 0-255 (Except where noted | ||
98 | // - see below | ||
99 | |||
100 | // Number of bytes of commands, status or whatever to follow | ||
101 | unsigned i2sCount : 6; | ||
102 | |||
103 | // These two bits determine the type of packet sent/received. | ||
104 | unsigned i2sType : 2; | ||
105 | |||
106 | } i2CmdHeader, *i2CmdHeaderPtr; | ||
107 | |||
108 | // Structure is immediately followed by the applicable data. | ||
109 | |||
110 | //--------------------------------------- | ||
111 | // Flow Control Packets (Outbound) | ||
112 | //--------------------------------------- | ||
113 | |||
114 | // One type of outbound command packet is so important that the entire structure | ||
115 | // is explicitly defined here. That is the flow-control packet. This is never | ||
116 | // sent by user-level code (as would be the commands to raise/lower DTR, for | ||
117 | // example). These are only sent by the library routines in response to reading | ||
118 | // incoming data into the buffers. | ||
119 | // | ||
120 | // The parameters inside the command block are maintained in place, then the | ||
121 | // block is sent at the appropriate time. | ||
122 | |||
123 | typedef struct _flowIn | ||
124 | { | ||
125 | i2CmdHeader hd; // Channel #, count, type (see above) | ||
126 | unsigned char fcmd; // The flow control command (37) | ||
127 | unsigned short asof; // As of byte number "asof" (LSB first!) I have room | ||
128 | // for "room" bytes | ||
129 | unsigned short room; | ||
130 | } flowIn, *flowInPtr; | ||
131 | |||
132 | //---------------------------------------- | ||
133 | // (Incoming) Status Packets | ||
134 | //---------------------------------------- | ||
135 | |||
136 | // Incoming packets which are non-data packets are status packets. In this case, | ||
137 | // the channel number in the header is unimportant. What follows are one or more | ||
138 | // sub-packets, the first word of which consists of the channel (first or low | ||
139 | // byte) and the status indicator (second or high byte), followed by possibly | ||
140 | // more data. | ||
141 | |||
142 | #define STAT_CTS_UP 0 /* CTS raised (no other bytes) */ | ||
143 | #define STAT_CTS_DN 1 /* CTS dropped (no other bytes) */ | ||
144 | #define STAT_DCD_UP 2 /* DCD raised (no other bytes) */ | ||
145 | #define STAT_DCD_DN 3 /* DCD dropped (no other bytes) */ | ||
146 | #define STAT_DSR_UP 4 /* DSR raised (no other bytes) */ | ||
147 | #define STAT_DSR_DN 5 /* DSR dropped (no other bytes) */ | ||
148 | #define STAT_RI_UP 6 /* RI raised (no other bytes) */ | ||
149 | #define STAT_RI_DN 7 /* RI dropped (no other bytes) */ | ||
150 | #define STAT_BRK_DET 8 /* BRK detect (no other bytes) */ | ||
151 | #define STAT_FLOW 9 /* Flow control(-- more: see below */ | ||
152 | #define STAT_BMARK 10 /* Bookmark (no other bytes) | ||
153 | * Bookmark is sent as a response to | ||
154 | * a command 60: request for bookmark | ||
155 | */ | ||
156 | #define STAT_STATUS 11 /* Special packet: see below */ | ||
157 | #define STAT_TXCNT 12 /* Special packet: see below */ | ||
158 | #define STAT_RXCNT 13 /* Special packet: see below */ | ||
159 | #define STAT_BOXIDS 14 /* Special packet: see below */ | ||
160 | #define STAT_HWFAIL 15 /* Special packet: see below */ | ||
161 | |||
162 | #define STAT_MOD_ERROR 0xc0 | ||
163 | #define STAT_MODEM 0xc0/* If status & STAT_MOD_ERROR: | ||
164 | * == STAT_MODEM, then this is a modem | ||
165 | * status packet, given in response to a | ||
166 | * CMD_DSS_NOW command. | ||
167 | * The low nibble has each data signal: | ||
168 | */ | ||
169 | #define STAT_MOD_DCD 0x8 | ||
170 | #define STAT_MOD_RI 0x4 | ||
171 | #define STAT_MOD_DSR 0x2 | ||
172 | #define STAT_MOD_CTS 0x1 | ||
173 | |||
174 | #define STAT_ERROR 0x80/* If status & STAT_MOD_ERROR | ||
175 | * == STAT_ERROR, then | ||
176 | * sort of error on the channel. | ||
177 | * The remaining seven bits indicate | ||
178 | * what sort of error it is. | ||
179 | */ | ||
180 | /* The low three bits indicate parity, framing, or overrun errors */ | ||
181 | |||
182 | #define STAT_E_PARITY 4 /* Parity error */ | ||
183 | #define STAT_E_FRAMING 2 /* Framing error */ | ||
184 | #define STAT_E_OVERRUN 1 /* (uxart) overrun error */ | ||
185 | |||
186 | //--------------------------------------- | ||
187 | // STAT_FLOW packets | ||
188 | //--------------------------------------- | ||
189 | |||
190 | typedef struct _flowStat | ||
191 | { | ||
192 | unsigned short asof; | ||
193 | unsigned short room; | ||
194 | }flowStat, *flowStatPtr; | ||
195 | |||
196 | // flowStat packets are received from the board to regulate the flow of outgoing | ||
197 | // data. A local copy of this structure is also kept to track the amount of | ||
198 | // credits used and credits remaining. "room" is the amount of space in the | ||
199 | // board's buffers, "as of" having received a certain byte number. When sending | ||
200 | // data to the fifo, you must calculate how much buffer space your packet will | ||
201 | // use. Add this to the current "asof" and subtract it from the current "room". | ||
202 | // | ||
203 | // The calculation for the board's buffer is given by CREDIT_USAGE, where size | ||
204 | // is the un-rounded count of either data characters or command characters. | ||
205 | // (Which is to say, the count rounded up, plus two). | ||
206 | |||
207 | #define CREDIT_USAGE(size) (((size) + 3) & ~1) | ||
208 | |||
209 | //--------------------------------------- | ||
210 | // STAT_STATUS packets | ||
211 | //--------------------------------------- | ||
212 | |||
213 | typedef struct _debugStat | ||
214 | { | ||
215 | unsigned char d_ccsr; | ||
216 | unsigned char d_txinh; | ||
217 | unsigned char d_stat1; | ||
218 | unsigned char d_stat2; | ||
219 | } debugStat, *debugStatPtr; | ||
220 | |||
221 | // debugStat packets are sent to the host in response to a CMD_GET_STATUS | ||
222 | // command. Each byte is bit-mapped as described below: | ||
223 | |||
224 | #define D_CCSR_XON 2 /* Has received XON, ready to transmit */ | ||
225 | #define D_CCSR_XOFF 4 /* Has received XOFF, not transmitting */ | ||
226 | #define D_CCSR_TXENAB 8 /* Transmitter is enabled */ | ||
227 | #define D_CCSR_RXENAB 0x80 /* Receiver is enabled */ | ||
228 | |||
229 | #define D_TXINH_BREAK 1 /* We are sending a break */ | ||
230 | #define D_TXINH_EMPTY 2 /* No data to send */ | ||
231 | #define D_TXINH_SUSP 4 /* Output suspended via command 57 */ | ||
232 | #define D_TXINH_CMD 8 /* We are processing an in-line command */ | ||
233 | #define D_TXINH_LCD 0x10 /* LCD diagnostics are running */ | ||
234 | #define D_TXINH_PAUSE 0x20 /* We are processing a PAUSE command */ | ||
235 | #define D_TXINH_DCD 0x40 /* DCD is low, preventing transmission */ | ||
236 | #define D_TXINH_DSR 0x80 /* DSR is low, preventing transmission */ | ||
237 | |||
238 | #define D_STAT1_TXEN 1 /* Transmit INTERRUPTS enabled */ | ||
239 | #define D_STAT1_RXEN 2 /* Receiver INTERRUPTS enabled */ | ||
240 | #define D_STAT1_MDEN 4 /* Modem (data set sigs) interrupts enabled */ | ||
241 | #define D_STAT1_RLM 8 /* Remote loopback mode selected */ | ||
242 | #define D_STAT1_LLM 0x10 /* Local internal loopback mode selected */ | ||
243 | #define D_STAT1_CTS 0x20 /* CTS is low, preventing transmission */ | ||
244 | #define D_STAT1_DTR 0x40 /* DTR is low, to stop remote transmission */ | ||
245 | #define D_STAT1_RTS 0x80 /* RTS is low, to stop remote transmission */ | ||
246 | |||
247 | #define D_STAT2_TXMT 1 /* Transmit buffers are all empty */ | ||
248 | #define D_STAT2_RXMT 2 /* Receive buffers are all empty */ | ||
249 | #define D_STAT2_RXINH 4 /* Loadware has tried to inhibit remote | ||
250 | * transmission: dropped DTR, sent XOFF, | ||
251 | * whatever... | ||
252 | */ | ||
253 | #define D_STAT2_RXFLO 8 /* Loadware can send no more data to host | ||
254 | * until it receives a flow-control packet | ||
255 | */ | ||
256 | //----------------------------------------- | ||
257 | // STAT_TXCNT and STAT_RXCNT packets | ||
258 | //---------------------------------------- | ||
259 | |||
260 | typedef struct _cntStat | ||
261 | { | ||
262 | unsigned short cs_time; // (Assumes host is little-endian!) | ||
263 | unsigned short cs_count; | ||
264 | } cntStat, *cntStatPtr; | ||
265 | |||
266 | // These packets are sent in response to a CMD_GET_RXCNT or a CMD_GET_TXCNT | ||
267 | // bypass command. cs_time is a running 1 Millisecond counter which acts as a | ||
268 | // time stamp. cs_count is a running counter of data sent or received from the | ||
269 | // uxarts. (Not including data added by the chip itself, as with CRLF | ||
270 | // processing). | ||
271 | //------------------------------------------ | ||
272 | // STAT_HWFAIL packets | ||
273 | //------------------------------------------ | ||
274 | |||
275 | typedef struct _failStat | ||
276 | { | ||
277 | unsigned char fs_written; | ||
278 | unsigned char fs_read; | ||
279 | unsigned short fs_address; | ||
280 | } failStat, *failStatPtr; | ||
281 | |||
282 | // This packet is sent whenever the on-board diagnostic process detects an | ||
283 | // error. At startup, this process is dormant. The host can wake it up by | ||
284 | // issuing the bypass command CMD_HW_TEST. The process runs at low priority and | ||
285 | // performs continuous hardware verification; writing data to certain on-board | ||
286 | // registers, reading it back, and comparing. If it detects an error, this | ||
287 | // packet is sent to the host, and the process goes dormant again until the host | ||
288 | // sends another CMD_HW_TEST. It then continues with the next register to be | ||
289 | // tested. | ||
290 | |||
291 | //------------------------------------------------------------------------------ | ||
292 | // Macros to deal with the headers more easily! Note that these are defined so | ||
293 | // they may be used as "left" as well as "right" expressions. | ||
294 | //------------------------------------------------------------------------------ | ||
295 | |||
296 | // Given a pointer to the packet, reference the channel number | ||
297 | // | ||
298 | #define CHANNEL_OF(pP) ((i2DataHeaderPtr)(pP))->i2sChannel | ||
299 | |||
300 | // Given a pointer to the packet, reference the Packet type | ||
301 | // | ||
302 | #define PTYPE_OF(pP) ((i2DataHeaderPtr)(pP))->i2sType | ||
303 | |||
304 | // The possible types of packets | ||
305 | // | ||
306 | #define PTYPE_DATA 0 /* Host <--> Board */ | ||
307 | #define PTYPE_BYPASS 1 /* Host ---> Board */ | ||
308 | #define PTYPE_INLINE 2 /* Host ---> Board */ | ||
309 | #define PTYPE_STATUS 2 /* Host <--- Board */ | ||
310 | |||
311 | // Given a pointer to a Data packet, reference the Tag | ||
312 | // | ||
313 | #define TAG_OF(pP) ((i2DataHeaderPtr)(pP))->i2sTag | ||
314 | |||
315 | // Given a pointer to a Data packet, reference the data i.d. | ||
316 | // | ||
317 | #define ID_OF(pP) ((i2DataHeaderPtr)(pP))->i2sId | ||
318 | |||
319 | // The possible types of ID's | ||
320 | // | ||
321 | #define ID_ORDINARY_DATA 0 | ||
322 | #define ID_HOT_KEY 1 | ||
323 | |||
324 | // Given a pointer to a Data packet, reference the count | ||
325 | // | ||
326 | #define DATA_COUNT_OF(pP) ((i2DataHeaderPtr)(pP))->i2sCount | ||
327 | |||
328 | // Given a pointer to a Data packet, reference the beginning of data | ||
329 | // | ||
330 | #define DATA_OF(pP) &((unsigned char *)(pP))[4] // 4 = size of header | ||
331 | |||
332 | // Given a pointer to a Non-Data packet, reference the count | ||
333 | // | ||
334 | #define CMD_COUNT_OF(pP) ((i2CmdHeaderPtr)(pP))->i2sCount | ||
335 | |||
336 | #define MAX_CMD_PACK_SIZE 62 // Maximum size of such a count | ||
337 | |||
338 | // Given a pointer to a Non-Data packet, reference the beginning of data | ||
339 | // | ||
340 | #define CMD_OF(pP) &((unsigned char *)(pP))[2] // 2 = size of header | ||
341 | |||
342 | //-------------------------------- | ||
343 | // MailBox Bits: | ||
344 | //-------------------------------- | ||
345 | |||
346 | //-------------------------- | ||
347 | // Outgoing (host to board) | ||
348 | //-------------------------- | ||
349 | // | ||
350 | #define MB_OUT_STUFFED 0x80 // Host has placed output in fifo | ||
351 | #define MB_IN_STRIPPED 0x40 // Host has read in all input from fifo | ||
352 | |||
353 | //-------------------------- | ||
354 | // Incoming (board to host) | ||
355 | //-------------------------- | ||
356 | // | ||
357 | #define MB_IN_STUFFED 0x80 // Board has placed input in fifo | ||
358 | #define MB_OUT_STRIPPED 0x40 // Board has read all output from fifo | ||
359 | #define MB_FATAL_ERROR 0x20 // Board has encountered a fatal error | ||
360 | |||
361 | #pragma pack() // Reset padding to command-line default | ||
362 | |||
363 | #endif // I2PACK_H | ||
364 | |||
diff --git a/drivers/char/ip2/ip2.h b/drivers/char/ip2/ip2.h deleted file mode 100644 index 936ccc533949..000000000000 --- a/drivers/char/ip2/ip2.h +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Driver constants for configuration and tuning | ||
12 | * | ||
13 | * NOTES: | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | #ifndef IP2_H | ||
17 | #define IP2_H | ||
18 | |||
19 | #include "ip2types.h" | ||
20 | #include "i2cmd.h" | ||
21 | |||
22 | /*************/ | ||
23 | /* Constants */ | ||
24 | /*************/ | ||
25 | |||
26 | /* Device major numbers - since version 2.0.26. */ | ||
27 | #define IP2_TTY_MAJOR 71 | ||
28 | #define IP2_CALLOUT_MAJOR 72 | ||
29 | #define IP2_IPL_MAJOR 73 | ||
30 | |||
31 | /* Board configuration array. | ||
32 | * This array defines the hardware irq and address for up to IP2_MAX_BOARDS | ||
33 | * (4 supported per ip2_types.h) ISA board addresses and irqs MUST be specified, | ||
34 | * PCI and EISA boards are probed for and automagicly configed | ||
35 | * iff the addresses are set to 1 and 2 respectivily. | ||
36 | * 0x0100 - 0x03f0 == ISA | ||
37 | * 1 == PCI | ||
38 | * 2 == EISA | ||
39 | * 0 == (skip this board) | ||
40 | * This array defines the hardware addresses for them. Special | ||
41 | * addresses are EISA and PCI which go sniffing for boards. | ||
42 | |||
43 | * In a multiboard system the position in the array determines which port | ||
44 | * devices are assigned to each board: | ||
45 | * board 0 is assigned ttyF0.. to ttyF63, | ||
46 | * board 1 is assigned ttyF64 to ttyF127, | ||
47 | * board 2 is assigned ttyF128 to ttyF191, | ||
48 | * board 3 is assigned ttyF192 to ttyF255. | ||
49 | * | ||
50 | * In PCI and EISA bus systems each range is mapped to card in | ||
51 | * monotonically increasing slot number order, ISA position is as specified | ||
52 | * here. | ||
53 | |||
54 | * If the irqs are ALL set to 0,0,0,0 all boards operate in | ||
55 | * polled mode. For interrupt operation ISA boards require that the IRQ be | ||
56 | * specified, while PCI and EISA boards any nonzero entry | ||
57 | * will enable interrupts using the BIOS configured irq for the board. | ||
58 | * An invalid irq entry will default to polled mode for that card and print | ||
59 | * console warning. | ||
60 | |||
61 | * When the driver is loaded as a module these setting can be overridden on the | ||
62 | * modprobe command line or on an option line in /etc/modprobe.conf. | ||
63 | * If the driver is built-in the configuration must be | ||
64 | * set here for ISA cards and address set to 1 and 2 for PCI and EISA. | ||
65 | * | ||
66 | * Here is an example that shows most if not all possibe combinations: | ||
67 | |||
68 | *static ip2config_t ip2config = | ||
69 | *{ | ||
70 | * {11,1,0,0}, // irqs | ||
71 | * { // Addresses | ||
72 | * 0x0308, // Board 0, ttyF0 - ttyF63// ISA card at io=0x308, irq=11 | ||
73 | * 0x0001, // Board 1, ttyF64 - ttyF127//PCI card configured by BIOS | ||
74 | * 0x0000, // Board 2, ttyF128 - ttyF191// Slot skipped | ||
75 | * 0x0002 // Board 3, ttyF192 - ttyF255//EISA card configured by BIOS | ||
76 | * // but polled not irq driven | ||
77 | * } | ||
78 | *}; | ||
79 | */ | ||
80 | |||
81 | /* this structure is zeroed out because the suggested method is to configure | ||
82 | * the driver as a module, set up the parameters with an options line in | ||
83 | * /etc/modprobe.conf and load with modprobe or kmod, the kernel | ||
84 | * module loader | ||
85 | */ | ||
86 | |||
87 | /* This structure is NOW always initialized when the driver is initialized. | ||
88 | * Compiled in defaults MUST be added to the io and irq arrays in | ||
89 | * ip2.c. Those values are configurable from insmod parameters in the | ||
90 | * case of modules or from command line parameters (ip2=io,irq) when | ||
91 | * compiled in. | ||
92 | */ | ||
93 | |||
94 | static ip2config_t ip2config = | ||
95 | { | ||
96 | {0,0,0,0}, // irqs | ||
97 | { // Addresses | ||
98 | /* Do NOT set compile time defaults HERE! Use the arrays in | ||
99 | ip2.c! These WILL be overwritten! =mhw= */ | ||
100 | 0x0000, // Board 0, ttyF0 - ttyF63 | ||
101 | 0x0000, // Board 1, ttyF64 - ttyF127 | ||
102 | 0x0000, // Board 2, ttyF128 - ttyF191 | ||
103 | 0x0000 // Board 3, ttyF192 - ttyF255 | ||
104 | } | ||
105 | }; | ||
106 | |||
107 | #endif | ||
diff --git a/drivers/char/ip2/ip2ioctl.h b/drivers/char/ip2/ip2ioctl.h deleted file mode 100644 index aa0a9da85e05..000000000000 --- a/drivers/char/ip2/ip2ioctl.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Driver constants for configuration and tuning | ||
12 | * | ||
13 | * NOTES: | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | |||
17 | #ifndef IP2IOCTL_H | ||
18 | #define IP2IOCTL_H | ||
19 | |||
20 | //************* | ||
21 | //* Constants * | ||
22 | //************* | ||
23 | |||
24 | // High baud rates (if not defined elsewhere. | ||
25 | #ifndef B153600 | ||
26 | # define B153600 0010005 | ||
27 | #endif | ||
28 | #ifndef B307200 | ||
29 | # define B307200 0010006 | ||
30 | #endif | ||
31 | #ifndef B921600 | ||
32 | # define B921600 0010007 | ||
33 | #endif | ||
34 | |||
35 | #endif | ||
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c deleted file mode 100644 index c3a025356b8b..000000000000 --- a/drivers/char/ip2/ip2main.c +++ /dev/null | |||
@@ -1,3234 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * (c) 1999 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport | ||
8 | * serial I/O controllers. | ||
9 | * | ||
10 | * DESCRIPTION: Mainline code for the device driver | ||
11 | * | ||
12 | *******************************************************************************/ | ||
13 | // ToDo: | ||
14 | // | ||
15 | // Fix the immediate DSS_NOW problem. | ||
16 | // Work over the channel stats return logic in ip2_ipl_ioctl so they | ||
17 | // make sense for all 256 possible channels and so the user space | ||
18 | // utilities will compile and work properly. | ||
19 | // | ||
20 | // Done: | ||
21 | // | ||
22 | // 1.2.14 /\/\|=mhw=|\/\/ | ||
23 | // Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts. | ||
24 | // Changed the definition of ip2trace to be more consistent with kernel style | ||
25 | // Thanks to Andreas Dilger <adilger@turbolabs.com> for these updates | ||
26 | // | ||
27 | // 1.2.13 /\/\|=mhw=|\/\/ | ||
28 | // DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform | ||
29 | // to agreed devfs serial device naming convention. | ||
30 | // | ||
31 | // 1.2.12 /\/\|=mhw=|\/\/ | ||
32 | // Cleaned up some remove queue cut and paste errors | ||
33 | // | ||
34 | // 1.2.11 /\/\|=mhw=|\/\/ | ||
35 | // Clean up potential NULL pointer dereferences | ||
36 | // Clean up devfs registration | ||
37 | // Add kernel command line parsing for io and irq | ||
38 | // Compile defaults for io and irq are now set in ip2.c not ip2.h! | ||
39 | // Reworked poll_only hack for explicit parameter setting | ||
40 | // You must now EXPLICITLY set poll_only = 1 or set all irqs to 0 | ||
41 | // Merged ip2_loadmain and old_ip2_init | ||
42 | // Converted all instances of interruptible_sleep_on into queue calls | ||
43 | // Most of these had no race conditions but better to clean up now | ||
44 | // | ||
45 | // 1.2.10 /\/\|=mhw=|\/\/ | ||
46 | // Fixed the bottom half interrupt handler and enabled USE_IQI | ||
47 | // to split the interrupt handler into a formal top-half / bottom-half | ||
48 | // Fixed timing window on high speed processors that queued messages to | ||
49 | // the outbound mail fifo faster than the board could handle. | ||
50 | // | ||
51 | // 1.2.9 | ||
52 | // Four box EX was barfing on >128k kmalloc, made structure smaller by | ||
53 | // reducing output buffer size | ||
54 | // | ||
55 | // 1.2.8 | ||
56 | // Device file system support (MHW) | ||
57 | // | ||
58 | // 1.2.7 | ||
59 | // Fixed | ||
60 | // Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules | ||
61 | // | ||
62 | // 1.2.6 | ||
63 | //Fixes DCD problems | ||
64 | // DCD was not reported when CLOCAL was set on call to TIOCMGET | ||
65 | // | ||
66 | //Enhancements: | ||
67 | // TIOCMGET requests and waits for status return | ||
68 | // No DSS interrupts enabled except for DCD when needed | ||
69 | // | ||
70 | // For internal use only | ||
71 | // | ||
72 | //#define IP2DEBUG_INIT | ||
73 | //#define IP2DEBUG_OPEN | ||
74 | //#define IP2DEBUG_WRITE | ||
75 | //#define IP2DEBUG_READ | ||
76 | //#define IP2DEBUG_IOCTL | ||
77 | //#define IP2DEBUG_IPL | ||
78 | |||
79 | //#define IP2DEBUG_TRACE | ||
80 | //#define DEBUG_FIFO | ||
81 | |||
82 | /************/ | ||
83 | /* Includes */ | ||
84 | /************/ | ||
85 | |||
86 | #include <linux/ctype.h> | ||
87 | #include <linux/string.h> | ||
88 | #include <linux/fcntl.h> | ||
89 | #include <linux/errno.h> | ||
90 | #include <linux/module.h> | ||
91 | #include <linux/signal.h> | ||
92 | #include <linux/sched.h> | ||
93 | #include <linux/timer.h> | ||
94 | #include <linux/interrupt.h> | ||
95 | #include <linux/pci.h> | ||
96 | #include <linux/mm.h> | ||
97 | #include <linux/slab.h> | ||
98 | #include <linux/major.h> | ||
99 | #include <linux/wait.h> | ||
100 | #include <linux/device.h> | ||
101 | #include <linux/mutex.h> | ||
102 | #include <linux/firmware.h> | ||
103 | #include <linux/platform_device.h> | ||
104 | |||
105 | #include <linux/tty.h> | ||
106 | #include <linux/tty_flip.h> | ||
107 | #include <linux/termios.h> | ||
108 | #include <linux/tty_driver.h> | ||
109 | #include <linux/serial.h> | ||
110 | #include <linux/ptrace.h> | ||
111 | #include <linux/ioport.h> | ||
112 | |||
113 | #include <linux/cdk.h> | ||
114 | #include <linux/comstats.h> | ||
115 | #include <linux/delay.h> | ||
116 | #include <linux/bitops.h> | ||
117 | |||
118 | #include <asm/system.h> | ||
119 | #include <asm/io.h> | ||
120 | #include <asm/irq.h> | ||
121 | |||
122 | #include <linux/vmalloc.h> | ||
123 | #include <linux/init.h> | ||
124 | |||
125 | #include <asm/uaccess.h> | ||
126 | |||
127 | #include "ip2types.h" | ||
128 | #include "ip2trace.h" | ||
129 | #include "ip2ioctl.h" | ||
130 | #include "ip2.h" | ||
131 | #include "i2ellis.h" | ||
132 | #include "i2lib.h" | ||
133 | |||
134 | /***************** | ||
135 | * /proc/ip2mem * | ||
136 | *****************/ | ||
137 | |||
138 | #include <linux/proc_fs.h> | ||
139 | #include <linux/seq_file.h> | ||
140 | |||
141 | static DEFINE_MUTEX(ip2_mutex); | ||
142 | static const struct file_operations ip2mem_proc_fops; | ||
143 | static const struct file_operations ip2_proc_fops; | ||
144 | |||
145 | /********************/ | ||
146 | /* Type Definitions */ | ||
147 | /********************/ | ||
148 | |||
149 | /*************/ | ||
150 | /* Constants */ | ||
151 | /*************/ | ||
152 | |||
153 | /* String constants to identify ourselves */ | ||
154 | static const char pcName[] = "Computone IntelliPort Plus multiport driver"; | ||
155 | static const char pcVersion[] = "1.2.14"; | ||
156 | |||
157 | /* String constants for port names */ | ||
158 | static const char pcDriver_name[] = "ip2"; | ||
159 | static const char pcIpl[] = "ip2ipl"; | ||
160 | |||
161 | /***********************/ | ||
162 | /* Function Prototypes */ | ||
163 | /***********************/ | ||
164 | |||
165 | /* Global module entry functions */ | ||
166 | |||
167 | /* Private (static) functions */ | ||
168 | static int ip2_open(PTTY, struct file *); | ||
169 | static void ip2_close(PTTY, struct file *); | ||
170 | static int ip2_write(PTTY, const unsigned char *, int); | ||
171 | static int ip2_putchar(PTTY, unsigned char); | ||
172 | static void ip2_flush_chars(PTTY); | ||
173 | static int ip2_write_room(PTTY); | ||
174 | static int ip2_chars_in_buf(PTTY); | ||
175 | static void ip2_flush_buffer(PTTY); | ||
176 | static int ip2_ioctl(PTTY, struct file *, UINT, ULONG); | ||
177 | static void ip2_set_termios(PTTY, struct ktermios *); | ||
178 | static void ip2_set_line_discipline(PTTY); | ||
179 | static void ip2_throttle(PTTY); | ||
180 | static void ip2_unthrottle(PTTY); | ||
181 | static void ip2_stop(PTTY); | ||
182 | static void ip2_start(PTTY); | ||
183 | static void ip2_hangup(PTTY); | ||
184 | static int ip2_tiocmget(struct tty_struct *tty, struct file *file); | ||
185 | static int ip2_tiocmset(struct tty_struct *tty, struct file *file, | ||
186 | unsigned int set, unsigned int clear); | ||
187 | static int ip2_get_icount(struct tty_struct *tty, | ||
188 | struct serial_icounter_struct *icount); | ||
189 | |||
190 | static void set_irq(int, int); | ||
191 | static void ip2_interrupt_bh(struct work_struct *work); | ||
192 | static irqreturn_t ip2_interrupt(int irq, void *dev_id); | ||
193 | static void ip2_poll(unsigned long arg); | ||
194 | static inline void service_all_boards(void); | ||
195 | static void do_input(struct work_struct *); | ||
196 | static void do_status(struct work_struct *); | ||
197 | |||
198 | static void ip2_wait_until_sent(PTTY,int); | ||
199 | |||
200 | static void set_params (i2ChanStrPtr, struct ktermios *); | ||
201 | static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); | ||
202 | static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); | ||
203 | |||
204 | static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); | ||
205 | static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); | ||
206 | static long ip2_ipl_ioctl(struct file *, UINT, ULONG); | ||
207 | static int ip2_ipl_open(struct inode *, struct file *); | ||
208 | |||
209 | static int DumpTraceBuffer(char __user *, int); | ||
210 | static int DumpFifoBuffer( char __user *, int); | ||
211 | |||
212 | static void ip2_init_board(int, const struct firmware *); | ||
213 | static unsigned short find_eisa_board(int); | ||
214 | static int ip2_setup(char *str); | ||
215 | |||
216 | /***************/ | ||
217 | /* Static Data */ | ||
218 | /***************/ | ||
219 | |||
220 | static struct tty_driver *ip2_tty_driver; | ||
221 | |||
222 | /* Here, then is a table of board pointers which the interrupt routine should | ||
223 | * scan through to determine who it must service. | ||
224 | */ | ||
225 | static unsigned short i2nBoards; // Number of boards here | ||
226 | |||
227 | static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS]; | ||
228 | |||
229 | static i2ChanStrPtr DevTable[IP2_MAX_PORTS]; | ||
230 | //DevTableMem just used to save addresses for kfree | ||
231 | static void *DevTableMem[IP2_MAX_BOARDS]; | ||
232 | |||
233 | /* This is the driver descriptor for the ip2ipl device, which is used to | ||
234 | * download the loadware to the boards. | ||
235 | */ | ||
236 | static const struct file_operations ip2_ipl = { | ||
237 | .owner = THIS_MODULE, | ||
238 | .read = ip2_ipl_read, | ||
239 | .write = ip2_ipl_write, | ||
240 | .unlocked_ioctl = ip2_ipl_ioctl, | ||
241 | .open = ip2_ipl_open, | ||
242 | .llseek = noop_llseek, | ||
243 | }; | ||
244 | |||
245 | static unsigned long irq_counter; | ||
246 | static unsigned long bh_counter; | ||
247 | |||
248 | // Use immediate queue to service interrupts | ||
249 | #define USE_IQI | ||
250 | //#define USE_IQ // PCI&2.2 needs work | ||
251 | |||
252 | /* The timer_list entry for our poll routine. If interrupt operation is not | ||
253 | * selected, the board is serviced periodically to see if anything needs doing. | ||
254 | */ | ||
255 | #define POLL_TIMEOUT (jiffies + 1) | ||
256 | static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); | ||
257 | |||
258 | #ifdef IP2DEBUG_TRACE | ||
259 | /* Trace (debug) buffer data */ | ||
260 | #define TRACEMAX 1000 | ||
261 | static unsigned long tracebuf[TRACEMAX]; | ||
262 | static int tracestuff; | ||
263 | static int tracestrip; | ||
264 | static int tracewrap; | ||
265 | #endif | ||
266 | |||
267 | /**********/ | ||
268 | /* Macros */ | ||
269 | /**********/ | ||
270 | |||
271 | #ifdef IP2DEBUG_OPEN | ||
272 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ | ||
273 | tty->name,(pCh->flags), \ | ||
274 | tty->count,/*GET_USE_COUNT(module)*/0,s) | ||
275 | #else | ||
276 | #define DBG_CNT(s) | ||
277 | #endif | ||
278 | |||
279 | /********/ | ||
280 | /* Code */ | ||
281 | /********/ | ||
282 | |||
283 | #include "i2ellis.c" /* Extremely low-level interface services */ | ||
284 | #include "i2cmd.c" /* Standard loadware command definitions */ | ||
285 | #include "i2lib.c" /* High level interface services */ | ||
286 | |||
287 | /* Configuration area for modprobe */ | ||
288 | |||
289 | MODULE_AUTHOR("Doug McNash"); | ||
290 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | ||
291 | MODULE_LICENSE("GPL"); | ||
292 | |||
293 | #define MAX_CMD_STR 50 | ||
294 | |||
295 | static int poll_only; | ||
296 | static char cmd[MAX_CMD_STR]; | ||
297 | |||
298 | static int Eisa_irq; | ||
299 | static int Eisa_slot; | ||
300 | |||
301 | static int iindx; | ||
302 | static char rirqs[IP2_MAX_BOARDS]; | ||
303 | static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; | ||
304 | |||
305 | /* Note: Add compiled in defaults to these arrays, not to the structure | ||
306 | in ip2.h any longer. That structure WILL get overridden | ||
307 | by these values, or command line values, or insmod values!!! =mhw= | ||
308 | */ | ||
309 | static int io[IP2_MAX_BOARDS]; | ||
310 | static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; | ||
311 | |||
312 | MODULE_AUTHOR("Doug McNash"); | ||
313 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | ||
314 | module_param_array(irq, int, NULL, 0); | ||
315 | MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards"); | ||
316 | module_param_array(io, int, NULL, 0); | ||
317 | MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); | ||
318 | module_param(poll_only, bool, 0); | ||
319 | MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); | ||
320 | module_param_string(ip2, cmd, MAX_CMD_STR, 0); | ||
321 | MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='"); | ||
322 | |||
323 | /* for sysfs class support */ | ||
324 | static struct class *ip2_class; | ||
325 | |||
326 | /* Some functions to keep track of what irqs we have */ | ||
327 | |||
328 | static int __init is_valid_irq(int irq) | ||
329 | { | ||
330 | int *i = Valid_Irqs; | ||
331 | |||
332 | while (*i != 0 && *i != irq) | ||
333 | i++; | ||
334 | |||
335 | return *i; | ||
336 | } | ||
337 | |||
338 | static void __init mark_requested_irq(char irq) | ||
339 | { | ||
340 | rirqs[iindx++] = irq; | ||
341 | } | ||
342 | |||
343 | static int __exit clear_requested_irq(char irq) | ||
344 | { | ||
345 | int i; | ||
346 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
347 | if (rirqs[i] == irq) { | ||
348 | rirqs[i] = 0; | ||
349 | return 1; | ||
350 | } | ||
351 | } | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int have_requested_irq(char irq) | ||
356 | { | ||
357 | /* array init to zeros so 0 irq will not be requested as a side | ||
358 | * effect */ | ||
359 | int i; | ||
360 | for (i = 0; i < IP2_MAX_BOARDS; ++i) | ||
361 | if (rirqs[i] == irq) | ||
362 | return 1; | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | /******************************************************************************/ | ||
367 | /* Function: cleanup_module() */ | ||
368 | /* Parameters: None */ | ||
369 | /* Returns: Nothing */ | ||
370 | /* */ | ||
371 | /* Description: */ | ||
372 | /* This is a required entry point for an installable module. It has to return */ | ||
373 | /* the device and the driver to a passive state. It should not be necessary */ | ||
374 | /* to reset the board fully, especially as the loadware is downloaded */ | ||
375 | /* externally rather than in the driver. We just want to disable the board */ | ||
376 | /* and clear the loadware to a reset state. To allow this there has to be a */ | ||
377 | /* way to detect whether the board has the loadware running at init time to */ | ||
378 | /* handle subsequent installations of the driver. All memory allocated by the */ | ||
379 | /* driver should be returned since it may be unloaded from memory. */ | ||
380 | /******************************************************************************/ | ||
381 | static void __exit ip2_cleanup_module(void) | ||
382 | { | ||
383 | int err; | ||
384 | int i; | ||
385 | |||
386 | del_timer_sync(&PollTimer); | ||
387 | |||
388 | /* Reset the boards we have. */ | ||
389 | for (i = 0; i < IP2_MAX_BOARDS; i++) | ||
390 | if (i2BoardPtrTable[i]) | ||
391 | iiReset(i2BoardPtrTable[i]); | ||
392 | |||
393 | /* The following is done at most once, if any boards were installed. */ | ||
394 | for (i = 0; i < IP2_MAX_BOARDS; i++) { | ||
395 | if (i2BoardPtrTable[i]) { | ||
396 | iiResetDelay(i2BoardPtrTable[i]); | ||
397 | /* free io addresses and Tibet */ | ||
398 | release_region(ip2config.addr[i], 8); | ||
399 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); | ||
400 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, | ||
401 | 4 * i + 1)); | ||
402 | } | ||
403 | /* Disable and remove interrupt handler. */ | ||
404 | if (ip2config.irq[i] > 0 && | ||
405 | have_requested_irq(ip2config.irq[i])) { | ||
406 | free_irq(ip2config.irq[i], (void *)&pcName); | ||
407 | clear_requested_irq(ip2config.irq[i]); | ||
408 | } | ||
409 | } | ||
410 | class_destroy(ip2_class); | ||
411 | err = tty_unregister_driver(ip2_tty_driver); | ||
412 | if (err) | ||
413 | printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", | ||
414 | err); | ||
415 | put_tty_driver(ip2_tty_driver); | ||
416 | unregister_chrdev(IP2_IPL_MAJOR, pcIpl); | ||
417 | remove_proc_entry("ip2mem", NULL); | ||
418 | |||
419 | /* free memory */ | ||
420 | for (i = 0; i < IP2_MAX_BOARDS; i++) { | ||
421 | void *pB; | ||
422 | #ifdef CONFIG_PCI | ||
423 | if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { | ||
424 | pci_disable_device(ip2config.pci_dev[i]); | ||
425 | pci_dev_put(ip2config.pci_dev[i]); | ||
426 | ip2config.pci_dev[i] = NULL; | ||
427 | } | ||
428 | #endif | ||
429 | pB = i2BoardPtrTable[i]; | ||
430 | if (pB != NULL) { | ||
431 | kfree(pB); | ||
432 | i2BoardPtrTable[i] = NULL; | ||
433 | } | ||
434 | if (DevTableMem[i] != NULL) { | ||
435 | kfree(DevTableMem[i]); | ||
436 | DevTableMem[i] = NULL; | ||
437 | } | ||
438 | } | ||
439 | } | ||
440 | module_exit(ip2_cleanup_module); | ||
441 | |||
442 | static const struct tty_operations ip2_ops = { | ||
443 | .open = ip2_open, | ||
444 | .close = ip2_close, | ||
445 | .write = ip2_write, | ||
446 | .put_char = ip2_putchar, | ||
447 | .flush_chars = ip2_flush_chars, | ||
448 | .write_room = ip2_write_room, | ||
449 | .chars_in_buffer = ip2_chars_in_buf, | ||
450 | .flush_buffer = ip2_flush_buffer, | ||
451 | .ioctl = ip2_ioctl, | ||
452 | .throttle = ip2_throttle, | ||
453 | .unthrottle = ip2_unthrottle, | ||
454 | .set_termios = ip2_set_termios, | ||
455 | .set_ldisc = ip2_set_line_discipline, | ||
456 | .stop = ip2_stop, | ||
457 | .start = ip2_start, | ||
458 | .hangup = ip2_hangup, | ||
459 | .tiocmget = ip2_tiocmget, | ||
460 | .tiocmset = ip2_tiocmset, | ||
461 | .get_icount = ip2_get_icount, | ||
462 | .proc_fops = &ip2_proc_fops, | ||
463 | }; | ||
464 | |||
465 | /******************************************************************************/ | ||
466 | /* Function: ip2_loadmain() */ | ||
467 | /* Parameters: irq, io from command line of insmod et. al. */ | ||
468 | /* pointer to fip firmware and firmware size for boards */ | ||
469 | /* Returns: Success (0) */ | ||
470 | /* */ | ||
471 | /* Description: */ | ||
472 | /* This was the required entry point for all drivers (now in ip2.c) */ | ||
473 | /* It performs all */ | ||
474 | /* initialisation of the devices and driver structures, and registers itself */ | ||
475 | /* with the relevant kernel modules. */ | ||
476 | /******************************************************************************/ | ||
477 | /* IRQF_DISABLED - if set blocks all interrupts else only this line */ | ||
478 | /* IRQF_SHARED - for shared irq PCI or maybe EISA only */ | ||
479 | /* SA_RANDOM - can be source for cert. random number generators */ | ||
480 | #define IP2_SA_FLAGS 0 | ||
481 | |||
482 | |||
483 | static const struct firmware *ip2_request_firmware(void) | ||
484 | { | ||
485 | struct platform_device *pdev; | ||
486 | const struct firmware *fw; | ||
487 | |||
488 | pdev = platform_device_register_simple("ip2", 0, NULL, 0); | ||
489 | if (IS_ERR(pdev)) { | ||
490 | printk(KERN_ERR "Failed to register platform device for ip2\n"); | ||
491 | return NULL; | ||
492 | } | ||
493 | if (request_firmware(&fw, "intelliport2.bin", &pdev->dev)) { | ||
494 | printk(KERN_ERR "Failed to load firmware 'intelliport2.bin'\n"); | ||
495 | fw = NULL; | ||
496 | } | ||
497 | platform_device_unregister(pdev); | ||
498 | return fw; | ||
499 | } | ||
500 | |||
501 | /****************************************************************************** | ||
502 | * ip2_setup: | ||
503 | * str: kernel command line string | ||
504 | * | ||
505 | * Can't autoprobe the boards so user must specify configuration on | ||
506 | * kernel command line. Sane people build it modular but the others | ||
507 | * come here. | ||
508 | * | ||
509 | * Alternating pairs of io,irq for up to 4 boards. | ||
510 | * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 | ||
511 | * | ||
512 | * io=0 => No board | ||
513 | * io=1 => PCI | ||
514 | * io=2 => EISA | ||
515 | * else => ISA I/O address | ||
516 | * | ||
517 | * irq=0 or invalid for ISA will revert to polling mode | ||
518 | * | ||
519 | * Any value = -1, do not overwrite compiled in value. | ||
520 | * | ||
521 | ******************************************************************************/ | ||
522 | static int __init ip2_setup(char *str) | ||
523 | { | ||
524 | int j, ints[10]; /* 4 boards, 2 parameters + 2 */ | ||
525 | unsigned int i; | ||
526 | |||
527 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
528 | |||
529 | for (i = 0, j = 1; i < 4; i++) { | ||
530 | if (j > ints[0]) | ||
531 | break; | ||
532 | if (ints[j] >= 0) | ||
533 | io[i] = ints[j]; | ||
534 | j++; | ||
535 | if (j > ints[0]) | ||
536 | break; | ||
537 | if (ints[j] >= 0) | ||
538 | irq[i] = ints[j]; | ||
539 | j++; | ||
540 | } | ||
541 | return 1; | ||
542 | } | ||
543 | __setup("ip2=", ip2_setup); | ||
544 | |||
545 | static int __init ip2_loadmain(void) | ||
546 | { | ||
547 | int i, j, box; | ||
548 | int err = 0; | ||
549 | i2eBordStrPtr pB = NULL; | ||
550 | int rc = -1; | ||
551 | const struct firmware *fw = NULL; | ||
552 | char *str; | ||
553 | |||
554 | str = cmd; | ||
555 | |||
556 | if (poll_only) { | ||
557 | /* Hard lock the interrupts to zero */ | ||
558 | irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; | ||
559 | } | ||
560 | |||
561 | /* Check module parameter with 'ip2=' has been passed or not */ | ||
562 | if (!poll_only && (!strncmp(str, "ip2=", 4))) | ||
563 | ip2_setup(str); | ||
564 | |||
565 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); | ||
566 | |||
567 | /* process command line arguments to modprobe or | ||
568 | insmod i.e. iop & irqp */ | ||
569 | /* irqp and iop should ALWAYS be specified now... But we check | ||
570 | them individually just to be sure, anyways... */ | ||
571 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
572 | ip2config.addr[i] = io[i]; | ||
573 | if (irq[i] >= 0) | ||
574 | ip2config.irq[i] = irq[i]; | ||
575 | else | ||
576 | ip2config.irq[i] = 0; | ||
577 | /* This is a little bit of a hack. If poll_only=1 on command | ||
578 | line back in ip2.c OR all IRQs on all specified boards are | ||
579 | explicitly set to 0, then drop to poll only mode and override | ||
580 | PCI or EISA interrupts. This superceeds the old hack of | ||
581 | triggering if all interrupts were zero (like da default). | ||
582 | Still a hack but less prone to random acts of terrorism. | ||
583 | |||
584 | What we really should do, now that the IRQ default is set | ||
585 | to -1, is to use 0 as a hard coded, do not probe. | ||
586 | |||
587 | /\/\|=mhw=|\/\/ | ||
588 | */ | ||
589 | poll_only |= irq[i]; | ||
590 | } | ||
591 | poll_only = !poll_only; | ||
592 | |||
593 | /* Announce our presence */ | ||
594 | printk(KERN_INFO "%s version %s\n", pcName, pcVersion); | ||
595 | |||
596 | ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); | ||
597 | if (!ip2_tty_driver) | ||
598 | return -ENOMEM; | ||
599 | |||
600 | /* Initialise all the boards we can find (up to the maximum). */ | ||
601 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
602 | switch (ip2config.addr[i]) { | ||
603 | case 0: /* skip this slot even if card is present */ | ||
604 | break; | ||
605 | default: /* ISA */ | ||
606 | /* ISA address must be specified */ | ||
607 | if (ip2config.addr[i] < 0x100 || | ||
608 | ip2config.addr[i] > 0x3f8) { | ||
609 | printk(KERN_ERR "IP2: Bad ISA board %d " | ||
610 | "address %x\n", i, | ||
611 | ip2config.addr[i]); | ||
612 | ip2config.addr[i] = 0; | ||
613 | break; | ||
614 | } | ||
615 | ip2config.type[i] = ISA; | ||
616 | |||
617 | /* Check for valid irq argument, set for polling if | ||
618 | * invalid */ | ||
619 | if (ip2config.irq[i] && | ||
620 | !is_valid_irq(ip2config.irq[i])) { | ||
621 | printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n", | ||
622 | ip2config.irq[i]); | ||
623 | /* 0 is polling and is valid in that sense */ | ||
624 | ip2config.irq[i] = 0; | ||
625 | } | ||
626 | break; | ||
627 | case PCI: | ||
628 | #ifdef CONFIG_PCI | ||
629 | { | ||
630 | struct pci_dev *pdev = NULL; | ||
631 | u32 addr; | ||
632 | int status; | ||
633 | |||
634 | pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE, | ||
635 | PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev); | ||
636 | if (pdev == NULL) { | ||
637 | ip2config.addr[i] = 0; | ||
638 | printk(KERN_ERR "IP2: PCI board %d not " | ||
639 | "found\n", i); | ||
640 | break; | ||
641 | } | ||
642 | |||
643 | if (pci_enable_device(pdev)) { | ||
644 | dev_err(&pdev->dev, "can't enable device\n"); | ||
645 | goto out; | ||
646 | } | ||
647 | ip2config.type[i] = PCI; | ||
648 | ip2config.pci_dev[i] = pci_dev_get(pdev); | ||
649 | status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, | ||
650 | &addr); | ||
651 | if (addr & 1) | ||
652 | ip2config.addr[i] = (USHORT)(addr & 0xfffe); | ||
653 | else | ||
654 | dev_err(&pdev->dev, "I/O address error\n"); | ||
655 | |||
656 | ip2config.irq[i] = pdev->irq; | ||
657 | out: | ||
658 | pci_dev_put(pdev); | ||
659 | } | ||
660 | #else | ||
661 | printk(KERN_ERR "IP2: PCI card specified but PCI " | ||
662 | "support not enabled.\n"); | ||
663 | printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI " | ||
664 | "defined!\n"); | ||
665 | #endif /* CONFIG_PCI */ | ||
666 | break; | ||
667 | case EISA: | ||
668 | ip2config.addr[i] = find_eisa_board(Eisa_slot + 1); | ||
669 | if (ip2config.addr[i] != 0) { | ||
670 | /* Eisa_irq set as side effect, boo */ | ||
671 | ip2config.type[i] = EISA; | ||
672 | } | ||
673 | ip2config.irq[i] = Eisa_irq; | ||
674 | break; | ||
675 | } /* switch */ | ||
676 | } /* for */ | ||
677 | |||
678 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
679 | if (ip2config.addr[i]) { | ||
680 | pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL); | ||
681 | if (pB) { | ||
682 | i2BoardPtrTable[i] = pB; | ||
683 | iiSetAddress(pB, ip2config.addr[i], | ||
684 | ii2DelayTimer); | ||
685 | iiReset(pB); | ||
686 | } else | ||
687 | printk(KERN_ERR "IP2: board memory allocation " | ||
688 | "error\n"); | ||
689 | } | ||
690 | } | ||
691 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
692 | pB = i2BoardPtrTable[i]; | ||
693 | if (pB != NULL) { | ||
694 | iiResetDelay(pB); | ||
695 | break; | ||
696 | } | ||
697 | } | ||
698 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
699 | /* We don't want to request the firmware unless we have at | ||
700 | least one board */ | ||
701 | if (i2BoardPtrTable[i] != NULL) { | ||
702 | if (!fw) | ||
703 | fw = ip2_request_firmware(); | ||
704 | if (!fw) | ||
705 | break; | ||
706 | ip2_init_board(i, fw); | ||
707 | } | ||
708 | } | ||
709 | if (fw) | ||
710 | release_firmware(fw); | ||
711 | |||
712 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0); | ||
713 | |||
714 | ip2_tty_driver->owner = THIS_MODULE; | ||
715 | ip2_tty_driver->name = "ttyF"; | ||
716 | ip2_tty_driver->driver_name = pcDriver_name; | ||
717 | ip2_tty_driver->major = IP2_TTY_MAJOR; | ||
718 | ip2_tty_driver->minor_start = 0; | ||
719 | ip2_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
720 | ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; | ||
721 | ip2_tty_driver->init_termios = tty_std_termios; | ||
722 | ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; | ||
723 | ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | | ||
724 | TTY_DRIVER_DYNAMIC_DEV; | ||
725 | tty_set_operations(ip2_tty_driver, &ip2_ops); | ||
726 | |||
727 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0); | ||
728 | |||
729 | err = tty_register_driver(ip2_tty_driver); | ||
730 | if (err) { | ||
731 | printk(KERN_ERR "IP2: failed to register tty driver\n"); | ||
732 | put_tty_driver(ip2_tty_driver); | ||
733 | return err; /* leaking resources */ | ||
734 | } | ||
735 | |||
736 | err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl); | ||
737 | if (err) { | ||
738 | printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", | ||
739 | err); | ||
740 | } else { | ||
741 | /* create the sysfs class */ | ||
742 | ip2_class = class_create(THIS_MODULE, "ip2"); | ||
743 | if (IS_ERR(ip2_class)) { | ||
744 | err = PTR_ERR(ip2_class); | ||
745 | goto out_chrdev; | ||
746 | } | ||
747 | } | ||
748 | /* Register the read_procmem thing */ | ||
749 | if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) { | ||
750 | printk(KERN_ERR "IP2: failed to register read_procmem\n"); | ||
751 | return -EIO; /* leaking resources */ | ||
752 | } | ||
753 | |||
754 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0); | ||
755 | /* Register the interrupt handler or poll handler, depending upon the | ||
756 | * specified interrupt. | ||
757 | */ | ||
758 | |||
759 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
760 | if (ip2config.addr[i] == 0) | ||
761 | continue; | ||
762 | |||
763 | pB = i2BoardPtrTable[i]; | ||
764 | if (pB != NULL) { | ||
765 | device_create(ip2_class, NULL, | ||
766 | MKDEV(IP2_IPL_MAJOR, 4 * i), | ||
767 | NULL, "ipl%d", i); | ||
768 | device_create(ip2_class, NULL, | ||
769 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), | ||
770 | NULL, "stat%d", i); | ||
771 | |||
772 | for (box = 0; box < ABS_MAX_BOXES; box++) | ||
773 | for (j = 0; j < ABS_BIGGEST_BOX; j++) | ||
774 | if (pB->i2eChannelMap[box] & (1 << j)) | ||
775 | tty_register_device( | ||
776 | ip2_tty_driver, | ||
777 | j + ABS_BIGGEST_BOX * | ||
778 | (box+i*ABS_MAX_BOXES), | ||
779 | NULL); | ||
780 | } | ||
781 | |||
782 | if (poll_only) { | ||
783 | /* Poll only forces driver to only use polling and | ||
784 | to ignore the probed PCI or EISA interrupts. */ | ||
785 | ip2config.irq[i] = CIR_POLL; | ||
786 | } | ||
787 | if (ip2config.irq[i] == CIR_POLL) { | ||
788 | retry: | ||
789 | if (!timer_pending(&PollTimer)) { | ||
790 | mod_timer(&PollTimer, POLL_TIMEOUT); | ||
791 | printk(KERN_INFO "IP2: polling\n"); | ||
792 | } | ||
793 | } else { | ||
794 | if (have_requested_irq(ip2config.irq[i])) | ||
795 | continue; | ||
796 | rc = request_irq(ip2config.irq[i], ip2_interrupt, | ||
797 | IP2_SA_FLAGS | | ||
798 | (ip2config.type[i] == PCI ? IRQF_SHARED : 0), | ||
799 | pcName, i2BoardPtrTable[i]); | ||
800 | if (rc) { | ||
801 | printk(KERN_ERR "IP2: request_irq failed: " | ||
802 | "error %d\n", rc); | ||
803 | ip2config.irq[i] = CIR_POLL; | ||
804 | printk(KERN_INFO "IP2: Polling %ld/sec.\n", | ||
805 | (POLL_TIMEOUT - jiffies)); | ||
806 | goto retry; | ||
807 | } | ||
808 | mark_requested_irq(ip2config.irq[i]); | ||
809 | /* Initialise the interrupt handler bottom half | ||
810 | * (aka slih). */ | ||
811 | } | ||
812 | } | ||
813 | |||
814 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { | ||
815 | if (i2BoardPtrTable[i]) { | ||
816 | /* set and enable board interrupt */ | ||
817 | set_irq(i, ip2config.irq[i]); | ||
818 | } | ||
819 | } | ||
820 | |||
821 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0); | ||
822 | |||
823 | return 0; | ||
824 | |||
825 | out_chrdev: | ||
826 | unregister_chrdev(IP2_IPL_MAJOR, "ip2"); | ||
827 | /* unregister and put tty here */ | ||
828 | return err; | ||
829 | } | ||
830 | module_init(ip2_loadmain); | ||
831 | |||
832 | /******************************************************************************/ | ||
833 | /* Function: ip2_init_board() */ | ||
834 | /* Parameters: Index of board in configuration structure */ | ||
835 | /* Returns: Success (0) */ | ||
836 | /* */ | ||
837 | /* Description: */ | ||
838 | /* This function initializes the specified board. The loadware is copied to */ | ||
839 | /* the board, the channel structures are initialized, and the board details */ | ||
840 | /* are reported on the console. */ | ||
841 | /******************************************************************************/ | ||
842 | static void | ||
843 | ip2_init_board(int boardnum, const struct firmware *fw) | ||
844 | { | ||
845 | int i; | ||
846 | int nports = 0, nboxes = 0; | ||
847 | i2ChanStrPtr pCh; | ||
848 | i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; | ||
849 | |||
850 | if ( !iiInitialize ( pB ) ) { | ||
851 | printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n", | ||
852 | pB->i2eBase, pB->i2eError ); | ||
853 | goto err_initialize; | ||
854 | } | ||
855 | printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1, | ||
856 | ip2config.addr[boardnum], ip2config.irq[boardnum] ); | ||
857 | |||
858 | if (!request_region( ip2config.addr[boardnum], 8, pcName )) { | ||
859 | printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]); | ||
860 | goto err_initialize; | ||
861 | } | ||
862 | |||
863 | if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size ) | ||
864 | != II_DOWN_GOOD ) { | ||
865 | printk ( KERN_ERR "IP2: failed to download loadware\n" ); | ||
866 | goto err_release_region; | ||
867 | } else { | ||
868 | printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n", | ||
869 | pB->i2ePom.e.porVersion, | ||
870 | pB->i2ePom.e.porRevision, | ||
871 | pB->i2ePom.e.porSubRev, pB->i2eLVersion, | ||
872 | pB->i2eLRevision, pB->i2eLSub ); | ||
873 | } | ||
874 | |||
875 | switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) { | ||
876 | |||
877 | default: | ||
878 | printk( KERN_ERR "IP2: Unknown board type, ID = %x\n", | ||
879 | pB->i2ePom.e.porID ); | ||
880 | nports = 0; | ||
881 | goto err_release_region; | ||
882 | break; | ||
883 | |||
884 | case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */ | ||
885 | printk ( KERN_INFO "IP2: ISA-4\n" ); | ||
886 | nports = 4; | ||
887 | break; | ||
888 | |||
889 | case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */ | ||
890 | printk ( KERN_INFO "IP2: ISA-8 std\n" ); | ||
891 | nports = 8; | ||
892 | break; | ||
893 | |||
894 | case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */ | ||
895 | printk ( KERN_INFO "IP2: ISA-8 RJ11\n" ); | ||
896 | nports = 8; | ||
897 | break; | ||
898 | |||
899 | case POR_ID_FIIEX: /* IntelliPort IIEX */ | ||
900 | { | ||
901 | int portnum = IP2_PORTS_PER_BOARD * boardnum; | ||
902 | int box; | ||
903 | |||
904 | for( box = 0; box < ABS_MAX_BOXES; ++box ) { | ||
905 | if ( pB->i2eChannelMap[box] != 0 ) { | ||
906 | ++nboxes; | ||
907 | } | ||
908 | for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { | ||
909 | if ( pB->i2eChannelMap[box] & 1<< i ) { | ||
910 | ++nports; | ||
911 | } | ||
912 | } | ||
913 | } | ||
914 | DevTableMem[boardnum] = pCh = | ||
915 | kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL ); | ||
916 | if ( !pCh ) { | ||
917 | printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); | ||
918 | goto err_release_region; | ||
919 | } | ||
920 | if ( !i2InitChannels( pB, nports, pCh ) ) { | ||
921 | printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); | ||
922 | kfree ( pCh ); | ||
923 | goto err_release_region; | ||
924 | } | ||
925 | pB->i2eChannelPtr = &DevTable[portnum]; | ||
926 | pB->i2eChannelCnt = ABS_MOST_PORTS; | ||
927 | |||
928 | for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) { | ||
929 | for( i = 0; i < ABS_BIGGEST_BOX; ++i ) { | ||
930 | if ( pB->i2eChannelMap[box] & (1 << i) ) { | ||
931 | DevTable[portnum + i] = pCh; | ||
932 | pCh->port_index = portnum + i; | ||
933 | pCh++; | ||
934 | } | ||
935 | } | ||
936 | } | ||
937 | printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n", | ||
938 | nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 ); | ||
939 | } | ||
940 | goto ex_exit; | ||
941 | } | ||
942 | DevTableMem[boardnum] = pCh = | ||
943 | kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL ); | ||
944 | if ( !pCh ) { | ||
945 | printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n"); | ||
946 | goto err_release_region; | ||
947 | } | ||
948 | pB->i2eChannelPtr = pCh; | ||
949 | pB->i2eChannelCnt = nports; | ||
950 | if ( !i2InitChannels( pB, nports, pCh ) ) { | ||
951 | printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError); | ||
952 | kfree ( pCh ); | ||
953 | goto err_release_region; | ||
954 | } | ||
955 | pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum]; | ||
956 | |||
957 | for( i = 0; i < pB->i2eChannelCnt; ++i ) { | ||
958 | DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh; | ||
959 | pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i; | ||
960 | pCh++; | ||
961 | } | ||
962 | ex_exit: | ||
963 | INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh); | ||
964 | return; | ||
965 | |||
966 | err_release_region: | ||
967 | release_region(ip2config.addr[boardnum], 8); | ||
968 | err_initialize: | ||
969 | kfree ( pB ); | ||
970 | i2BoardPtrTable[boardnum] = NULL; | ||
971 | return; | ||
972 | } | ||
973 | |||
974 | /******************************************************************************/ | ||
975 | /* Function: find_eisa_board ( int start_slot ) */ | ||
976 | /* Parameters: First slot to check */ | ||
977 | /* Returns: Address of EISA IntelliPort II controller */ | ||
978 | /* */ | ||
979 | /* Description: */ | ||
980 | /* This function searches for an EISA IntelliPort controller, starting */ | ||
981 | /* from the specified slot number. If the motherboard is not identified as an */ | ||
982 | /* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */ | ||
983 | /* it returns the base address of the controller. */ | ||
984 | /******************************************************************************/ | ||
985 | static unsigned short | ||
986 | find_eisa_board( int start_slot ) | ||
987 | { | ||
988 | int i, j; | ||
989 | unsigned int idm = 0; | ||
990 | unsigned int idp = 0; | ||
991 | unsigned int base = 0; | ||
992 | unsigned int value; | ||
993 | int setup_address; | ||
994 | int setup_irq; | ||
995 | int ismine = 0; | ||
996 | |||
997 | /* | ||
998 | * First a check for an EISA motherboard, which we do by comparing the | ||
999 | * EISA ID registers for the system board and the first couple of slots. | ||
1000 | * No slot ID should match the system board ID, but on an ISA or PCI | ||
1001 | * machine the odds are that an empty bus will return similar values for | ||
1002 | * each slot. | ||
1003 | */ | ||
1004 | i = 0x0c80; | ||
1005 | value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3); | ||
1006 | for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) { | ||
1007 | j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3); | ||
1008 | if ( value == j ) | ||
1009 | return 0; | ||
1010 | } | ||
1011 | |||
1012 | /* | ||
1013 | * OK, so we are inclined to believe that this is an EISA machine. Find | ||
1014 | * an IntelliPort controller. | ||
1015 | */ | ||
1016 | for( i = start_slot; i < 16; i++ ) { | ||
1017 | base = i << 12; | ||
1018 | idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff); | ||
1019 | idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff); | ||
1020 | ismine = 0; | ||
1021 | if ( idm == 0x0e8e ) { | ||
1022 | if ( idp == 0x0281 || idp == 0x0218 ) { | ||
1023 | ismine = 1; | ||
1024 | } else if ( idp == 0x0282 || idp == 0x0283 ) { | ||
1025 | ismine = 3; /* Can do edge-trigger */ | ||
1026 | } | ||
1027 | if ( ismine ) { | ||
1028 | Eisa_slot = i; | ||
1029 | break; | ||
1030 | } | ||
1031 | } | ||
1032 | } | ||
1033 | if ( !ismine ) | ||
1034 | return 0; | ||
1035 | |||
1036 | /* It's some sort of EISA card, but at what address is it configured? */ | ||
1037 | |||
1038 | setup_address = base + 0xc88; | ||
1039 | value = inb(base + 0xc86); | ||
1040 | setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0; | ||
1041 | |||
1042 | if ( (ismine & 2) && !(value & 0x10) ) { | ||
1043 | ismine = 1; /* Could be edging, but not */ | ||
1044 | } | ||
1045 | |||
1046 | if ( Eisa_irq == 0 ) { | ||
1047 | Eisa_irq = setup_irq; | ||
1048 | } else if ( Eisa_irq != setup_irq ) { | ||
1049 | printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" ); | ||
1050 | } | ||
1051 | |||
1052 | #ifdef IP2DEBUG_INIT | ||
1053 | printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x", | ||
1054 | base >> 12, idm, idp, setup_address); | ||
1055 | if ( Eisa_irq ) { | ||
1056 | printk(KERN_DEBUG ", Interrupt %d %s\n", | ||
1057 | setup_irq, (ismine & 2) ? "(edge)" : "(level)"); | ||
1058 | } else { | ||
1059 | printk(KERN_DEBUG ", (polled)\n"); | ||
1060 | } | ||
1061 | #endif | ||
1062 | return setup_address; | ||
1063 | } | ||
1064 | |||
1065 | /******************************************************************************/ | ||
1066 | /* Function: set_irq() */ | ||
1067 | /* Parameters: index to board in board table */ | ||
1068 | /* IRQ to use */ | ||
1069 | /* Returns: Success (0) */ | ||
1070 | /* */ | ||
1071 | /* Description: */ | ||
1072 | /******************************************************************************/ | ||
1073 | static void | ||
1074 | set_irq( int boardnum, int boardIrq ) | ||
1075 | { | ||
1076 | unsigned char tempCommand[16]; | ||
1077 | i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; | ||
1078 | unsigned long flags; | ||
1079 | |||
1080 | /* | ||
1081 | * Notify the boards they may generate interrupts. This is done by | ||
1082 | * sending an in-line command to channel 0 on each board. This is why | ||
1083 | * the channels have to be defined already. For each board, if the | ||
1084 | * interrupt has never been defined, we must do so NOW, directly, since | ||
1085 | * board will not send flow control or even give an interrupt until this | ||
1086 | * is done. If polling we must send 0 as the interrupt parameter. | ||
1087 | */ | ||
1088 | |||
1089 | // We will get an interrupt here at the end of this function | ||
1090 | |||
1091 | iiDisableMailIrq(pB); | ||
1092 | |||
1093 | /* We build up the entire packet header. */ | ||
1094 | CHANNEL_OF(tempCommand) = 0; | ||
1095 | PTYPE_OF(tempCommand) = PTYPE_INLINE; | ||
1096 | CMD_COUNT_OF(tempCommand) = 2; | ||
1097 | (CMD_OF(tempCommand))[0] = CMDVALUE_IRQ; | ||
1098 | (CMD_OF(tempCommand))[1] = boardIrq; | ||
1099 | /* | ||
1100 | * Write to FIFO; don't bother to adjust fifo capacity for this, since | ||
1101 | * board will respond almost immediately after SendMail hit. | ||
1102 | */ | ||
1103 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
1104 | iiWriteBuf(pB, tempCommand, 4); | ||
1105 | write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); | ||
1106 | pB->i2eUsingIrq = boardIrq; | ||
1107 | pB->i2eOutMailWaiting |= MB_OUT_STUFFED; | ||
1108 | |||
1109 | /* Need to update number of boards before you enable mailbox int */ | ||
1110 | ++i2nBoards; | ||
1111 | |||
1112 | CHANNEL_OF(tempCommand) = 0; | ||
1113 | PTYPE_OF(tempCommand) = PTYPE_BYPASS; | ||
1114 | CMD_COUNT_OF(tempCommand) = 6; | ||
1115 | (CMD_OF(tempCommand))[0] = 88; // SILO | ||
1116 | (CMD_OF(tempCommand))[1] = 64; // chars | ||
1117 | (CMD_OF(tempCommand))[2] = 32; // ms | ||
1118 | |||
1119 | (CMD_OF(tempCommand))[3] = 28; // MAX_BLOCK | ||
1120 | (CMD_OF(tempCommand))[4] = 64; // chars | ||
1121 | |||
1122 | (CMD_OF(tempCommand))[5] = 87; // HW_TEST | ||
1123 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
1124 | iiWriteBuf(pB, tempCommand, 8); | ||
1125 | write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); | ||
1126 | |||
1127 | CHANNEL_OF(tempCommand) = 0; | ||
1128 | PTYPE_OF(tempCommand) = PTYPE_BYPASS; | ||
1129 | CMD_COUNT_OF(tempCommand) = 1; | ||
1130 | (CMD_OF(tempCommand))[0] = 84; /* get BOX_IDS */ | ||
1131 | iiWriteBuf(pB, tempCommand, 3); | ||
1132 | |||
1133 | #ifdef XXX | ||
1134 | // enable heartbeat for test porpoises | ||
1135 | CHANNEL_OF(tempCommand) = 0; | ||
1136 | PTYPE_OF(tempCommand) = PTYPE_BYPASS; | ||
1137 | CMD_COUNT_OF(tempCommand) = 2; | ||
1138 | (CMD_OF(tempCommand))[0] = 44; /* get ping */ | ||
1139 | (CMD_OF(tempCommand))[1] = 200; /* 200 ms */ | ||
1140 | write_lock_irqsave(&pB->write_fifo_spinlock, flags); | ||
1141 | iiWriteBuf(pB, tempCommand, 4); | ||
1142 | write_unlock_irqrestore(&pB->write_fifo_spinlock, flags); | ||
1143 | #endif | ||
1144 | |||
1145 | iiEnableMailIrq(pB); | ||
1146 | iiSendPendingMail(pB); | ||
1147 | } | ||
1148 | |||
1149 | /******************************************************************************/ | ||
1150 | /* Interrupt Handler Section */ | ||
1151 | /******************************************************************************/ | ||
1152 | |||
1153 | static inline void | ||
1154 | service_all_boards(void) | ||
1155 | { | ||
1156 | int i; | ||
1157 | i2eBordStrPtr pB; | ||
1158 | |||
1159 | /* Service every board on the list */ | ||
1160 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | ||
1161 | pB = i2BoardPtrTable[i]; | ||
1162 | if ( pB ) { | ||
1163 | i2ServiceBoard( pB ); | ||
1164 | } | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | |||
1169 | /******************************************************************************/ | ||
1170 | /* Function: ip2_interrupt_bh(work) */ | ||
1171 | /* Parameters: work - pointer to the board structure */ | ||
1172 | /* Returns: Nothing */ | ||
1173 | /* */ | ||
1174 | /* Description: */ | ||
1175 | /* Service the board in a bottom half interrupt handler and then */ | ||
1176 | /* reenable the board's interrupts if it has an IRQ number */ | ||
1177 | /* */ | ||
1178 | /******************************************************************************/ | ||
1179 | static void | ||
1180 | ip2_interrupt_bh(struct work_struct *work) | ||
1181 | { | ||
1182 | i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt); | ||
1183 | // pB better well be set or we have a problem! We can only get | ||
1184 | // here from the IMMEDIATE queue. Here, we process the boards. | ||
1185 | // Checking pB doesn't cost much and it saves us from the sanity checkers. | ||
1186 | |||
1187 | bh_counter++; | ||
1188 | |||
1189 | if ( pB ) { | ||
1190 | i2ServiceBoard( pB ); | ||
1191 | if( pB->i2eUsingIrq ) { | ||
1192 | // Re-enable his interrupts | ||
1193 | iiEnableMailIrq(pB); | ||
1194 | } | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | |||
1199 | /******************************************************************************/ | ||
1200 | /* Function: ip2_interrupt(int irq, void *dev_id) */ | ||
1201 | /* Parameters: irq - interrupt number */ | ||
1202 | /* pointer to optional device ID structure */ | ||
1203 | /* Returns: Nothing */ | ||
1204 | /* */ | ||
1205 | /* Description: */ | ||
1206 | /* */ | ||
1207 | /* Our task here is simply to identify each board which needs servicing. */ | ||
1208 | /* If we are queuing then, queue it to be serviced, and disable its irq */ | ||
1209 | /* mask otherwise process the board directly. */ | ||
1210 | /* */ | ||
1211 | /* We could queue by IRQ but that just complicates things on both ends */ | ||
1212 | /* with very little gain in performance (how many instructions does */ | ||
1213 | /* it take to iterate on the immediate queue). */ | ||
1214 | /* */ | ||
1215 | /* */ | ||
1216 | /******************************************************************************/ | ||
1217 | static void | ||
1218 | ip2_irq_work(i2eBordStrPtr pB) | ||
1219 | { | ||
1220 | #ifdef USE_IQI | ||
1221 | if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) { | ||
1222 | // Disable his interrupt (will be enabled when serviced) | ||
1223 | // This is mostly to protect from reentrancy. | ||
1224 | iiDisableMailIrq(pB); | ||
1225 | |||
1226 | // Park the board on the immediate queue for processing. | ||
1227 | schedule_work(&pB->tqueue_interrupt); | ||
1228 | |||
1229 | // Make sure the immediate queue is flagged to fire. | ||
1230 | } | ||
1231 | #else | ||
1232 | |||
1233 | // We are using immediate servicing here. This sucks and can | ||
1234 | // cause all sorts of havoc with ppp and others. The failsafe | ||
1235 | // check on iiSendPendingMail could also throw a hairball. | ||
1236 | |||
1237 | i2ServiceBoard( pB ); | ||
1238 | |||
1239 | #endif /* USE_IQI */ | ||
1240 | } | ||
1241 | |||
1242 | static void | ||
1243 | ip2_polled_interrupt(void) | ||
1244 | { | ||
1245 | int i; | ||
1246 | i2eBordStrPtr pB; | ||
1247 | |||
1248 | ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0); | ||
1249 | |||
1250 | /* Service just the boards on the list using this irq */ | ||
1251 | for( i = 0; i < i2nBoards; ++i ) { | ||
1252 | pB = i2BoardPtrTable[i]; | ||
1253 | |||
1254 | // Only process those boards which match our IRQ. | ||
1255 | // IRQ = 0 for polled boards, we won't poll "IRQ" boards | ||
1256 | |||
1257 | if (pB && pB->i2eUsingIrq == 0) | ||
1258 | ip2_irq_work(pB); | ||
1259 | } | ||
1260 | |||
1261 | ++irq_counter; | ||
1262 | |||
1263 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); | ||
1264 | } | ||
1265 | |||
1266 | static irqreturn_t | ||
1267 | ip2_interrupt(int irq, void *dev_id) | ||
1268 | { | ||
1269 | i2eBordStrPtr pB = dev_id; | ||
1270 | |||
1271 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq ); | ||
1272 | |||
1273 | ip2_irq_work(pB); | ||
1274 | |||
1275 | ++irq_counter; | ||
1276 | |||
1277 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); | ||
1278 | return IRQ_HANDLED; | ||
1279 | } | ||
1280 | |||
1281 | /******************************************************************************/ | ||
1282 | /* Function: ip2_poll(unsigned long arg) */ | ||
1283 | /* Parameters: ? */ | ||
1284 | /* Returns: Nothing */ | ||
1285 | /* */ | ||
1286 | /* Description: */ | ||
1287 | /* This function calls the library routine i2ServiceBoard for each board in */ | ||
1288 | /* the board table. This is used instead of the interrupt routine when polled */ | ||
1289 | /* mode is specified. */ | ||
1290 | /******************************************************************************/ | ||
1291 | static void | ||
1292 | ip2_poll(unsigned long arg) | ||
1293 | { | ||
1294 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); | ||
1295 | |||
1296 | // Just polled boards, IRQ = 0 will hit all non-interrupt boards. | ||
1297 | // It will NOT poll boards handled by hard interrupts. | ||
1298 | // The issue of queued BH interrupts is handled in ip2_interrupt(). | ||
1299 | ip2_polled_interrupt(); | ||
1300 | |||
1301 | mod_timer(&PollTimer, POLL_TIMEOUT); | ||
1302 | |||
1303 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); | ||
1304 | } | ||
1305 | |||
1306 | static void do_input(struct work_struct *work) | ||
1307 | { | ||
1308 | i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input); | ||
1309 | unsigned long flags; | ||
1310 | |||
1311 | ip2trace(CHANN, ITRC_INPUT, 21, 0 ); | ||
1312 | |||
1313 | // Data input | ||
1314 | if ( pCh->pTTY != NULL ) { | ||
1315 | read_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
1316 | if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) { | ||
1317 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
1318 | i2Input( pCh ); | ||
1319 | } else | ||
1320 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
1321 | } else { | ||
1322 | ip2trace(CHANN, ITRC_INPUT, 22, 0 ); | ||
1323 | |||
1324 | i2InputFlush( pCh ); | ||
1325 | } | ||
1326 | } | ||
1327 | |||
1328 | // code duplicated from n_tty (ldisc) | ||
1329 | static inline void isig(int sig, struct tty_struct *tty, int flush) | ||
1330 | { | ||
1331 | /* FIXME: This is completely bogus */ | ||
1332 | if (tty->pgrp) | ||
1333 | kill_pgrp(tty->pgrp, sig, 1); | ||
1334 | if (flush || !L_NOFLSH(tty)) { | ||
1335 | if ( tty->ldisc->ops->flush_buffer ) | ||
1336 | tty->ldisc->ops->flush_buffer(tty); | ||
1337 | i2InputFlush( tty->driver_data ); | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | static void do_status(struct work_struct *work) | ||
1342 | { | ||
1343 | i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status); | ||
1344 | int status; | ||
1345 | |||
1346 | status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) ); | ||
1347 | |||
1348 | ip2trace (CHANN, ITRC_STATUS, 21, 1, status ); | ||
1349 | |||
1350 | if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) { | ||
1351 | if ( (status & I2_BRK) ) { | ||
1352 | // code duplicated from n_tty (ldisc) | ||
1353 | if (I_IGNBRK(pCh->pTTY)) | ||
1354 | goto skip_this; | ||
1355 | if (I_BRKINT(pCh->pTTY)) { | ||
1356 | isig(SIGINT, pCh->pTTY, 1); | ||
1357 | goto skip_this; | ||
1358 | } | ||
1359 | wake_up_interruptible(&pCh->pTTY->read_wait); | ||
1360 | } | ||
1361 | #ifdef NEVER_HAPPENS_AS_SETUP_XXX | ||
1362 | // and can't work because we don't know the_char | ||
1363 | // as the_char is reported on a separate path | ||
1364 | // The intelligent board does this stuff as setup | ||
1365 | { | ||
1366 | char brkf = TTY_NORMAL; | ||
1367 | unsigned char brkc = '\0'; | ||
1368 | unsigned char tmp; | ||
1369 | if ( (status & I2_BRK) ) { | ||
1370 | brkf = TTY_BREAK; | ||
1371 | brkc = '\0'; | ||
1372 | } | ||
1373 | else if (status & I2_PAR) { | ||
1374 | brkf = TTY_PARITY; | ||
1375 | brkc = the_char; | ||
1376 | } else if (status & I2_FRA) { | ||
1377 | brkf = TTY_FRAME; | ||
1378 | brkc = the_char; | ||
1379 | } else if (status & I2_OVR) { | ||
1380 | brkf = TTY_OVERRUN; | ||
1381 | brkc = the_char; | ||
1382 | } | ||
1383 | tmp = pCh->pTTY->real_raw; | ||
1384 | pCh->pTTY->real_raw = 0; | ||
1385 | pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 ); | ||
1386 | pCh->pTTY->real_raw = tmp; | ||
1387 | } | ||
1388 | #endif /* NEVER_HAPPENS_AS_SETUP_XXX */ | ||
1389 | } | ||
1390 | skip_this: | ||
1391 | |||
1392 | if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) { | ||
1393 | wake_up_interruptible(&pCh->delta_msr_wait); | ||
1394 | |||
1395 | if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) { | ||
1396 | if ( status & I2_DCD ) { | ||
1397 | if ( pCh->wopen ) { | ||
1398 | wake_up_interruptible ( &pCh->open_wait ); | ||
1399 | } | ||
1400 | } else { | ||
1401 | if (pCh->pTTY && (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) { | ||
1402 | tty_hangup( pCh->pTTY ); | ||
1403 | } | ||
1404 | } | ||
1405 | } | ||
1406 | } | ||
1407 | |||
1408 | ip2trace (CHANN, ITRC_STATUS, 26, 0 ); | ||
1409 | } | ||
1410 | |||
1411 | /******************************************************************************/ | ||
1412 | /* Device Open/Close/Ioctl Entry Point Section */ | ||
1413 | /******************************************************************************/ | ||
1414 | |||
1415 | /******************************************************************************/ | ||
1416 | /* Function: open_sanity_check() */ | ||
1417 | /* Parameters: Pointer to tty structure */ | ||
1418 | /* Pointer to file structure */ | ||
1419 | /* Returns: Success or failure */ | ||
1420 | /* */ | ||
1421 | /* Description: */ | ||
1422 | /* Verifies the structure magic numbers and cross links. */ | ||
1423 | /******************************************************************************/ | ||
1424 | #ifdef IP2DEBUG_OPEN | ||
1425 | static void | ||
1426 | open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd ) | ||
1427 | { | ||
1428 | if ( pBrd->i2eValid != I2E_MAGIC ) { | ||
1429 | printk(KERN_ERR "IP2: invalid board structure\n" ); | ||
1430 | } else if ( pBrd != pCh->pMyBord ) { | ||
1431 | printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n", | ||
1432 | pCh->pMyBord ); | ||
1433 | } else if ( pBrd->i2eChannelCnt < pCh->port_index ) { | ||
1434 | printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index ); | ||
1435 | } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) { | ||
1436 | } else { | ||
1437 | printk(KERN_INFO "IP2: all pointers check out!\n" ); | ||
1438 | } | ||
1439 | } | ||
1440 | #endif | ||
1441 | |||
1442 | |||
1443 | /******************************************************************************/ | ||
1444 | /* Function: ip2_open() */ | ||
1445 | /* Parameters: Pointer to tty structure */ | ||
1446 | /* Pointer to file structure */ | ||
1447 | /* Returns: Success or failure */ | ||
1448 | /* */ | ||
1449 | /* Description: (MANDATORY) */ | ||
1450 | /* A successful device open has to run a gauntlet of checks before it */ | ||
1451 | /* completes. After some sanity checking and pointer setup, the function */ | ||
1452 | /* blocks until all conditions are satisfied. It then initialises the port to */ | ||
1453 | /* the default characteristics and returns. */ | ||
1454 | /******************************************************************************/ | ||
1455 | static int | ||
1456 | ip2_open( PTTY tty, struct file *pFile ) | ||
1457 | { | ||
1458 | wait_queue_t wait; | ||
1459 | int rc = 0; | ||
1460 | int do_clocal = 0; | ||
1461 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
1462 | |||
1463 | ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 ); | ||
1464 | |||
1465 | if ( pCh == NULL ) { | ||
1466 | return -ENODEV; | ||
1467 | } | ||
1468 | /* Setup pointer links in device and tty structures */ | ||
1469 | pCh->pTTY = tty; | ||
1470 | tty->driver_data = pCh; | ||
1471 | |||
1472 | #ifdef IP2DEBUG_OPEN | ||
1473 | printk(KERN_DEBUG \ | ||
1474 | "IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n", | ||
1475 | tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index); | ||
1476 | open_sanity_check ( pCh, pCh->pMyBord ); | ||
1477 | #endif | ||
1478 | |||
1479 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP); | ||
1480 | pCh->dataSetOut |= (I2_DTR | I2_RTS); | ||
1481 | serviceOutgoingFifo( pCh->pMyBord ); | ||
1482 | |||
1483 | /* Block here until the port is ready (per serial and istallion) */ | ||
1484 | /* | ||
1485 | * 1. If the port is in the middle of closing wait for the completion | ||
1486 | * and then return the appropriate error. | ||
1487 | */ | ||
1488 | init_waitqueue_entry(&wait, current); | ||
1489 | add_wait_queue(&pCh->close_wait, &wait); | ||
1490 | set_current_state( TASK_INTERRUPTIBLE ); | ||
1491 | |||
1492 | if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { | ||
1493 | if ( pCh->flags & ASYNC_CLOSING ) { | ||
1494 | tty_unlock(); | ||
1495 | schedule(); | ||
1496 | tty_lock(); | ||
1497 | } | ||
1498 | if ( tty_hung_up_p(pFile) ) { | ||
1499 | set_current_state( TASK_RUNNING ); | ||
1500 | remove_wait_queue(&pCh->close_wait, &wait); | ||
1501 | return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS; | ||
1502 | } | ||
1503 | } | ||
1504 | set_current_state( TASK_RUNNING ); | ||
1505 | remove_wait_queue(&pCh->close_wait, &wait); | ||
1506 | |||
1507 | /* | ||
1508 | * 3. Handle a non-blocking open of a normal port. | ||
1509 | */ | ||
1510 | if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) { | ||
1511 | pCh->flags |= ASYNC_NORMAL_ACTIVE; | ||
1512 | goto noblock; | ||
1513 | } | ||
1514 | /* | ||
1515 | * 4. Now loop waiting for the port to be free and carrier present | ||
1516 | * (if required). | ||
1517 | */ | ||
1518 | if ( tty->termios->c_cflag & CLOCAL ) | ||
1519 | do_clocal = 1; | ||
1520 | |||
1521 | #ifdef IP2DEBUG_OPEN | ||
1522 | printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal); | ||
1523 | #endif | ||
1524 | |||
1525 | ++pCh->wopen; | ||
1526 | |||
1527 | init_waitqueue_entry(&wait, current); | ||
1528 | add_wait_queue(&pCh->open_wait, &wait); | ||
1529 | |||
1530 | for(;;) { | ||
1531 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); | ||
1532 | pCh->dataSetOut |= (I2_DTR | I2_RTS); | ||
1533 | set_current_state( TASK_INTERRUPTIBLE ); | ||
1534 | serviceOutgoingFifo( pCh->pMyBord ); | ||
1535 | if ( tty_hung_up_p(pFile) ) { | ||
1536 | set_current_state( TASK_RUNNING ); | ||
1537 | remove_wait_queue(&pCh->open_wait, &wait); | ||
1538 | return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS; | ||
1539 | } | ||
1540 | if (!(pCh->flags & ASYNC_CLOSING) && | ||
1541 | (do_clocal || (pCh->dataSetIn & I2_DCD) )) { | ||
1542 | rc = 0; | ||
1543 | break; | ||
1544 | } | ||
1545 | |||
1546 | #ifdef IP2DEBUG_OPEN | ||
1547 | printk(KERN_DEBUG "ASYNC_CLOSING = %s\n", | ||
1548 | (pCh->flags & ASYNC_CLOSING)?"True":"False"); | ||
1549 | printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n"); | ||
1550 | #endif | ||
1551 | ip2trace (CHANN, ITRC_OPEN, 3, 2, 0, | ||
1552 | (pCh->flags & ASYNC_CLOSING) ); | ||
1553 | /* check for signal */ | ||
1554 | if (signal_pending(current)) { | ||
1555 | rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); | ||
1556 | break; | ||
1557 | } | ||
1558 | tty_unlock(); | ||
1559 | schedule(); | ||
1560 | tty_lock(); | ||
1561 | } | ||
1562 | set_current_state( TASK_RUNNING ); | ||
1563 | remove_wait_queue(&pCh->open_wait, &wait); | ||
1564 | |||
1565 | --pCh->wopen; //why count? | ||
1566 | |||
1567 | ip2trace (CHANN, ITRC_OPEN, 4, 0 ); | ||
1568 | |||
1569 | if (rc != 0 ) { | ||
1570 | return rc; | ||
1571 | } | ||
1572 | pCh->flags |= ASYNC_NORMAL_ACTIVE; | ||
1573 | |||
1574 | noblock: | ||
1575 | |||
1576 | /* first open - Assign termios structure to port */ | ||
1577 | if ( tty->count == 1 ) { | ||
1578 | i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); | ||
1579 | /* Now we must send the termios settings to the loadware */ | ||
1580 | set_params( pCh, NULL ); | ||
1581 | } | ||
1582 | |||
1583 | /* | ||
1584 | * Now set any i2lib options. These may go away if the i2lib code ends | ||
1585 | * up rolled into the mainline. | ||
1586 | */ | ||
1587 | pCh->channelOptions |= CO_NBLOCK_WRITE; | ||
1588 | |||
1589 | #ifdef IP2DEBUG_OPEN | ||
1590 | printk (KERN_DEBUG "IP2: open completed\n" ); | ||
1591 | #endif | ||
1592 | serviceOutgoingFifo( pCh->pMyBord ); | ||
1593 | |||
1594 | ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 ); | ||
1595 | |||
1596 | return 0; | ||
1597 | } | ||
1598 | |||
1599 | /******************************************************************************/ | ||
1600 | /* Function: ip2_close() */ | ||
1601 | /* Parameters: Pointer to tty structure */ | ||
1602 | /* Pointer to file structure */ | ||
1603 | /* Returns: Nothing */ | ||
1604 | /* */ | ||
1605 | /* Description: */ | ||
1606 | /* */ | ||
1607 | /* */ | ||
1608 | /******************************************************************************/ | ||
1609 | static void | ||
1610 | ip2_close( PTTY tty, struct file *pFile ) | ||
1611 | { | ||
1612 | i2ChanStrPtr pCh = tty->driver_data; | ||
1613 | |||
1614 | if ( !pCh ) { | ||
1615 | return; | ||
1616 | } | ||
1617 | |||
1618 | ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 ); | ||
1619 | |||
1620 | #ifdef IP2DEBUG_OPEN | ||
1621 | printk(KERN_DEBUG "IP2:close %s:\n",tty->name); | ||
1622 | #endif | ||
1623 | |||
1624 | if ( tty_hung_up_p ( pFile ) ) { | ||
1625 | |||
1626 | ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); | ||
1627 | |||
1628 | return; | ||
1629 | } | ||
1630 | if ( tty->count > 1 ) { /* not the last close */ | ||
1631 | |||
1632 | ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); | ||
1633 | |||
1634 | return; | ||
1635 | } | ||
1636 | pCh->flags |= ASYNC_CLOSING; // last close actually | ||
1637 | |||
1638 | tty->closing = 1; | ||
1639 | |||
1640 | if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) { | ||
1641 | /* | ||
1642 | * Before we drop DTR, make sure the transmitter has completely drained. | ||
1643 | * This uses an timeout, after which the close | ||
1644 | * completes. | ||
1645 | */ | ||
1646 | ip2_wait_until_sent(tty, pCh->ClosingWaitTime ); | ||
1647 | } | ||
1648 | /* | ||
1649 | * At this point we stop accepting input. Here we flush the channel | ||
1650 | * input buffer which will allow the board to send up more data. Any | ||
1651 | * additional input is tossed at interrupt/poll time. | ||
1652 | */ | ||
1653 | i2InputFlush( pCh ); | ||
1654 | |||
1655 | /* disable DSS reporting */ | ||
1656 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, | ||
1657 | CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); | ||
1658 | if (tty->termios->c_cflag & HUPCL) { | ||
1659 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); | ||
1660 | pCh->dataSetOut &= ~(I2_DTR | I2_RTS); | ||
1661 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); | ||
1662 | } | ||
1663 | |||
1664 | serviceOutgoingFifo ( pCh->pMyBord ); | ||
1665 | |||
1666 | tty_ldisc_flush(tty); | ||
1667 | tty_driver_flush_buffer(tty); | ||
1668 | tty->closing = 0; | ||
1669 | |||
1670 | pCh->pTTY = NULL; | ||
1671 | |||
1672 | if (pCh->wopen) { | ||
1673 | if (pCh->ClosingDelay) { | ||
1674 | msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay)); | ||
1675 | } | ||
1676 | wake_up_interruptible(&pCh->open_wait); | ||
1677 | } | ||
1678 | |||
1679 | pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
1680 | wake_up_interruptible(&pCh->close_wait); | ||
1681 | |||
1682 | #ifdef IP2DEBUG_OPEN | ||
1683 | DBG_CNT("ip2_close: after wakeups--"); | ||
1684 | #endif | ||
1685 | |||
1686 | |||
1687 | ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 ); | ||
1688 | |||
1689 | return; | ||
1690 | } | ||
1691 | |||
1692 | /******************************************************************************/ | ||
1693 | /* Function: ip2_hangup() */ | ||
1694 | /* Parameters: Pointer to tty structure */ | ||
1695 | /* Returns: Nothing */ | ||
1696 | /* */ | ||
1697 | /* Description: */ | ||
1698 | /* */ | ||
1699 | /* */ | ||
1700 | /******************************************************************************/ | ||
1701 | static void | ||
1702 | ip2_hangup ( PTTY tty ) | ||
1703 | { | ||
1704 | i2ChanStrPtr pCh = tty->driver_data; | ||
1705 | |||
1706 | if( !pCh ) { | ||
1707 | return; | ||
1708 | } | ||
1709 | |||
1710 | ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 ); | ||
1711 | |||
1712 | ip2_flush_buffer(tty); | ||
1713 | |||
1714 | /* disable DSS reporting */ | ||
1715 | |||
1716 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP); | ||
1717 | i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); | ||
1718 | if ( (tty->termios->c_cflag & HUPCL) ) { | ||
1719 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN); | ||
1720 | pCh->dataSetOut &= ~(I2_DTR | I2_RTS); | ||
1721 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); | ||
1722 | } | ||
1723 | i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, | ||
1724 | CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); | ||
1725 | serviceOutgoingFifo ( pCh->pMyBord ); | ||
1726 | |||
1727 | wake_up_interruptible ( &pCh->delta_msr_wait ); | ||
1728 | |||
1729 | pCh->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1730 | pCh->pTTY = NULL; | ||
1731 | wake_up_interruptible ( &pCh->open_wait ); | ||
1732 | |||
1733 | ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 ); | ||
1734 | } | ||
1735 | |||
1736 | /******************************************************************************/ | ||
1737 | /******************************************************************************/ | ||
1738 | /* Device Output Section */ | ||
1739 | /******************************************************************************/ | ||
1740 | /******************************************************************************/ | ||
1741 | |||
1742 | /******************************************************************************/ | ||
1743 | /* Function: ip2_write() */ | ||
1744 | /* Parameters: Pointer to tty structure */ | ||
1745 | /* Flag denoting data is in user (1) or kernel (0) space */ | ||
1746 | /* Pointer to data */ | ||
1747 | /* Number of bytes to write */ | ||
1748 | /* Returns: Number of bytes actually written */ | ||
1749 | /* */ | ||
1750 | /* Description: (MANDATORY) */ | ||
1751 | /* */ | ||
1752 | /* */ | ||
1753 | /******************************************************************************/ | ||
1754 | static int | ||
1755 | ip2_write( PTTY tty, const unsigned char *pData, int count) | ||
1756 | { | ||
1757 | i2ChanStrPtr pCh = tty->driver_data; | ||
1758 | int bytesSent = 0; | ||
1759 | unsigned long flags; | ||
1760 | |||
1761 | ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 ); | ||
1762 | |||
1763 | /* Flush out any buffered data left over from ip2_putchar() calls. */ | ||
1764 | ip2_flush_chars( tty ); | ||
1765 | |||
1766 | /* This is the actual move bit. Make sure it does what we need!!!!! */ | ||
1767 | write_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1768 | bytesSent = i2Output( pCh, pData, count); | ||
1769 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1770 | |||
1771 | ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent ); | ||
1772 | |||
1773 | return bytesSent > 0 ? bytesSent : 0; | ||
1774 | } | ||
1775 | |||
1776 | /******************************************************************************/ | ||
1777 | /* Function: ip2_putchar() */ | ||
1778 | /* Parameters: Pointer to tty structure */ | ||
1779 | /* Character to write */ | ||
1780 | /* Returns: Nothing */ | ||
1781 | /* */ | ||
1782 | /* Description: */ | ||
1783 | /* */ | ||
1784 | /* */ | ||
1785 | /******************************************************************************/ | ||
1786 | static int | ||
1787 | ip2_putchar( PTTY tty, unsigned char ch ) | ||
1788 | { | ||
1789 | i2ChanStrPtr pCh = tty->driver_data; | ||
1790 | unsigned long flags; | ||
1791 | |||
1792 | // ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch ); | ||
1793 | |||
1794 | write_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1795 | pCh->Pbuf[pCh->Pbuf_stuff++] = ch; | ||
1796 | if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) { | ||
1797 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1798 | ip2_flush_chars( tty ); | ||
1799 | } else | ||
1800 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1801 | return 1; | ||
1802 | |||
1803 | // ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch ); | ||
1804 | } | ||
1805 | |||
1806 | /******************************************************************************/ | ||
1807 | /* Function: ip2_flush_chars() */ | ||
1808 | /* Parameters: Pointer to tty structure */ | ||
1809 | /* Returns: Nothing */ | ||
1810 | /* */ | ||
1811 | /* Description: */ | ||
1812 | /* */ | ||
1813 | /******************************************************************************/ | ||
1814 | static void | ||
1815 | ip2_flush_chars( PTTY tty ) | ||
1816 | { | ||
1817 | int strip; | ||
1818 | i2ChanStrPtr pCh = tty->driver_data; | ||
1819 | unsigned long flags; | ||
1820 | |||
1821 | write_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1822 | if ( pCh->Pbuf_stuff ) { | ||
1823 | |||
1824 | // ip2trace (CHANN, ITRC_PUTC, 10, 1, strip ); | ||
1825 | |||
1826 | // | ||
1827 | // We may need to restart i2Output if it does not fullfill this request | ||
1828 | // | ||
1829 | strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff); | ||
1830 | if ( strip != pCh->Pbuf_stuff ) { | ||
1831 | memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip ); | ||
1832 | } | ||
1833 | pCh->Pbuf_stuff -= strip; | ||
1834 | } | ||
1835 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1836 | } | ||
1837 | |||
1838 | /******************************************************************************/ | ||
1839 | /* Function: ip2_write_room() */ | ||
1840 | /* Parameters: Pointer to tty structure */ | ||
1841 | /* Returns: Number of bytes that the driver can accept */ | ||
1842 | /* */ | ||
1843 | /* Description: */ | ||
1844 | /* */ | ||
1845 | /******************************************************************************/ | ||
1846 | static int | ||
1847 | ip2_write_room ( PTTY tty ) | ||
1848 | { | ||
1849 | int bytesFree; | ||
1850 | i2ChanStrPtr pCh = tty->driver_data; | ||
1851 | unsigned long flags; | ||
1852 | |||
1853 | read_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1854 | bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff; | ||
1855 | read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1856 | |||
1857 | ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree ); | ||
1858 | |||
1859 | return ((bytesFree > 0) ? bytesFree : 0); | ||
1860 | } | ||
1861 | |||
1862 | /******************************************************************************/ | ||
1863 | /* Function: ip2_chars_in_buf() */ | ||
1864 | /* Parameters: Pointer to tty structure */ | ||
1865 | /* Returns: Number of bytes queued for transmission */ | ||
1866 | /* */ | ||
1867 | /* Description: */ | ||
1868 | /* */ | ||
1869 | /* */ | ||
1870 | /******************************************************************************/ | ||
1871 | static int | ||
1872 | ip2_chars_in_buf ( PTTY tty ) | ||
1873 | { | ||
1874 | i2ChanStrPtr pCh = tty->driver_data; | ||
1875 | int rc; | ||
1876 | unsigned long flags; | ||
1877 | |||
1878 | ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff ); | ||
1879 | |||
1880 | #ifdef IP2DEBUG_WRITE | ||
1881 | printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n", | ||
1882 | pCh->Obuf_char_count + pCh->Pbuf_stuff, | ||
1883 | pCh->Obuf_char_count, pCh->Pbuf_stuff ); | ||
1884 | #endif | ||
1885 | read_lock_irqsave(&pCh->Obuf_spinlock, flags); | ||
1886 | rc = pCh->Obuf_char_count; | ||
1887 | read_unlock_irqrestore(&pCh->Obuf_spinlock, flags); | ||
1888 | read_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1889 | rc += pCh->Pbuf_stuff; | ||
1890 | read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1891 | return rc; | ||
1892 | } | ||
1893 | |||
1894 | /******************************************************************************/ | ||
1895 | /* Function: ip2_flush_buffer() */ | ||
1896 | /* Parameters: Pointer to tty structure */ | ||
1897 | /* Returns: Nothing */ | ||
1898 | /* */ | ||
1899 | /* Description: */ | ||
1900 | /* */ | ||
1901 | /* */ | ||
1902 | /******************************************************************************/ | ||
1903 | static void | ||
1904 | ip2_flush_buffer( PTTY tty ) | ||
1905 | { | ||
1906 | i2ChanStrPtr pCh = tty->driver_data; | ||
1907 | unsigned long flags; | ||
1908 | |||
1909 | ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 ); | ||
1910 | |||
1911 | #ifdef IP2DEBUG_WRITE | ||
1912 | printk (KERN_DEBUG "IP2: flush buffer\n" ); | ||
1913 | #endif | ||
1914 | write_lock_irqsave(&pCh->Pbuf_spinlock, flags); | ||
1915 | pCh->Pbuf_stuff = 0; | ||
1916 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | ||
1917 | i2FlushOutput( pCh ); | ||
1918 | ip2_owake(tty); | ||
1919 | |||
1920 | ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 ); | ||
1921 | |||
1922 | } | ||
1923 | |||
1924 | /******************************************************************************/ | ||
1925 | /* Function: ip2_wait_until_sent() */ | ||
1926 | /* Parameters: Pointer to tty structure */ | ||
1927 | /* Timeout for wait. */ | ||
1928 | /* Returns: Nothing */ | ||
1929 | /* */ | ||
1930 | /* Description: */ | ||
1931 | /* This function is used in place of the normal tty_wait_until_sent, which */ | ||
1932 | /* only waits for the driver buffers to be empty (or rather, those buffers */ | ||
1933 | /* reported by chars_in_buffer) which doesn't work for IP2 due to the */ | ||
1934 | /* indeterminate number of bytes buffered on the board. */ | ||
1935 | /******************************************************************************/ | ||
1936 | static void | ||
1937 | ip2_wait_until_sent ( PTTY tty, int timeout ) | ||
1938 | { | ||
1939 | int i = jiffies; | ||
1940 | i2ChanStrPtr pCh = tty->driver_data; | ||
1941 | |||
1942 | tty_wait_until_sent(tty, timeout ); | ||
1943 | if ( (i = timeout - (jiffies -i)) > 0) | ||
1944 | i2DrainOutput( pCh, i ); | ||
1945 | } | ||
1946 | |||
1947 | /******************************************************************************/ | ||
1948 | /******************************************************************************/ | ||
1949 | /* Device Input Section */ | ||
1950 | /******************************************************************************/ | ||
1951 | /******************************************************************************/ | ||
1952 | |||
1953 | /******************************************************************************/ | ||
1954 | /* Function: ip2_throttle() */ | ||
1955 | /* Parameters: Pointer to tty structure */ | ||
1956 | /* Returns: Nothing */ | ||
1957 | /* */ | ||
1958 | /* Description: */ | ||
1959 | /* */ | ||
1960 | /* */ | ||
1961 | /******************************************************************************/ | ||
1962 | static void | ||
1963 | ip2_throttle ( PTTY tty ) | ||
1964 | { | ||
1965 | i2ChanStrPtr pCh = tty->driver_data; | ||
1966 | |||
1967 | #ifdef IP2DEBUG_READ | ||
1968 | printk (KERN_DEBUG "IP2: throttle\n" ); | ||
1969 | #endif | ||
1970 | /* | ||
1971 | * Signal the poll/interrupt handlers not to forward incoming data to | ||
1972 | * the line discipline. This will cause the buffers to fill up in the | ||
1973 | * library and thus cause the library routines to send the flow control | ||
1974 | * stuff. | ||
1975 | */ | ||
1976 | pCh->throttled = 1; | ||
1977 | } | ||
1978 | |||
1979 | /******************************************************************************/ | ||
1980 | /* Function: ip2_unthrottle() */ | ||
1981 | /* Parameters: Pointer to tty structure */ | ||
1982 | /* Returns: Nothing */ | ||
1983 | /* */ | ||
1984 | /* Description: */ | ||
1985 | /* */ | ||
1986 | /* */ | ||
1987 | /******************************************************************************/ | ||
1988 | static void | ||
1989 | ip2_unthrottle ( PTTY tty ) | ||
1990 | { | ||
1991 | i2ChanStrPtr pCh = tty->driver_data; | ||
1992 | unsigned long flags; | ||
1993 | |||
1994 | #ifdef IP2DEBUG_READ | ||
1995 | printk (KERN_DEBUG "IP2: unthrottle\n" ); | ||
1996 | #endif | ||
1997 | |||
1998 | /* Pass incoming data up to the line discipline again. */ | ||
1999 | pCh->throttled = 0; | ||
2000 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); | ||
2001 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2002 | read_lock_irqsave(&pCh->Ibuf_spinlock, flags); | ||
2003 | if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) { | ||
2004 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
2005 | #ifdef IP2DEBUG_READ | ||
2006 | printk (KERN_DEBUG "i2Input called from unthrottle\n" ); | ||
2007 | #endif | ||
2008 | i2Input( pCh ); | ||
2009 | } else | ||
2010 | read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags); | ||
2011 | } | ||
2012 | |||
2013 | static void | ||
2014 | ip2_start ( PTTY tty ) | ||
2015 | { | ||
2016 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2017 | |||
2018 | i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME); | ||
2019 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND); | ||
2020 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME); | ||
2021 | #ifdef IP2DEBUG_WRITE | ||
2022 | printk (KERN_DEBUG "IP2: start tx\n" ); | ||
2023 | #endif | ||
2024 | } | ||
2025 | |||
2026 | static void | ||
2027 | ip2_stop ( PTTY tty ) | ||
2028 | { | ||
2029 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2030 | |||
2031 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND); | ||
2032 | #ifdef IP2DEBUG_WRITE | ||
2033 | printk (KERN_DEBUG "IP2: stop tx\n" ); | ||
2034 | #endif | ||
2035 | } | ||
2036 | |||
2037 | /******************************************************************************/ | ||
2038 | /* Device Ioctl Section */ | ||
2039 | /******************************************************************************/ | ||
2040 | |||
2041 | static int ip2_tiocmget(struct tty_struct *tty, struct file *file) | ||
2042 | { | ||
2043 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2044 | #ifdef ENABLE_DSSNOW | ||
2045 | wait_queue_t wait; | ||
2046 | #endif | ||
2047 | |||
2048 | if (pCh == NULL) | ||
2049 | return -ENODEV; | ||
2050 | |||
2051 | /* | ||
2052 | FIXME - the following code is causing a NULL pointer dereference in | ||
2053 | 2.3.51 in an interrupt handler. It's suppose to prompt the board | ||
2054 | to return the DSS signal status immediately. Why doesn't it do | ||
2055 | the same thing in 2.2.14? | ||
2056 | */ | ||
2057 | |||
2058 | /* This thing is still busted in the 1.2.12 driver on 2.4.x | ||
2059 | and even hoses the serial console so the oops can be trapped. | ||
2060 | /\/\|=mhw=|\/\/ */ | ||
2061 | |||
2062 | #ifdef ENABLE_DSSNOW | ||
2063 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW); | ||
2064 | |||
2065 | init_waitqueue_entry(&wait, current); | ||
2066 | add_wait_queue(&pCh->dss_now_wait, &wait); | ||
2067 | set_current_state( TASK_INTERRUPTIBLE ); | ||
2068 | |||
2069 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2070 | |||
2071 | schedule(); | ||
2072 | |||
2073 | set_current_state( TASK_RUNNING ); | ||
2074 | remove_wait_queue(&pCh->dss_now_wait, &wait); | ||
2075 | |||
2076 | if (signal_pending(current)) { | ||
2077 | return -EINTR; | ||
2078 | } | ||
2079 | #endif | ||
2080 | return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0) | ||
2081 | | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0) | ||
2082 | | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0) | ||
2083 | | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0) | ||
2084 | | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0) | ||
2085 | | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0); | ||
2086 | } | ||
2087 | |||
2088 | static int ip2_tiocmset(struct tty_struct *tty, struct file *file, | ||
2089 | unsigned int set, unsigned int clear) | ||
2090 | { | ||
2091 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2092 | |||
2093 | if (pCh == NULL) | ||
2094 | return -ENODEV; | ||
2095 | |||
2096 | if (set & TIOCM_RTS) { | ||
2097 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP); | ||
2098 | pCh->dataSetOut |= I2_RTS; | ||
2099 | } | ||
2100 | if (set & TIOCM_DTR) { | ||
2101 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP); | ||
2102 | pCh->dataSetOut |= I2_DTR; | ||
2103 | } | ||
2104 | |||
2105 | if (clear & TIOCM_RTS) { | ||
2106 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN); | ||
2107 | pCh->dataSetOut &= ~I2_RTS; | ||
2108 | } | ||
2109 | if (clear & TIOCM_DTR) { | ||
2110 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN); | ||
2111 | pCh->dataSetOut &= ~I2_DTR; | ||
2112 | } | ||
2113 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2114 | return 0; | ||
2115 | } | ||
2116 | |||
2117 | /******************************************************************************/ | ||
2118 | /* Function: ip2_ioctl() */ | ||
2119 | /* Parameters: Pointer to tty structure */ | ||
2120 | /* Pointer to file structure */ | ||
2121 | /* Command */ | ||
2122 | /* Argument */ | ||
2123 | /* Returns: Success or failure */ | ||
2124 | /* */ | ||
2125 | /* Description: */ | ||
2126 | /* */ | ||
2127 | /* */ | ||
2128 | /******************************************************************************/ | ||
2129 | static int | ||
2130 | ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg ) | ||
2131 | { | ||
2132 | wait_queue_t wait; | ||
2133 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2134 | i2eBordStrPtr pB; | ||
2135 | struct async_icount cprev, cnow; /* kernel counter temps */ | ||
2136 | int rc = 0; | ||
2137 | unsigned long flags; | ||
2138 | void __user *argp = (void __user *)arg; | ||
2139 | |||
2140 | if ( pCh == NULL ) | ||
2141 | return -ENODEV; | ||
2142 | |||
2143 | pB = pCh->pMyBord; | ||
2144 | |||
2145 | ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg ); | ||
2146 | |||
2147 | #ifdef IP2DEBUG_IOCTL | ||
2148 | printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg ); | ||
2149 | #endif | ||
2150 | |||
2151 | switch(cmd) { | ||
2152 | case TIOCGSERIAL: | ||
2153 | |||
2154 | ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc ); | ||
2155 | |||
2156 | rc = get_serial_info(pCh, argp); | ||
2157 | if (rc) | ||
2158 | return rc; | ||
2159 | break; | ||
2160 | |||
2161 | case TIOCSSERIAL: | ||
2162 | |||
2163 | ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc ); | ||
2164 | |||
2165 | rc = set_serial_info(pCh, argp); | ||
2166 | if (rc) | ||
2167 | return rc; | ||
2168 | break; | ||
2169 | |||
2170 | case TCXONC: | ||
2171 | rc = tty_check_change(tty); | ||
2172 | if (rc) | ||
2173 | return rc; | ||
2174 | switch (arg) { | ||
2175 | case TCOOFF: | ||
2176 | //return -ENOIOCTLCMD; | ||
2177 | break; | ||
2178 | case TCOON: | ||
2179 | //return -ENOIOCTLCMD; | ||
2180 | break; | ||
2181 | case TCIOFF: | ||
2182 | if (STOP_CHAR(tty) != __DISABLED_CHAR) { | ||
2183 | i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, | ||
2184 | CMD_XMIT_NOW(STOP_CHAR(tty))); | ||
2185 | } | ||
2186 | break; | ||
2187 | case TCION: | ||
2188 | if (START_CHAR(tty) != __DISABLED_CHAR) { | ||
2189 | i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1, | ||
2190 | CMD_XMIT_NOW(START_CHAR(tty))); | ||
2191 | } | ||
2192 | break; | ||
2193 | default: | ||
2194 | return -EINVAL; | ||
2195 | } | ||
2196 | return 0; | ||
2197 | |||
2198 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | ||
2199 | rc = tty_check_change(tty); | ||
2200 | |||
2201 | ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc ); | ||
2202 | |||
2203 | if (!rc) { | ||
2204 | ip2_wait_until_sent(tty,0); | ||
2205 | if (!arg) { | ||
2206 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250)); | ||
2207 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2208 | } | ||
2209 | } | ||
2210 | break; | ||
2211 | |||
2212 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | ||
2213 | rc = tty_check_change(tty); | ||
2214 | |||
2215 | ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc ); | ||
2216 | |||
2217 | if (!rc) { | ||
2218 | ip2_wait_until_sent(tty,0); | ||
2219 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, | ||
2220 | CMD_SEND_BRK(arg ? arg*100 : 250)); | ||
2221 | serviceOutgoingFifo ( pCh->pMyBord ); | ||
2222 | } | ||
2223 | break; | ||
2224 | |||
2225 | case TIOCGSOFTCAR: | ||
2226 | |||
2227 | ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc ); | ||
2228 | |||
2229 | rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); | ||
2230 | if (rc) | ||
2231 | return rc; | ||
2232 | break; | ||
2233 | |||
2234 | case TIOCSSOFTCAR: | ||
2235 | |||
2236 | ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc ); | ||
2237 | |||
2238 | rc = get_user(arg,(unsigned long __user *) argp); | ||
2239 | if (rc) | ||
2240 | return rc; | ||
2241 | tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | ||
2242 | | (arg ? CLOCAL : 0)); | ||
2243 | |||
2244 | break; | ||
2245 | |||
2246 | /* | ||
2247 | * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask | ||
2248 | * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS | ||
2249 | * for masking). Caller should use TIOCGICOUNT to see which one it was | ||
2250 | */ | ||
2251 | case TIOCMIWAIT: | ||
2252 | write_lock_irqsave(&pB->read_fifo_spinlock, flags); | ||
2253 | cprev = pCh->icount; /* note the counters on entry */ | ||
2254 | write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); | ||
2255 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, | ||
2256 | CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP); | ||
2257 | init_waitqueue_entry(&wait, current); | ||
2258 | add_wait_queue(&pCh->delta_msr_wait, &wait); | ||
2259 | set_current_state( TASK_INTERRUPTIBLE ); | ||
2260 | |||
2261 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2262 | for(;;) { | ||
2263 | ip2trace (CHANN, ITRC_IOCTL, 10, 0 ); | ||
2264 | |||
2265 | schedule(); | ||
2266 | |||
2267 | ip2trace (CHANN, ITRC_IOCTL, 11, 0 ); | ||
2268 | |||
2269 | /* see if a signal did it */ | ||
2270 | if (signal_pending(current)) { | ||
2271 | rc = -ERESTARTSYS; | ||
2272 | break; | ||
2273 | } | ||
2274 | write_lock_irqsave(&pB->read_fifo_spinlock, flags); | ||
2275 | cnow = pCh->icount; /* atomic copy */ | ||
2276 | write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); | ||
2277 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | ||
2278 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { | ||
2279 | rc = -EIO; /* no change => rc */ | ||
2280 | break; | ||
2281 | } | ||
2282 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | ||
2283 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | ||
2284 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
2285 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { | ||
2286 | rc = 0; | ||
2287 | break; | ||
2288 | } | ||
2289 | cprev = cnow; | ||
2290 | } | ||
2291 | set_current_state( TASK_RUNNING ); | ||
2292 | remove_wait_queue(&pCh->delta_msr_wait, &wait); | ||
2293 | |||
2294 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, | ||
2295 | CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); | ||
2296 | if ( ! (pCh->flags & ASYNC_CHECK_CD)) { | ||
2297 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP); | ||
2298 | } | ||
2299 | serviceOutgoingFifo( pCh->pMyBord ); | ||
2300 | return rc; | ||
2301 | break; | ||
2302 | |||
2303 | /* | ||
2304 | * The rest are not supported by this driver. By returning -ENOIOCTLCMD they | ||
2305 | * will be passed to the line discipline for it to handle. | ||
2306 | */ | ||
2307 | case TIOCSERCONFIG: | ||
2308 | case TIOCSERGWILD: | ||
2309 | case TIOCSERGETLSR: | ||
2310 | case TIOCSERSWILD: | ||
2311 | case TIOCSERGSTRUCT: | ||
2312 | case TIOCSERGETMULTI: | ||
2313 | case TIOCSERSETMULTI: | ||
2314 | |||
2315 | default: | ||
2316 | ip2trace (CHANN, ITRC_IOCTL, 12, 0 ); | ||
2317 | |||
2318 | rc = -ENOIOCTLCMD; | ||
2319 | break; | ||
2320 | } | ||
2321 | |||
2322 | ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 ); | ||
2323 | |||
2324 | return rc; | ||
2325 | } | ||
2326 | |||
2327 | static int ip2_get_icount(struct tty_struct *tty, | ||
2328 | struct serial_icounter_struct *icount) | ||
2329 | { | ||
2330 | i2ChanStrPtr pCh = DevTable[tty->index]; | ||
2331 | i2eBordStrPtr pB; | ||
2332 | struct async_icount cnow; /* kernel counter temp */ | ||
2333 | unsigned long flags; | ||
2334 | |||
2335 | if ( pCh == NULL ) | ||
2336 | return -ENODEV; | ||
2337 | |||
2338 | pB = pCh->pMyBord; | ||
2339 | |||
2340 | /* | ||
2341 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
2342 | * Return: write counters to the user passed counter struct | ||
2343 | * NB: both 1->0 and 0->1 transitions are counted except for RI where | ||
2344 | * only 0->1 is counted. The controller is quite capable of counting | ||
2345 | * both, but this done to preserve compatibility with the standard | ||
2346 | * serial driver. | ||
2347 | */ | ||
2348 | |||
2349 | write_lock_irqsave(&pB->read_fifo_spinlock, flags); | ||
2350 | cnow = pCh->icount; | ||
2351 | write_unlock_irqrestore(&pB->read_fifo_spinlock, flags); | ||
2352 | |||
2353 | icount->cts = cnow.cts; | ||
2354 | icount->dsr = cnow.dsr; | ||
2355 | icount->rng = cnow.rng; | ||
2356 | icount->dcd = cnow.dcd; | ||
2357 | icount->rx = cnow.rx; | ||
2358 | icount->tx = cnow.tx; | ||
2359 | icount->frame = cnow.frame; | ||
2360 | icount->overrun = cnow.overrun; | ||
2361 | icount->parity = cnow.parity; | ||
2362 | icount->brk = cnow.brk; | ||
2363 | icount->buf_overrun = cnow.buf_overrun; | ||
2364 | return 0; | ||
2365 | } | ||
2366 | |||
2367 | /******************************************************************************/ | ||
2368 | /* Function: GetSerialInfo() */ | ||
2369 | /* Parameters: Pointer to channel structure */ | ||
2370 | /* Pointer to old termios structure */ | ||
2371 | /* Returns: Nothing */ | ||
2372 | /* */ | ||
2373 | /* Description: */ | ||
2374 | /* This is to support the setserial command, and requires processing of the */ | ||
2375 | /* standard Linux serial structure. */ | ||
2376 | /******************************************************************************/ | ||
2377 | static int | ||
2378 | get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo ) | ||
2379 | { | ||
2380 | struct serial_struct tmp; | ||
2381 | |||
2382 | memset ( &tmp, 0, sizeof(tmp) ); | ||
2383 | tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16]; | ||
2384 | if (BID_HAS_654(tmp.type)) { | ||
2385 | tmp.type = PORT_16650; | ||
2386 | } else { | ||
2387 | tmp.type = PORT_CIRRUS; | ||
2388 | } | ||
2389 | tmp.line = pCh->port_index; | ||
2390 | tmp.port = pCh->pMyBord->i2eBase; | ||
2391 | tmp.irq = ip2config.irq[pCh->port_index/64]; | ||
2392 | tmp.flags = pCh->flags; | ||
2393 | tmp.baud_base = pCh->BaudBase; | ||
2394 | tmp.close_delay = pCh->ClosingDelay; | ||
2395 | tmp.closing_wait = pCh->ClosingWaitTime; | ||
2396 | tmp.custom_divisor = pCh->BaudDivisor; | ||
2397 | return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); | ||
2398 | } | ||
2399 | |||
2400 | /******************************************************************************/ | ||
2401 | /* Function: SetSerialInfo() */ | ||
2402 | /* Parameters: Pointer to channel structure */ | ||
2403 | /* Pointer to old termios structure */ | ||
2404 | /* Returns: Nothing */ | ||
2405 | /* */ | ||
2406 | /* Description: */ | ||
2407 | /* This function provides support for setserial, which uses the TIOCSSERIAL */ | ||
2408 | /* ioctl. Not all setserial parameters are relevant. If the user attempts to */ | ||
2409 | /* change the IRQ, address or type of the port the ioctl fails. */ | ||
2410 | /******************************************************************************/ | ||
2411 | static int | ||
2412 | set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info ) | ||
2413 | { | ||
2414 | struct serial_struct ns; | ||
2415 | int old_flags, old_baud_divisor; | ||
2416 | |||
2417 | if (copy_from_user(&ns, new_info, sizeof (ns))) | ||
2418 | return -EFAULT; | ||
2419 | |||
2420 | /* | ||
2421 | * We don't allow setserial to change IRQ, board address, type or baud | ||
2422 | * base. Also line nunber as such is meaningless but we use it for our | ||
2423 | * array index so it is fixed also. | ||
2424 | */ | ||
2425 | if ( (ns.irq != ip2config.irq[pCh->port_index]) | ||
2426 | || ((int) ns.port != ((int) (pCh->pMyBord->i2eBase))) | ||
2427 | || (ns.baud_base != pCh->BaudBase) | ||
2428 | || (ns.line != pCh->port_index) ) { | ||
2429 | return -EINVAL; | ||
2430 | } | ||
2431 | |||
2432 | old_flags = pCh->flags; | ||
2433 | old_baud_divisor = pCh->BaudDivisor; | ||
2434 | |||
2435 | if ( !capable(CAP_SYS_ADMIN) ) { | ||
2436 | if ( ( ns.close_delay != pCh->ClosingDelay ) || | ||
2437 | ( (ns.flags & ~ASYNC_USR_MASK) != | ||
2438 | (pCh->flags & ~ASYNC_USR_MASK) ) ) { | ||
2439 | return -EPERM; | ||
2440 | } | ||
2441 | |||
2442 | pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) | | ||
2443 | (ns.flags & ASYNC_USR_MASK); | ||
2444 | pCh->BaudDivisor = ns.custom_divisor; | ||
2445 | } else { | ||
2446 | pCh->flags = (pCh->flags & ~ASYNC_FLAGS) | | ||
2447 | (ns.flags & ASYNC_FLAGS); | ||
2448 | pCh->BaudDivisor = ns.custom_divisor; | ||
2449 | pCh->ClosingDelay = ns.close_delay * HZ/100; | ||
2450 | pCh->ClosingWaitTime = ns.closing_wait * HZ/100; | ||
2451 | } | ||
2452 | |||
2453 | if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) ) | ||
2454 | || (old_baud_divisor != pCh->BaudDivisor) ) { | ||
2455 | // Invalidate speed and reset parameters | ||
2456 | set_params( pCh, NULL ); | ||
2457 | } | ||
2458 | |||
2459 | return 0; | ||
2460 | } | ||
2461 | |||
2462 | /******************************************************************************/ | ||
2463 | /* Function: ip2_set_termios() */ | ||
2464 | /* Parameters: Pointer to tty structure */ | ||
2465 | /* Pointer to old termios structure */ | ||
2466 | /* Returns: Nothing */ | ||
2467 | /* */ | ||
2468 | /* Description: */ | ||
2469 | /* */ | ||
2470 | /* */ | ||
2471 | /******************************************************************************/ | ||
2472 | static void | ||
2473 | ip2_set_termios( PTTY tty, struct ktermios *old_termios ) | ||
2474 | { | ||
2475 | i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data; | ||
2476 | |||
2477 | #ifdef IP2DEBUG_IOCTL | ||
2478 | printk (KERN_DEBUG "IP2: set termios %p\n", old_termios ); | ||
2479 | #endif | ||
2480 | |||
2481 | set_params( pCh, old_termios ); | ||
2482 | } | ||
2483 | |||
2484 | /******************************************************************************/ | ||
2485 | /* Function: ip2_set_line_discipline() */ | ||
2486 | /* Parameters: Pointer to tty structure */ | ||
2487 | /* Returns: Nothing */ | ||
2488 | /* */ | ||
2489 | /* Description: Does nothing */ | ||
2490 | /* */ | ||
2491 | /* */ | ||
2492 | /******************************************************************************/ | ||
2493 | static void | ||
2494 | ip2_set_line_discipline ( PTTY tty ) | ||
2495 | { | ||
2496 | #ifdef IP2DEBUG_IOCTL | ||
2497 | printk (KERN_DEBUG "IP2: set line discipline\n" ); | ||
2498 | #endif | ||
2499 | |||
2500 | ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 ); | ||
2501 | |||
2502 | } | ||
2503 | |||
2504 | /******************************************************************************/ | ||
2505 | /* Function: SetLine Characteristics() */ | ||
2506 | /* Parameters: Pointer to channel structure */ | ||
2507 | /* Returns: Nothing */ | ||
2508 | /* */ | ||
2509 | /* Description: */ | ||
2510 | /* This routine is called to update the channel structure with the new line */ | ||
2511 | /* characteristics, and send the appropriate commands to the board when they */ | ||
2512 | /* change. */ | ||
2513 | /******************************************************************************/ | ||
2514 | static void | ||
2515 | set_params( i2ChanStrPtr pCh, struct ktermios *o_tios ) | ||
2516 | { | ||
2517 | tcflag_t cflag, iflag, lflag; | ||
2518 | char stop_char, start_char; | ||
2519 | struct ktermios dummy; | ||
2520 | |||
2521 | lflag = pCh->pTTY->termios->c_lflag; | ||
2522 | cflag = pCh->pTTY->termios->c_cflag; | ||
2523 | iflag = pCh->pTTY->termios->c_iflag; | ||
2524 | |||
2525 | if (o_tios == NULL) { | ||
2526 | dummy.c_lflag = ~lflag; | ||
2527 | dummy.c_cflag = ~cflag; | ||
2528 | dummy.c_iflag = ~iflag; | ||
2529 | o_tios = &dummy; | ||
2530 | } | ||
2531 | |||
2532 | { | ||
2533 | switch ( cflag & CBAUD ) { | ||
2534 | case B0: | ||
2535 | i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); | ||
2536 | pCh->dataSetOut &= ~(I2_DTR | I2_RTS); | ||
2537 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); | ||
2538 | pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag); | ||
2539 | goto service_it; | ||
2540 | break; | ||
2541 | case B38400: | ||
2542 | /* | ||
2543 | * This is the speed that is overloaded with all the other high | ||
2544 | * speeds, depending upon the flag settings. | ||
2545 | */ | ||
2546 | if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) { | ||
2547 | pCh->speed = CBR_57600; | ||
2548 | } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) { | ||
2549 | pCh->speed = CBR_115200; | ||
2550 | } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) { | ||
2551 | pCh->speed = CBR_C1; | ||
2552 | } else { | ||
2553 | pCh->speed = CBR_38400; | ||
2554 | } | ||
2555 | break; | ||
2556 | case B50: pCh->speed = CBR_50; break; | ||
2557 | case B75: pCh->speed = CBR_75; break; | ||
2558 | case B110: pCh->speed = CBR_110; break; | ||
2559 | case B134: pCh->speed = CBR_134; break; | ||
2560 | case B150: pCh->speed = CBR_150; break; | ||
2561 | case B200: pCh->speed = CBR_200; break; | ||
2562 | case B300: pCh->speed = CBR_300; break; | ||
2563 | case B600: pCh->speed = CBR_600; break; | ||
2564 | case B1200: pCh->speed = CBR_1200; break; | ||
2565 | case B1800: pCh->speed = CBR_1800; break; | ||
2566 | case B2400: pCh->speed = CBR_2400; break; | ||
2567 | case B4800: pCh->speed = CBR_4800; break; | ||
2568 | case B9600: pCh->speed = CBR_9600; break; | ||
2569 | case B19200: pCh->speed = CBR_19200; break; | ||
2570 | case B57600: pCh->speed = CBR_57600; break; | ||
2571 | case B115200: pCh->speed = CBR_115200; break; | ||
2572 | case B153600: pCh->speed = CBR_153600; break; | ||
2573 | case B230400: pCh->speed = CBR_230400; break; | ||
2574 | case B307200: pCh->speed = CBR_307200; break; | ||
2575 | case B460800: pCh->speed = CBR_460800; break; | ||
2576 | case B921600: pCh->speed = CBR_921600; break; | ||
2577 | default: pCh->speed = CBR_9600; break; | ||
2578 | } | ||
2579 | if ( pCh->speed == CBR_C1 ) { | ||
2580 | // Process the custom speed parameters. | ||
2581 | int bps = pCh->BaudBase / pCh->BaudDivisor; | ||
2582 | if ( bps == 921600 ) { | ||
2583 | pCh->speed = CBR_921600; | ||
2584 | } else { | ||
2585 | bps = bps/10; | ||
2586 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) ); | ||
2587 | } | ||
2588 | } | ||
2589 | i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed)); | ||
2590 | |||
2591 | i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP); | ||
2592 | pCh->dataSetOut |= (I2_DTR | I2_RTS); | ||
2593 | } | ||
2594 | if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) | ||
2595 | { | ||
2596 | i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, | ||
2597 | CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1)); | ||
2598 | } | ||
2599 | if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) | ||
2600 | { | ||
2601 | i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, | ||
2602 | CMD_SETPAR( | ||
2603 | (cflag & PARENB ? (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP) | ||
2604 | ) | ||
2605 | ); | ||
2606 | } | ||
2607 | /* byte size and parity */ | ||
2608 | if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) | ||
2609 | { | ||
2610 | int datasize; | ||
2611 | switch ( cflag & CSIZE ) { | ||
2612 | case CS5: datasize = CSZ_5; break; | ||
2613 | case CS6: datasize = CSZ_6; break; | ||
2614 | case CS7: datasize = CSZ_7; break; | ||
2615 | case CS8: datasize = CSZ_8; break; | ||
2616 | default: datasize = CSZ_5; break; /* as per serial.c */ | ||
2617 | } | ||
2618 | i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) ); | ||
2619 | } | ||
2620 | /* Process CTS flow control flag setting */ | ||
2621 | if ( (cflag & CRTSCTS) ) { | ||
2622 | i2QueueCommands(PTYPE_INLINE, pCh, 100, | ||
2623 | 2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB); | ||
2624 | } else { | ||
2625 | i2QueueCommands(PTYPE_INLINE, pCh, 100, | ||
2626 | 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB); | ||
2627 | } | ||
2628 | // | ||
2629 | // Process XON/XOFF flow control flags settings | ||
2630 | // | ||
2631 | stop_char = STOP_CHAR(pCh->pTTY); | ||
2632 | start_char = START_CHAR(pCh->pTTY); | ||
2633 | |||
2634 | //////////// can't be \000 | ||
2635 | if (stop_char == __DISABLED_CHAR ) | ||
2636 | { | ||
2637 | stop_char = ~__DISABLED_CHAR; | ||
2638 | } | ||
2639 | if (start_char == __DISABLED_CHAR ) | ||
2640 | { | ||
2641 | start_char = ~__DISABLED_CHAR; | ||
2642 | } | ||
2643 | ///////////////////////////////// | ||
2644 | |||
2645 | if ( o_tios->c_cc[VSTART] != start_char ) | ||
2646 | { | ||
2647 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char)); | ||
2648 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char)); | ||
2649 | } | ||
2650 | if ( o_tios->c_cc[VSTOP] != stop_char ) | ||
2651 | { | ||
2652 | i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char)); | ||
2653 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char)); | ||
2654 | } | ||
2655 | if (stop_char == __DISABLED_CHAR ) | ||
2656 | { | ||
2657 | stop_char = ~__DISABLED_CHAR; //TEST123 | ||
2658 | goto no_xoff; | ||
2659 | } | ||
2660 | if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) | ||
2661 | { | ||
2662 | if ( iflag & IXOFF ) { // Enable XOFF output flow control | ||
2663 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON)); | ||
2664 | } else { // Disable XOFF output flow control | ||
2665 | no_xoff: | ||
2666 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE)); | ||
2667 | } | ||
2668 | } | ||
2669 | if (start_char == __DISABLED_CHAR ) | ||
2670 | { | ||
2671 | goto no_xon; | ||
2672 | } | ||
2673 | if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) | ||
2674 | { | ||
2675 | if ( iflag & IXON ) { | ||
2676 | if ( iflag & IXANY ) { // Enable XON/XANY output flow control | ||
2677 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY)); | ||
2678 | } else { // Enable XON output flow control | ||
2679 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON)); | ||
2680 | } | ||
2681 | } else { // Disable XON output flow control | ||
2682 | no_xon: | ||
2683 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE)); | ||
2684 | } | ||
2685 | } | ||
2686 | if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) | ||
2687 | { | ||
2688 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, | ||
2689 | CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0))); | ||
2690 | } | ||
2691 | if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) | ||
2692 | { | ||
2693 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, | ||
2694 | CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB)); | ||
2695 | } | ||
2696 | |||
2697 | if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) | ||
2698 | ^ ( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) | ||
2699 | { | ||
2700 | char brkrpt = 0; | ||
2701 | char parrpt = 0; | ||
2702 | |||
2703 | if ( iflag & IGNBRK ) { /* Ignore breaks altogether */ | ||
2704 | /* Ignore breaks altogether */ | ||
2705 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP); | ||
2706 | } else { | ||
2707 | if ( iflag & BRKINT ) { | ||
2708 | if ( iflag & PARMRK ) { | ||
2709 | brkrpt = 0x0a; // exception an inline triple | ||
2710 | } else { | ||
2711 | brkrpt = 0x1a; // exception and NULL | ||
2712 | } | ||
2713 | brkrpt |= 0x04; // flush input | ||
2714 | } else { | ||
2715 | if ( iflag & PARMRK ) { | ||
2716 | brkrpt = 0x0b; //POSIX triple \0377 \0 \0 | ||
2717 | } else { | ||
2718 | brkrpt = 0x01; // Null only | ||
2719 | } | ||
2720 | } | ||
2721 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt)); | ||
2722 | } | ||
2723 | |||
2724 | if (iflag & IGNPAR) { | ||
2725 | parrpt = 0x20; | ||
2726 | /* would be 2 for not cirrus bug */ | ||
2727 | /* would be 0x20 cept for cirrus bug */ | ||
2728 | } else { | ||
2729 | if ( iflag & PARMRK ) { | ||
2730 | /* | ||
2731 | * Replace error characters with 3-byte sequence (\0377,\0,char) | ||
2732 | */ | ||
2733 | parrpt = 0x04 ; | ||
2734 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0)); | ||
2735 | } else { | ||
2736 | parrpt = 0x03; | ||
2737 | } | ||
2738 | } | ||
2739 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt)); | ||
2740 | } | ||
2741 | if (cflag & CLOCAL) { | ||
2742 | // Status reporting fails for DCD if this is off | ||
2743 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP); | ||
2744 | pCh->flags &= ~ASYNC_CHECK_CD; | ||
2745 | } else { | ||
2746 | i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP); | ||
2747 | pCh->flags |= ASYNC_CHECK_CD; | ||
2748 | } | ||
2749 | |||
2750 | service_it: | ||
2751 | i2DrainOutput( pCh, 100 ); | ||
2752 | } | ||
2753 | |||
2754 | /******************************************************************************/ | ||
2755 | /* IPL Device Section */ | ||
2756 | /******************************************************************************/ | ||
2757 | |||
2758 | /******************************************************************************/ | ||
2759 | /* Function: ip2_ipl_read() */ | ||
2760 | /* Parameters: Pointer to device inode */ | ||
2761 | /* Pointer to file structure */ | ||
2762 | /* Pointer to data */ | ||
2763 | /* Number of bytes to read */ | ||
2764 | /* Returns: Success or failure */ | ||
2765 | /* */ | ||
2766 | /* Description: Ugly */ | ||
2767 | /* */ | ||
2768 | /* */ | ||
2769 | /******************************************************************************/ | ||
2770 | |||
2771 | static | ||
2772 | ssize_t | ||
2773 | ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off ) | ||
2774 | { | ||
2775 | unsigned int minor = iminor(pFile->f_path.dentry->d_inode); | ||
2776 | int rc = 0; | ||
2777 | |||
2778 | #ifdef IP2DEBUG_IPL | ||
2779 | printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count ); | ||
2780 | #endif | ||
2781 | |||
2782 | switch( minor ) { | ||
2783 | case 0: // IPL device | ||
2784 | rc = -EINVAL; | ||
2785 | break; | ||
2786 | case 1: // Status dump | ||
2787 | rc = -EINVAL; | ||
2788 | break; | ||
2789 | case 2: // Ping device | ||
2790 | rc = -EINVAL; | ||
2791 | break; | ||
2792 | case 3: // Trace device | ||
2793 | rc = DumpTraceBuffer ( pData, count ); | ||
2794 | break; | ||
2795 | case 4: // Trace device | ||
2796 | rc = DumpFifoBuffer ( pData, count ); | ||
2797 | break; | ||
2798 | default: | ||
2799 | rc = -ENODEV; | ||
2800 | break; | ||
2801 | } | ||
2802 | return rc; | ||
2803 | } | ||
2804 | |||
2805 | static int | ||
2806 | DumpFifoBuffer ( char __user *pData, int count ) | ||
2807 | { | ||
2808 | #ifdef DEBUG_FIFO | ||
2809 | int rc; | ||
2810 | rc = copy_to_user(pData, DBGBuf, count); | ||
2811 | |||
2812 | printk(KERN_DEBUG "Last index %d\n", I ); | ||
2813 | |||
2814 | return count; | ||
2815 | #endif /* DEBUG_FIFO */ | ||
2816 | return 0; | ||
2817 | } | ||
2818 | |||
2819 | static int | ||
2820 | DumpTraceBuffer ( char __user *pData, int count ) | ||
2821 | { | ||
2822 | #ifdef IP2DEBUG_TRACE | ||
2823 | int rc; | ||
2824 | int dumpcount; | ||
2825 | int chunk; | ||
2826 | int *pIndex = (int __user *)pData; | ||
2827 | |||
2828 | if ( count < (sizeof(int) * 6) ) { | ||
2829 | return -EIO; | ||
2830 | } | ||
2831 | rc = put_user(tracewrap, pIndex ); | ||
2832 | rc = put_user(TRACEMAX, ++pIndex ); | ||
2833 | rc = put_user(tracestrip, ++pIndex ); | ||
2834 | rc = put_user(tracestuff, ++pIndex ); | ||
2835 | pData += sizeof(int) * 6; | ||
2836 | count -= sizeof(int) * 6; | ||
2837 | |||
2838 | dumpcount = tracestuff - tracestrip; | ||
2839 | if ( dumpcount < 0 ) { | ||
2840 | dumpcount += TRACEMAX; | ||
2841 | } | ||
2842 | if ( dumpcount > count ) { | ||
2843 | dumpcount = count; | ||
2844 | } | ||
2845 | chunk = TRACEMAX - tracestrip; | ||
2846 | if ( dumpcount > chunk ) { | ||
2847 | rc = copy_to_user(pData, &tracebuf[tracestrip], | ||
2848 | chunk * sizeof(tracebuf[0]) ); | ||
2849 | pData += chunk * sizeof(tracebuf[0]); | ||
2850 | tracestrip = 0; | ||
2851 | chunk = dumpcount - chunk; | ||
2852 | } else { | ||
2853 | chunk = dumpcount; | ||
2854 | } | ||
2855 | rc = copy_to_user(pData, &tracebuf[tracestrip], | ||
2856 | chunk * sizeof(tracebuf[0]) ); | ||
2857 | tracestrip += chunk; | ||
2858 | tracewrap = 0; | ||
2859 | |||
2860 | rc = put_user(tracestrip, ++pIndex ); | ||
2861 | rc = put_user(tracestuff, ++pIndex ); | ||
2862 | |||
2863 | return dumpcount; | ||
2864 | #else | ||
2865 | return 0; | ||
2866 | #endif | ||
2867 | } | ||
2868 | |||
2869 | /******************************************************************************/ | ||
2870 | /* Function: ip2_ipl_write() */ | ||
2871 | /* Parameters: */ | ||
2872 | /* Pointer to file structure */ | ||
2873 | /* Pointer to data */ | ||
2874 | /* Number of bytes to write */ | ||
2875 | /* Returns: Success or failure */ | ||
2876 | /* */ | ||
2877 | /* Description: */ | ||
2878 | /* */ | ||
2879 | /* */ | ||
2880 | /******************************************************************************/ | ||
2881 | static ssize_t | ||
2882 | ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off) | ||
2883 | { | ||
2884 | #ifdef IP2DEBUG_IPL | ||
2885 | printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count ); | ||
2886 | #endif | ||
2887 | return 0; | ||
2888 | } | ||
2889 | |||
2890 | /******************************************************************************/ | ||
2891 | /* Function: ip2_ipl_ioctl() */ | ||
2892 | /* Parameters: Pointer to device inode */ | ||
2893 | /* Pointer to file structure */ | ||
2894 | /* Command */ | ||
2895 | /* Argument */ | ||
2896 | /* Returns: Success or failure */ | ||
2897 | /* */ | ||
2898 | /* Description: */ | ||
2899 | /* */ | ||
2900 | /* */ | ||
2901 | /******************************************************************************/ | ||
2902 | static long | ||
2903 | ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) | ||
2904 | { | ||
2905 | unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode); | ||
2906 | int rc = 0; | ||
2907 | void __user *argp = (void __user *)arg; | ||
2908 | ULONG __user *pIndex = argp; | ||
2909 | i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4]; | ||
2910 | i2ChanStrPtr pCh; | ||
2911 | |||
2912 | #ifdef IP2DEBUG_IPL | ||
2913 | printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); | ||
2914 | #endif | ||
2915 | |||
2916 | mutex_lock(&ip2_mutex); | ||
2917 | |||
2918 | switch ( iplminor ) { | ||
2919 | case 0: // IPL device | ||
2920 | rc = -EINVAL; | ||
2921 | break; | ||
2922 | case 1: // Status dump | ||
2923 | case 5: | ||
2924 | case 9: | ||
2925 | case 13: | ||
2926 | switch ( cmd ) { | ||
2927 | case 64: /* Driver - ip2stat */ | ||
2928 | rc = put_user(-1, pIndex++ ); | ||
2929 | rc = put_user(irq_counter, pIndex++ ); | ||
2930 | rc = put_user(bh_counter, pIndex++ ); | ||
2931 | break; | ||
2932 | |||
2933 | case 65: /* Board - ip2stat */ | ||
2934 | if ( pB ) { | ||
2935 | rc = copy_to_user(argp, pB, sizeof(i2eBordStr)); | ||
2936 | rc = put_user(inb(pB->i2eStatus), | ||
2937 | (ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) ); | ||
2938 | } else { | ||
2939 | rc = -ENODEV; | ||
2940 | } | ||
2941 | break; | ||
2942 | |||
2943 | default: | ||
2944 | if (cmd < IP2_MAX_PORTS) { | ||
2945 | pCh = DevTable[cmd]; | ||
2946 | if ( pCh ) | ||
2947 | { | ||
2948 | rc = copy_to_user(argp, pCh, sizeof(i2ChanStr)); | ||
2949 | if (rc) | ||
2950 | rc = -EFAULT; | ||
2951 | } else { | ||
2952 | rc = -ENODEV; | ||
2953 | } | ||
2954 | } else { | ||
2955 | rc = -EINVAL; | ||
2956 | } | ||
2957 | } | ||
2958 | break; | ||
2959 | |||
2960 | case 2: // Ping device | ||
2961 | rc = -EINVAL; | ||
2962 | break; | ||
2963 | case 3: // Trace device | ||
2964 | /* | ||
2965 | * akpm: This used to write a whole bunch of function addresses | ||
2966 | * to userspace, which generated lots of put_user() warnings. | ||
2967 | * I killed it all. Just return "success" and don't do | ||
2968 | * anything. | ||
2969 | */ | ||
2970 | if (cmd == 1) | ||
2971 | rc = 0; | ||
2972 | else | ||
2973 | rc = -EINVAL; | ||
2974 | break; | ||
2975 | |||
2976 | default: | ||
2977 | rc = -ENODEV; | ||
2978 | break; | ||
2979 | } | ||
2980 | mutex_unlock(&ip2_mutex); | ||
2981 | return rc; | ||
2982 | } | ||
2983 | |||
2984 | /******************************************************************************/ | ||
2985 | /* Function: ip2_ipl_open() */ | ||
2986 | /* Parameters: Pointer to device inode */ | ||
2987 | /* Pointer to file structure */ | ||
2988 | /* Returns: Success or failure */ | ||
2989 | /* */ | ||
2990 | /* Description: */ | ||
2991 | /* */ | ||
2992 | /* */ | ||
2993 | /******************************************************************************/ | ||
2994 | static int | ||
2995 | ip2_ipl_open( struct inode *pInode, struct file *pFile ) | ||
2996 | { | ||
2997 | |||
2998 | #ifdef IP2DEBUG_IPL | ||
2999 | printk (KERN_DEBUG "IP2IPL: open\n" ); | ||
3000 | #endif | ||
3001 | return 0; | ||
3002 | } | ||
3003 | |||
3004 | static int | ||
3005 | proc_ip2mem_show(struct seq_file *m, void *v) | ||
3006 | { | ||
3007 | i2eBordStrPtr pB; | ||
3008 | i2ChanStrPtr pCh; | ||
3009 | PTTY tty; | ||
3010 | int i; | ||
3011 | |||
3012 | #define FMTLINE "%3d: 0x%08x 0x%08x 0%011o 0%011o\n" | ||
3013 | #define FMTLIN2 " 0x%04x 0x%04x tx flow 0x%x\n" | ||
3014 | #define FMTLIN3 " 0x%04x 0x%04x rc flow\n" | ||
3015 | |||
3016 | seq_printf(m,"\n"); | ||
3017 | |||
3018 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | ||
3019 | pB = i2BoardPtrTable[i]; | ||
3020 | if ( pB ) { | ||
3021 | seq_printf(m,"board %d:\n",i); | ||
3022 | seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n", | ||
3023 | pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting); | ||
3024 | } | ||
3025 | } | ||
3026 | |||
3027 | seq_printf(m,"#: tty flags, port flags, cflags, iflags\n"); | ||
3028 | for (i=0; i < IP2_MAX_PORTS; i++) { | ||
3029 | pCh = DevTable[i]; | ||
3030 | if (pCh) { | ||
3031 | tty = pCh->pTTY; | ||
3032 | if (tty && tty->count) { | ||
3033 | seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags, | ||
3034 | tty->termios->c_cflag,tty->termios->c_iflag); | ||
3035 | |||
3036 | seq_printf(m,FMTLIN2, | ||
3037 | pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds); | ||
3038 | seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room); | ||
3039 | } | ||
3040 | } | ||
3041 | } | ||
3042 | return 0; | ||
3043 | } | ||
3044 | |||
3045 | static int proc_ip2mem_open(struct inode *inode, struct file *file) | ||
3046 | { | ||
3047 | return single_open(file, proc_ip2mem_show, NULL); | ||
3048 | } | ||
3049 | |||
3050 | static const struct file_operations ip2mem_proc_fops = { | ||
3051 | .owner = THIS_MODULE, | ||
3052 | .open = proc_ip2mem_open, | ||
3053 | .read = seq_read, | ||
3054 | .llseek = seq_lseek, | ||
3055 | .release = single_release, | ||
3056 | }; | ||
3057 | |||
3058 | /* | ||
3059 | * This is the handler for /proc/tty/driver/ip2 | ||
3060 | * | ||
3061 | * This stretch of code has been largely plagerized from at least three | ||
3062 | * different sources including ip2mkdev.c and a couple of other drivers. | ||
3063 | * The bugs are all mine. :-) =mhw= | ||
3064 | */ | ||
3065 | static int ip2_proc_show(struct seq_file *m, void *v) | ||
3066 | { | ||
3067 | int i, j, box; | ||
3068 | int boxes = 0; | ||
3069 | int ports = 0; | ||
3070 | int tports = 0; | ||
3071 | i2eBordStrPtr pB; | ||
3072 | char *sep; | ||
3073 | |||
3074 | seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion); | ||
3075 | seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", | ||
3076 | IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, | ||
3077 | IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); | ||
3078 | |||
3079 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | ||
3080 | /* This need to be reset for a board by board count... */ | ||
3081 | boxes = 0; | ||
3082 | pB = i2BoardPtrTable[i]; | ||
3083 | if( pB ) { | ||
3084 | switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) | ||
3085 | { | ||
3086 | case POR_ID_FIIEX: | ||
3087 | seq_printf(m, "Board %d: EX ports=", i); | ||
3088 | sep = ""; | ||
3089 | for( box = 0; box < ABS_MAX_BOXES; ++box ) | ||
3090 | { | ||
3091 | ports = 0; | ||
3092 | |||
3093 | if( pB->i2eChannelMap[box] != 0 ) ++boxes; | ||
3094 | for( j = 0; j < ABS_BIGGEST_BOX; ++j ) | ||
3095 | { | ||
3096 | if( pB->i2eChannelMap[box] & 1<< j ) { | ||
3097 | ++ports; | ||
3098 | } | ||
3099 | } | ||
3100 | seq_printf(m, "%s%d", sep, ports); | ||
3101 | sep = ","; | ||
3102 | tports += ports; | ||
3103 | } | ||
3104 | seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8); | ||
3105 | break; | ||
3106 | |||
3107 | case POR_ID_II_4: | ||
3108 | seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i); | ||
3109 | tports = ports = 4; | ||
3110 | break; | ||
3111 | |||
3112 | case POR_ID_II_8: | ||
3113 | seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i); | ||
3114 | tports = ports = 8; | ||
3115 | break; | ||
3116 | |||
3117 | case POR_ID_II_8R: | ||
3118 | seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i); | ||
3119 | tports = ports = 8; | ||
3120 | break; | ||
3121 | |||
3122 | default: | ||
3123 | seq_printf(m, "Board %d: unknown", i); | ||
3124 | /* Don't try and probe for minor numbers */ | ||
3125 | tports = ports = 0; | ||
3126 | } | ||
3127 | |||
3128 | } else { | ||
3129 | /* Don't try and probe for minor numbers */ | ||
3130 | seq_printf(m, "Board %d: vacant", i); | ||
3131 | tports = ports = 0; | ||
3132 | } | ||
3133 | |||
3134 | if( tports ) { | ||
3135 | seq_puts(m, " minors="); | ||
3136 | sep = ""; | ||
3137 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | ||
3138 | { | ||
3139 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) | ||
3140 | { | ||
3141 | if ( pB->i2eChannelMap[box] & (1 << j) ) | ||
3142 | { | ||
3143 | seq_printf(m, "%s%d", sep, | ||
3144 | j + ABS_BIGGEST_BOX * | ||
3145 | (box+i*ABS_MAX_BOXES)); | ||
3146 | sep = ","; | ||
3147 | } | ||
3148 | } | ||
3149 | } | ||
3150 | } | ||
3151 | seq_putc(m, '\n'); | ||
3152 | } | ||
3153 | return 0; | ||
3154 | } | ||
3155 | |||
3156 | static int ip2_proc_open(struct inode *inode, struct file *file) | ||
3157 | { | ||
3158 | return single_open(file, ip2_proc_show, NULL); | ||
3159 | } | ||
3160 | |||
3161 | static const struct file_operations ip2_proc_fops = { | ||
3162 | .owner = THIS_MODULE, | ||
3163 | .open = ip2_proc_open, | ||
3164 | .read = seq_read, | ||
3165 | .llseek = seq_lseek, | ||
3166 | .release = single_release, | ||
3167 | }; | ||
3168 | |||
3169 | /******************************************************************************/ | ||
3170 | /* Function: ip2trace() */ | ||
3171 | /* Parameters: Value to add to trace buffer */ | ||
3172 | /* Returns: Nothing */ | ||
3173 | /* */ | ||
3174 | /* Description: */ | ||
3175 | /* */ | ||
3176 | /* */ | ||
3177 | /******************************************************************************/ | ||
3178 | #ifdef IP2DEBUG_TRACE | ||
3179 | void | ||
3180 | ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...) | ||
3181 | { | ||
3182 | long flags; | ||
3183 | unsigned long *pCode = &codes; | ||
3184 | union ip2breadcrumb bc; | ||
3185 | i2ChanStrPtr pCh; | ||
3186 | |||
3187 | |||
3188 | tracebuf[tracestuff++] = jiffies; | ||
3189 | if ( tracestuff == TRACEMAX ) { | ||
3190 | tracestuff = 0; | ||
3191 | } | ||
3192 | if ( tracestuff == tracestrip ) { | ||
3193 | if ( ++tracestrip == TRACEMAX ) { | ||
3194 | tracestrip = 0; | ||
3195 | } | ||
3196 | ++tracewrap; | ||
3197 | } | ||
3198 | |||
3199 | bc.hdr.port = 0xff & pn; | ||
3200 | bc.hdr.cat = cat; | ||
3201 | bc.hdr.codes = (unsigned char)( codes & 0xff ); | ||
3202 | bc.hdr.label = label; | ||
3203 | tracebuf[tracestuff++] = bc.value; | ||
3204 | |||
3205 | for (;;) { | ||
3206 | if ( tracestuff == TRACEMAX ) { | ||
3207 | tracestuff = 0; | ||
3208 | } | ||
3209 | if ( tracestuff == tracestrip ) { | ||
3210 | if ( ++tracestrip == TRACEMAX ) { | ||
3211 | tracestrip = 0; | ||
3212 | } | ||
3213 | ++tracewrap; | ||
3214 | } | ||
3215 | |||
3216 | if ( !codes-- ) | ||
3217 | break; | ||
3218 | |||
3219 | tracebuf[tracestuff++] = *++pCode; | ||
3220 | } | ||
3221 | } | ||
3222 | #endif | ||
3223 | |||
3224 | |||
3225 | MODULE_LICENSE("GPL"); | ||
3226 | |||
3227 | static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = { | ||
3228 | { PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) }, | ||
3229 | { } | ||
3230 | }; | ||
3231 | |||
3232 | MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl); | ||
3233 | |||
3234 | MODULE_FIRMWARE("intelliport2.bin"); | ||
diff --git a/drivers/char/ip2/ip2trace.h b/drivers/char/ip2/ip2trace.h deleted file mode 100644 index da20435dc8a6..000000000000 --- a/drivers/char/ip2/ip2trace.h +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | |||
2 | // | ||
3 | union ip2breadcrumb | ||
4 | { | ||
5 | struct { | ||
6 | unsigned char port, cat, codes, label; | ||
7 | } __attribute__ ((packed)) hdr; | ||
8 | unsigned long value; | ||
9 | }; | ||
10 | |||
11 | #define ITRC_NO_PORT 0xFF | ||
12 | #define CHANN (pCh->port_index) | ||
13 | |||
14 | #define ITRC_ERROR '!' | ||
15 | #define ITRC_INIT 'A' | ||
16 | #define ITRC_OPEN 'B' | ||
17 | #define ITRC_CLOSE 'C' | ||
18 | #define ITRC_DRAIN 'D' | ||
19 | #define ITRC_IOCTL 'E' | ||
20 | #define ITRC_FLUSH 'F' | ||
21 | #define ITRC_STATUS 'G' | ||
22 | #define ITRC_HANGUP 'H' | ||
23 | #define ITRC_INTR 'I' | ||
24 | #define ITRC_SFLOW 'J' | ||
25 | #define ITRC_SBCMD 'K' | ||
26 | #define ITRC_SICMD 'L' | ||
27 | #define ITRC_MODEM 'M' | ||
28 | #define ITRC_INPUT 'N' | ||
29 | #define ITRC_OUTPUT 'O' | ||
30 | #define ITRC_PUTC 'P' | ||
31 | #define ITRC_QUEUE 'Q' | ||
32 | #define ITRC_STFLW 'R' | ||
33 | #define ITRC_SFIFO 'S' | ||
34 | #define ITRC_VERIFY 'V' | ||
35 | #define ITRC_WRITE 'W' | ||
36 | |||
37 | #define ITRC_ENTER 0x00 | ||
38 | #define ITRC_RETURN 0xFF | ||
39 | |||
40 | #define ITRC_QUEUE_ROOM 2 | ||
41 | #define ITRC_QUEUE_CMD 6 | ||
42 | |||
diff --git a/drivers/char/ip2/ip2types.h b/drivers/char/ip2/ip2types.h deleted file mode 100644 index 9d67b260b2f6..000000000000 --- a/drivers/char/ip2/ip2types.h +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * (c) 1998 by Computone Corporation | ||
4 | * | ||
5 | ******************************************************************************** | ||
6 | * | ||
7 | * | ||
8 | * PACKAGE: Linux tty Device Driver for IntelliPort II family of multiport | ||
9 | * serial I/O controllers. | ||
10 | * | ||
11 | * DESCRIPTION: Driver constants and type definitions. | ||
12 | * | ||
13 | * NOTES: | ||
14 | * | ||
15 | *******************************************************************************/ | ||
16 | #ifndef IP2TYPES_H | ||
17 | #define IP2TYPES_H | ||
18 | |||
19 | //************* | ||
20 | //* Constants * | ||
21 | //************* | ||
22 | |||
23 | // Define some limits for this driver. Ports per board is a hardware limitation | ||
24 | // that will not change. Current hardware limits this to 64 ports per board. | ||
25 | // Boards per driver is a self-imposed limit. | ||
26 | // | ||
27 | #define IP2_MAX_BOARDS 4 | ||
28 | #define IP2_PORTS_PER_BOARD ABS_MOST_PORTS | ||
29 | #define IP2_MAX_PORTS (IP2_MAX_BOARDS*IP2_PORTS_PER_BOARD) | ||
30 | |||
31 | #define ISA 0 | ||
32 | #define PCI 1 | ||
33 | #define EISA 2 | ||
34 | |||
35 | //******************** | ||
36 | //* Type Definitions * | ||
37 | //******************** | ||
38 | |||
39 | typedef struct tty_struct * PTTY; | ||
40 | typedef wait_queue_head_t PWAITQ; | ||
41 | |||
42 | typedef unsigned char UCHAR; | ||
43 | typedef unsigned int UINT; | ||
44 | typedef unsigned short USHORT; | ||
45 | typedef unsigned long ULONG; | ||
46 | |||
47 | typedef struct | ||
48 | { | ||
49 | short irq[IP2_MAX_BOARDS]; | ||
50 | unsigned short addr[IP2_MAX_BOARDS]; | ||
51 | int type[IP2_MAX_BOARDS]; | ||
52 | #ifdef CONFIG_PCI | ||
53 | struct pci_dev *pci_dev[IP2_MAX_BOARDS]; | ||
54 | #endif | ||
55 | } ip2config_t; | ||
56 | |||
57 | #endif | ||