diff options
Diffstat (limited to 'drivers/char/rio')
77 files changed, 21235 insertions, 0 deletions
diff --git a/drivers/char/rio/Makefile b/drivers/char/rio/Makefile new file mode 100644 index 000000000000..bce2bd1204ed --- /dev/null +++ b/drivers/char/rio/Makefile | |||
@@ -0,0 +1,12 @@ | |||
1 | # | ||
2 | # Makefile for the linux rio-subsystem. | ||
3 | # | ||
4 | # (C) R.E.Wolff@BitWizard.nl | ||
5 | # | ||
6 | # This file is GPL. See other files for the full Blurb. I'm lazy today. | ||
7 | # | ||
8 | |||
9 | obj-$(CONFIG_RIO) += rio.o | ||
10 | |||
11 | rio-objs := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \ | ||
12 | rioparam.o riopcicopy.o rioroute.o riotable.o riotty.o | ||
diff --git a/drivers/char/rio/board.h b/drivers/char/rio/board.h new file mode 100644 index 000000000000..0b397e1c8f1c --- /dev/null +++ b/drivers/char/rio/board.h | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : board.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:07 | ||
26 | ** Retrieved : 11/6/98 11:34:20 | ||
27 | ** | ||
28 | ** ident @(#)board.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_board_h__ | ||
34 | #define __rio_board_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_board_h_sccs_ = "@(#)board.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** board.h contains the definitions for the *hardware* of the host cards. | ||
42 | ** It describes the memory overlay for the dual port RAM area. | ||
43 | */ | ||
44 | |||
45 | #define DP_SRAM1_SIZE 0x7C00 | ||
46 | #define DP_SRAM2_SIZE 0x0200 | ||
47 | #define DP_SRAM3_SIZE 0x7000 | ||
48 | #define DP_SCRATCH_SIZE 0x1000 | ||
49 | #define DP_PARMMAP_ADDR 0x01FE /* offset into SRAM2 */ | ||
50 | #define DP_STARTUP_ADDR 0x01F8 /* offset into SRAM2 */ | ||
51 | |||
52 | /* | ||
53 | ** The shape of the Host Control area, at offset 0x7C00, Write Only | ||
54 | */ | ||
55 | struct s_Ctrl | ||
56 | { | ||
57 | BYTE DpCtl; /* 7C00 */ | ||
58 | BYTE Dp_Unused2_[127]; | ||
59 | BYTE DpIntSet; /* 7C80 */ | ||
60 | BYTE Dp_Unused3_[127]; | ||
61 | BYTE DpTpuReset; /* 7D00 */ | ||
62 | BYTE Dp_Unused4_[127]; | ||
63 | BYTE DpIntReset; /* 7D80 */ | ||
64 | BYTE Dp_Unused5_[127]; | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | ** The PROM data area on the host (0x7C00), Read Only | ||
69 | */ | ||
70 | struct s_Prom | ||
71 | { | ||
72 | WORD DpSlxCode[2]; | ||
73 | WORD DpRev; | ||
74 | WORD Dp_Unused6_; | ||
75 | WORD DpUniq[4]; | ||
76 | WORD DpJahre; | ||
77 | WORD DpWoche; | ||
78 | WORD DpHwFeature[5]; | ||
79 | WORD DpOemId; | ||
80 | WORD DpSiggy[16]; | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | ** Union of the Ctrl and Prom areas | ||
85 | */ | ||
86 | union u_CtrlProm /* This is the control/PROM area (0x7C00) */ | ||
87 | { | ||
88 | struct s_Ctrl DpCtrl; | ||
89 | struct s_Prom DpProm; | ||
90 | }; | ||
91 | |||
92 | /* | ||
93 | ** The top end of memory! | ||
94 | */ | ||
95 | struct s_ParmMapS /* Area containing Parm Map Pointer */ | ||
96 | { | ||
97 | BYTE Dp_Unused8_[DP_PARMMAP_ADDR]; | ||
98 | WORD DpParmMapAd; | ||
99 | }; | ||
100 | |||
101 | struct s_StartUpS | ||
102 | { | ||
103 | BYTE Dp_Unused9_[DP_STARTUP_ADDR]; | ||
104 | BYTE Dp_LongJump[0x4]; | ||
105 | BYTE Dp_Unused10_[2]; | ||
106 | BYTE Dp_ShortJump[0x2]; | ||
107 | }; | ||
108 | |||
109 | union u_Sram2ParmMap /* This is the top of memory (0x7E00-0x7FFF) */ | ||
110 | { | ||
111 | BYTE DpSramMem[DP_SRAM2_SIZE]; | ||
112 | struct s_ParmMapS DpParmMapS; | ||
113 | struct s_StartUpS DpStartUpS; | ||
114 | }; | ||
115 | |||
116 | /* | ||
117 | ** This is the DP RAM overlay. | ||
118 | */ | ||
119 | struct DpRam | ||
120 | { | ||
121 | BYTE DpSram1[DP_SRAM1_SIZE]; /* 0000 - 7BFF */ | ||
122 | union u_CtrlProm DpCtrlProm; /* 7C00 - 7DFF */ | ||
123 | union u_Sram2ParmMap DpSram2ParmMap; /* 7E00 - 7FFF */ | ||
124 | BYTE DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */ | ||
125 | BYTE DpSram3[DP_SRAM3_SIZE]; /* 9000 - FFFF */ | ||
126 | }; | ||
127 | |||
128 | #define DpControl DpCtrlProm.DpCtrl.DpCtl | ||
129 | #define DpSetInt DpCtrlProm.DpCtrl.DpIntSet | ||
130 | #define DpResetTpu DpCtrlProm.DpCtrl.DpTpuReset | ||
131 | #define DpResetInt DpCtrlProm.DpCtrl.DpIntReset | ||
132 | |||
133 | #define DpSlx DpCtrlProm.DpProm.DpSlxCode | ||
134 | #define DpRevision DpCtrlProm.DpProm.DpRev | ||
135 | #define DpUnique DpCtrlProm.DpProm.DpUniq | ||
136 | #define DpYear DpCtrlProm.DpProm.DpJahre | ||
137 | #define DpWeek DpCtrlProm.DpProm.DpWoche | ||
138 | #define DpSignature DpCtrlProm.DpProm.DpSiggy | ||
139 | |||
140 | #define DpParmMapR DpSram2ParmMap.DpParmMapS.DpParmMapAd | ||
141 | #define DpSram2 DpSram2ParmMap.DpSramMem | ||
142 | |||
143 | #endif | ||
diff --git a/drivers/char/rio/bootpkt.h b/drivers/char/rio/bootpkt.h new file mode 100644 index 000000000000..c329aeb7c871 --- /dev/null +++ b/drivers/char/rio/bootpkt.h | |||
@@ -0,0 +1,62 @@ | |||
1 | |||
2 | |||
3 | /**************************************************************************** | ||
4 | ******* ******* | ||
5 | ******* B O O T P A C K E T H E A D E R F I L E | ||
6 | ******* ******* | ||
7 | **************************************************************************** | ||
8 | |||
9 | Author : Ian Nandhra | ||
10 | Date : | ||
11 | |||
12 | * | ||
13 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | |||
29 | Version : 0.01 | ||
30 | |||
31 | |||
32 | Mods | ||
33 | ---------------------------------------------------------------------------- | ||
34 | Date By Description | ||
35 | ---------------------------------------------------------------------------- | ||
36 | |||
37 | ***************************************************************************/ | ||
38 | |||
39 | #ifndef _pkt_h | ||
40 | #define _pkt_h 1 | ||
41 | |||
42 | #ifndef lint | ||
43 | #ifdef SCCS | ||
44 | static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h 1.1" ; | ||
45 | #endif | ||
46 | #endif | ||
47 | |||
48 | /************************************************* | ||
49 | * Overlayed onto the Data fields of a regular | ||
50 | * Packet | ||
51 | ************************************************/ | ||
52 | typedef struct BOOT_PKT BOOT_PKT ; | ||
53 | struct BOOT_PKT { | ||
54 | short seq_num ; | ||
55 | char data[10] ; | ||
56 | } ; | ||
57 | |||
58 | |||
59 | #endif | ||
60 | |||
61 | /*********** end of file ***********/ | ||
62 | |||
diff --git a/drivers/char/rio/brates.h b/drivers/char/rio/brates.h new file mode 100644 index 000000000000..bd4fc84ec6cf --- /dev/null +++ b/drivers/char/rio/brates.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* BRATES.H ******* | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Jeremy Rolls | ||
8 | Date : 1 Nov 1990 | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _brates_h | ||
38 | #ifndef lint | ||
39 | /* static char * _brates_h_sccs = "@(#)brates.h 1.4"; */ | ||
40 | #endif | ||
41 | #define _brates_h 1 | ||
42 | /* List of baud rate defines. Most are borrowed from /usr/include/sys/termio.h | ||
43 | */ | ||
44 | #ifndef INKERNEL | ||
45 | |||
46 | #define B0 0x00 | ||
47 | #define B50 0x01 | ||
48 | #define B75 0x02 | ||
49 | #define B110 0x03 | ||
50 | #define B134 0x04 | ||
51 | #define B150 0x05 | ||
52 | #define B200 0x06 | ||
53 | #define B300 0x07 | ||
54 | #define B600 0x08 | ||
55 | #define B1200 0x09 | ||
56 | #define B1800 0x0a | ||
57 | #define B2400 0x0b | ||
58 | #define B4800 0x0c | ||
59 | #define B9600 0x0d | ||
60 | #define B19200 0x0e | ||
61 | #define B38400 0x0f | ||
62 | |||
63 | #endif | ||
64 | |||
65 | /* | ||
66 | ** The following baudrates may or may not be defined | ||
67 | ** on various UNIX systems. | ||
68 | ** If they are not then we define them. | ||
69 | ** If they are then we do not define them ;-) | ||
70 | ** | ||
71 | ** This is appalling that we use same definitions as UNIX | ||
72 | ** for our own download code as there is no garuntee that | ||
73 | ** B57600 will be defined as 0x11 by a UNIX system.... | ||
74 | ** Arghhhhh!!!!!!!!!!!!!! | ||
75 | */ | ||
76 | #if !defined(B56000) | ||
77 | #define B56000 0x10 | ||
78 | #endif | ||
79 | |||
80 | #if !defined(B57600) | ||
81 | #define B57600 0x11 | ||
82 | #endif | ||
83 | |||
84 | #if !defined(B64000) | ||
85 | #define B64000 0x12 | ||
86 | #endif | ||
87 | |||
88 | #if !defined(B115200) | ||
89 | #define B115200 0x13 | ||
90 | #endif | ||
91 | |||
92 | |||
93 | #if !defined(B2000) | ||
94 | #define B2000 0x14 | ||
95 | #endif | ||
96 | |||
97 | |||
98 | #define MAX_RATE B2000 | ||
99 | |||
100 | struct baud_rate /* Tag for baud rates */ | ||
101 | { | ||
102 | /* short host_rate,*/ /* As passed by the driver */ | ||
103 | short divisor, /* The divisor */ | ||
104 | prescaler; /* The pre-scaler */ | ||
105 | }; | ||
106 | |||
107 | #endif | ||
diff --git a/drivers/char/rio/chan.h b/drivers/char/rio/chan.h new file mode 100644 index 000000000000..5b306543328f --- /dev/null +++ b/drivers/char/rio/chan.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * | ||
3 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | #ifndef _chan_h | ||
20 | #define _chan_h | ||
21 | |||
22 | #ifndef lint | ||
23 | #ifdef SCCS | ||
24 | static char *_rio_chan_h_sccs = "@(#)chan.h 1.1" ; | ||
25 | #endif | ||
26 | #endif | ||
27 | |||
28 | #define Link0 0 | ||
29 | #define Link1 1 | ||
30 | #define Link2 2 | ||
31 | #define Link3 3 | ||
32 | |||
33 | #endif | ||
diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h new file mode 100644 index 000000000000..cf056a990f18 --- /dev/null +++ b/drivers/char/rio/cirrus.h | |||
@@ -0,0 +1,463 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* CIRRUS.H ******* | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Jeremy Rolls | ||
8 | Date : 3 Aug 1990 | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _cirrus_h | ||
38 | #ifndef lint | ||
39 | /* static char* _cirrus_h_sccs = "@(#)cirrus.h 1.16"; */ | ||
40 | #endif | ||
41 | #define _cirrus_h 1 | ||
42 | |||
43 | #ifdef RTA | ||
44 | #define TO_UART RX | ||
45 | #define TO_DRIVER TX | ||
46 | #endif | ||
47 | |||
48 | #ifdef HOST | ||
49 | #define TO_UART TX | ||
50 | #define TO_DRIVER RX | ||
51 | #endif | ||
52 | #ifdef RTA | ||
53 | /* Miscellaneous defines for CIRRUS addresses and related logic for | ||
54 | interrupts etc. | ||
55 | */ | ||
56 | #define MAP(a) ((short *)(cirrus_base + (a))) | ||
57 | #define outp(a,b) (*MAP (a) =(b)) | ||
58 | #define inp(a) ((*MAP (a)) & 0xff) | ||
59 | #define CIRRUS_FIRST (short*)0x7300 | ||
60 | #define CIRRUS_SECOND (short*)0x7200 | ||
61 | #define CIRRUS_THIRD (short*)0x7100 | ||
62 | #define CIRRUS_FOURTH (short*)0x7000 | ||
63 | #define PORTS_ON_CIRRUS 4 | ||
64 | #define CIRRUS_FIFO_SIZE 12 | ||
65 | #define SPACE 0x20 | ||
66 | #define TAB 0x09 | ||
67 | #define LINE_FEED 0x0a | ||
68 | #define CARRIAGE_RETURN 0x0d | ||
69 | #define BACKSPACE 0x08 | ||
70 | #define SPACES_IN_TABS 8 | ||
71 | #define SEND_ESCAPE 0x00 | ||
72 | #define START_BREAK 0x81 | ||
73 | #define TIMER_TICK 0x82 | ||
74 | #define STOP_BREAK 0x83 | ||
75 | #define BASE(a) ((a) < 4 ? (short*)CIRRUS_FIRST : ((a) < 8 ? (short *)CIRRUS_SECOND : ((a) < 12 ? (short*)CIRRUS_THIRD : (short *)CIRRUS_FOURTH))) | ||
76 | #define txack1 ((short *)0x7104) | ||
77 | #define rxack1 ((short *)0x7102) | ||
78 | #define mdack1 ((short *)0x7106) | ||
79 | #define txack2 ((short *)0x7006) | ||
80 | #define rxack2 ((short *)0x7004) | ||
81 | #define mdack2 ((short *)0x7100) | ||
82 | #define int_latch ((short *) 0x7800) | ||
83 | #define int_status ((short *) 0x7c00) | ||
84 | #define tx1_pending 0x20 | ||
85 | #define rx1_pending 0x10 | ||
86 | #define md1_pending 0x40 | ||
87 | #define tx2_pending 0x02 | ||
88 | #define rx2_pending 0x01 | ||
89 | #define md2_pending 0x40 | ||
90 | #define module1_bits 0x07 | ||
91 | #define module1_modern 0x08 | ||
92 | #define module2_bits 0x70 | ||
93 | #define module2_modern 0x80 | ||
94 | #define module_blank 0xf | ||
95 | #define rs232_d25 0x0 | ||
96 | #define rs232_rj45 0x1 | ||
97 | #define rs422_d25 0x3 | ||
98 | #define parallel 0x5 | ||
99 | |||
100 | #define CLK0 0x00 | ||
101 | #define CLK1 0x01 | ||
102 | #define CLK2 0x02 | ||
103 | #define CLK3 0x03 | ||
104 | #define CLK4 0x04 | ||
105 | |||
106 | #define CIRRUS_REVC 0x42 | ||
107 | #define CIRRUS_REVE 0x44 | ||
108 | |||
109 | #define TURNON 1 | ||
110 | #define TURNOFF 0 | ||
111 | |||
112 | /* The list of CIRRUS registers. | ||
113 | NB. These registers are relative values on 8 bit boundaries whereas | ||
114 | on the RTA's the CIRRUS registers are on word boundaries. Use pointer | ||
115 | arithmetic (short *) to obtain the real addresses required */ | ||
116 | #define ccr 0x05 /* Channel Command Register */ | ||
117 | #define ier 0x06 /* Interrupt Enable Register */ | ||
118 | #define cor1 0x08 /* Channel Option Register 1 */ | ||
119 | #define cor2 0x09 /* Channel Option Register 2 */ | ||
120 | #define cor3 0x0a /* Channel Option Register 3 */ | ||
121 | #define cor4 0x1e /* Channel Option Register 4 */ | ||
122 | #define cor5 0x1f /* Channel Option Register 5 */ | ||
123 | |||
124 | #define ccsr 0x0b /* Channel Control Status Register */ | ||
125 | #define rdcr 0x0e /* Receive Data Count Register */ | ||
126 | #define tdcr 0x12 /* Transmit Data Count Register */ | ||
127 | #define mcor1 0x15 /* Modem Change Option Register 1 */ | ||
128 | #define mcor2 0x16 /* Modem Change Option Regsiter 2 */ | ||
129 | |||
130 | #define livr 0x18 /* Local Interrupt Vector Register */ | ||
131 | #define schr1 0x1a /* Special Character Register 1 */ | ||
132 | #define schr2 0x1b /* Special Character Register 2 */ | ||
133 | #define schr3 0x1c /* Special Character Register 3 */ | ||
134 | #define schr4 0x1d /* Special Character Register 4 */ | ||
135 | |||
136 | #define rtr 0x20 /* Receive Timer Register */ | ||
137 | #define rtpr 0x21 /* Receive Timeout Period Register */ | ||
138 | #define lnc 0x24 /* Lnext character */ | ||
139 | |||
140 | #define rivr 0x43 /* Receive Interrupt Vector Register */ | ||
141 | #define tivr 0x42 /* Transmit Interrupt Vector Register */ | ||
142 | #define mivr 0x41 /* Modem Interrupt Vector Register */ | ||
143 | #define gfrcr 0x40 /* Global Firmware Revision code Reg */ | ||
144 | #define ricr 0x44 /* Receive Interrupting Channel Reg */ | ||
145 | #define ticr 0x45 /* Transmit Interrupting Channel Reg */ | ||
146 | #define micr 0x46 /* Modem Interrupting Channel Register */ | ||
147 | |||
148 | #define gcr 0x4b /* Global configuration register*/ | ||
149 | #define misr 0x4c /* Modem interrupt status register */ | ||
150 | |||
151 | #define rbusr 0x59 | ||
152 | #define tbusr 0x5a | ||
153 | #define mbusr 0x5b | ||
154 | |||
155 | #define eoir 0x60 /* End Of Interrupt Register */ | ||
156 | #define rdsr 0x62 /* Receive Data / Status Register */ | ||
157 | #define tdr 0x63 /* Transmit Data Register */ | ||
158 | #define svrr 0x67 /* Service Request Register */ | ||
159 | |||
160 | #define car 0x68 /* Channel Access Register */ | ||
161 | #define mir 0x69 /* Modem Interrupt Register */ | ||
162 | #define tir 0x6a /* Transmit Interrupt Register */ | ||
163 | #define rir 0x6b /* Receive Interrupt Register */ | ||
164 | #define msvr1 0x6c /* Modem Signal Value Register 1 */ | ||
165 | #define msvr2 0x6d /* Modem Signal Value Register 2*/ | ||
166 | #define psvr 0x6f /* Printer Signal Value Register*/ | ||
167 | |||
168 | #define tbpr 0x72 /* Transmit Baud Rate Period Register */ | ||
169 | #define tcor 0x76 /* Transmit Clock Option Register */ | ||
170 | |||
171 | #define rbpr 0x78 /* Receive Baud Rate Period Register */ | ||
172 | #define rber 0x7a /* Receive Baud Rate Extension Register */ | ||
173 | #define rcor 0x7c /* Receive Clock Option Register*/ | ||
174 | #define ppr 0x7e /* Prescalar Period Register */ | ||
175 | |||
176 | /* Misc registers used for forcing the 1400 out of its reset woes */ | ||
177 | #define airl 0x6d | ||
178 | #define airm 0x6e | ||
179 | #define airh 0x6f | ||
180 | #define btcr 0x66 | ||
181 | #define mtcr 0x6c | ||
182 | #define tber 0x74 | ||
183 | |||
184 | #endif /* #ifdef RTA */ | ||
185 | |||
186 | |||
187 | /* Bit fields for particular registers */ | ||
188 | |||
189 | /* GCR */ | ||
190 | #define GCR_SERIAL 0x00 /* Configure as serial channel */ | ||
191 | #define GCR_PARALLEL 0x80 /* Configure as parallel channel */ | ||
192 | |||
193 | /* RDSR - when status read from FIFO */ | ||
194 | #define RDSR_BREAK 0x08 /* Break received */ | ||
195 | #define RDSR_TIMEOUT 0x80 /* No new data timeout */ | ||
196 | #define RDSR_SC1 0x10 /* Special char 1 (tx XON) matched */ | ||
197 | #define RDSR_SC2 0x20 /* Special char 2 (tx XOFF) matched */ | ||
198 | #define RDSR_SC12_MASK 0x30 /* Mask for special chars 1 and 2 */ | ||
199 | |||
200 | /* PPR */ | ||
201 | #define PPR_DEFAULT 0x31 /* Default value - for a 25Mhz clock gives | ||
202 | a timeout period of 1ms */ | ||
203 | |||
204 | /* LIVR */ | ||
205 | #define LIVR_EXCEPTION 0x07 /* Receive exception interrupt */ | ||
206 | |||
207 | /* CCR */ | ||
208 | #define CCR_RESET 0x80 /* Reset channel */ | ||
209 | #define CCR_CHANGE 0x4e /* COR's have changed - NB always change all | ||
210 | COR's */ | ||
211 | #define CCR_WFLUSH 0x82 /* Flush transmit FIFO and TSR / THR */ | ||
212 | |||
213 | #define CCR_SENDSC1 0x21 /* Send special character one */ | ||
214 | #define CCR_SENDSC2 0x22 /* Send special character two */ | ||
215 | #define CCR_SENDSC3 0x23 /* Send special character three */ | ||
216 | #define CCR_SENDSC4 0x24 /* Send special character four */ | ||
217 | |||
218 | #define CCR_TENABLE 0x18 /* Enable transmitter */ | ||
219 | #define CCR_TDISABLE 0x14 /* Disable transmitter */ | ||
220 | #define CCR_RENABLE 0x12 /* Enable receiver */ | ||
221 | #define CCR_RDISABLE 0x11 /* Disable receiver */ | ||
222 | |||
223 | #define CCR_READY 0x00 /* CCR is ready for another command */ | ||
224 | |||
225 | /* CCSR */ | ||
226 | #define CCSR_TXENABLE 0x08 /* Transmitter enable */ | ||
227 | #define CCSR_RXENABLE 0x80 /* Receiver enable */ | ||
228 | #define CCSR_TXFLOWOFF 0x04 /* Transmit flow off */ | ||
229 | #define CCSR_TXFLOWON 0x02 /* Transmit flow on */ | ||
230 | |||
231 | /* SVRR */ | ||
232 | #define SVRR_RECEIVE 0x01 /* Receive interrupt pending */ | ||
233 | #define SVRR_TRANSMIT 0x02 /* Transmit interrupt pending */ | ||
234 | #define SVRR_MODEM 0x04 /* Modem interrupt pending */ | ||
235 | |||
236 | /* CAR */ | ||
237 | #define CAR_PORTS 0x03 /* Bit fields for ports */ | ||
238 | |||
239 | /* IER */ | ||
240 | #define IER_MODEM 0x80 /* Change in modem status */ | ||
241 | #define IER_RECEIVE 0x10 /* Good data / data exception */ | ||
242 | #define IER_TRANSMITR 0x04 /* Transmit ready (FIFO empty) */ | ||
243 | #define IER_TRANSMITE 0x02 /* Transmit empty */ | ||
244 | #define IER_TIMEOUT 0x01 /* Timeout on no data */ | ||
245 | |||
246 | #define IER_DEFAULT 0x94 /* Default values */ | ||
247 | #define IER_PARALLEL 0x84 /* Default for Parallel */ | ||
248 | #define IER_EMPTY 0x92 /* Transmitter empty rather than ready */ | ||
249 | |||
250 | /* COR1 - Driver only */ | ||
251 | #define COR1_INPCK 0x10 /* Check parity of received characters */ | ||
252 | |||
253 | /* COR1 - driver and RTA */ | ||
254 | #define COR1_ODD 0x80 /* Odd parity */ | ||
255 | #define COR1_EVEN 0x00 /* Even parity */ | ||
256 | #define COR1_NOP 0x00 /* No parity */ | ||
257 | #define COR1_FORCE 0x20 /* Force parity */ | ||
258 | #define COR1_NORMAL 0x40 /* With parity */ | ||
259 | #define COR1_1STOP 0x00 /* 1 stop bit */ | ||
260 | #define COR1_15STOP 0x04 /* 1.5 stop bits */ | ||
261 | #define COR1_2STOP 0x08 /* 2 stop bits */ | ||
262 | #define COR1_5BITS 0x00 /* 5 data bits */ | ||
263 | #define COR1_6BITS 0x01 /* 6 data bits */ | ||
264 | #define COR1_7BITS 0x02 /* 7 data bits */ | ||
265 | #define COR1_8BITS 0x03 /* 8 data bits */ | ||
266 | |||
267 | #define COR1_HOST 0xef /* Safe host bits */ | ||
268 | |||
269 | /* RTA only */ | ||
270 | #define COR1_CINPCK 0x00 /* Check parity of received characters */ | ||
271 | #define COR1_CNINPCK 0x10 /* Don't check parity */ | ||
272 | |||
273 | /* COR2 bits for both RTA and driver use */ | ||
274 | #define COR2_IXANY 0x80 /* IXANY - any character is XON */ | ||
275 | #define COR2_IXON 0x40 /* IXON - enable tx soft flowcontrol */ | ||
276 | #define COR2_RTSFLOW 0x02 /* Enable tx hardware flow control */ | ||
277 | |||
278 | /* Additional driver bits */ | ||
279 | #define COR2_HUPCL 0x20 /* Hang up on close */ | ||
280 | #define COR2_CTSFLOW 0x04 /* Enable rx hardware flow control */ | ||
281 | #define COR2_IXOFF 0x01 /* Enable rx software flow control */ | ||
282 | #define COR2_DTRFLOW 0x08 /* Enable tx hardware flow control */ | ||
283 | |||
284 | /* RTA use only */ | ||
285 | #define COR2_ETC 0x20 /* Embedded transmit options */ | ||
286 | #define COR2_LOCAL 0x10 /* Local loopback mode */ | ||
287 | #define COR2_REMOTE 0x08 /* Remote loopback mode */ | ||
288 | #define COR2_HOST 0xc2 /* Safe host bits */ | ||
289 | |||
290 | /* COR3 - RTA use only */ | ||
291 | #define COR3_SCDRNG 0x80 /* Enable special char detect for range */ | ||
292 | #define COR3_SCD34 0x40 /* Special character detect for SCHR's 3 + 4 */ | ||
293 | #define COR3_FCT 0x20 /* Flow control transparency */ | ||
294 | #define COR3_SCD12 0x10 /* Special character detect for SCHR's 1 + 2 */ | ||
295 | #define COR3_FIFO12 0x0c /* 12 chars for receive FIFO threshold */ | ||
296 | #define COR3_FIFO10 0x0a /* 10 chars for receive FIFO threshold */ | ||
297 | #define COR3_FIFO8 0x08 /* 8 chars for receive FIFO threshold */ | ||
298 | #define COR3_FIFO6 0x06 /* 6 chars for receive FIFO threshold */ | ||
299 | |||
300 | #define COR3_THRESHOLD COR3_FIFO8 /* MUST BE LESS THAN MCOR_THRESHOLD */ | ||
301 | |||
302 | #define COR3_DEFAULT (COR3_FCT | COR3_THRESHOLD) | ||
303 | /* Default bits for COR3 */ | ||
304 | |||
305 | /* COR4 driver and RTA use */ | ||
306 | #define COR4_IGNCR 0x80 /* Throw away CR's on input */ | ||
307 | #define COR4_ICRNL 0x40 /* Map CR -> NL on input */ | ||
308 | #define COR4_INLCR 0x20 /* Map NL -> CR on input */ | ||
309 | #define COR4_IGNBRK 0x10 /* Ignore Break */ | ||
310 | #define COR4_NBRKINT 0x08 /* No interrupt on break (-BRKINT) */ | ||
311 | #define COR4_RAISEMOD 0x01 /* Raise modem output lines on non-zero baud */ | ||
312 | |||
313 | |||
314 | /* COR4 driver only */ | ||
315 | #define COR4_IGNPAR 0x04 /* IGNPAR (ignore characters with errors) */ | ||
316 | #define COR4_PARMRK 0x02 /* PARMRK */ | ||
317 | |||
318 | #define COR4_HOST 0xf8 /* Safe host bits */ | ||
319 | |||
320 | /* COR4 RTA only */ | ||
321 | #define COR4_CIGNPAR 0x02 /* Thrown away bad characters */ | ||
322 | #define COR4_CPARMRK 0x04 /* PARMRK characters */ | ||
323 | #define COR4_CNPARMRK 0x03 /* Don't PARMRK */ | ||
324 | |||
325 | /* COR5 driver and RTA use */ | ||
326 | #define COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */ | ||
327 | #define COR5_LNE 0x40 /* Enable LNEXT processing */ | ||
328 | #define COR5_CMOE 0x20 /* Match good and errored characters */ | ||
329 | #define COR5_ONLCR 0x02 /* NL -> CR NL on output */ | ||
330 | #define COR5_OCRNL 0x01 /* CR -> NL on output */ | ||
331 | |||
332 | /* | ||
333 | ** Spare bits - these are not used in the CIRRUS registers, so we use | ||
334 | ** them to set various other features. | ||
335 | */ | ||
336 | /* | ||
337 | ** tstop and tbusy indication | ||
338 | */ | ||
339 | #define COR5_TSTATE_ON 0x08 /* Turn on monitoring of tbusy and tstop */ | ||
340 | #define COR5_TSTATE_OFF 0x04 /* Turn off monitoring of tbusy and tstop */ | ||
341 | /* | ||
342 | ** TAB3 | ||
343 | */ | ||
344 | #define COR5_TAB3 0x10 /* TAB3 mode */ | ||
345 | |||
346 | #define COR5_HOST 0xc3 /* Safe host bits */ | ||
347 | |||
348 | /* CCSR */ | ||
349 | #define CCSR_TXFLOFF 0x04 /* Tx is xoffed */ | ||
350 | |||
351 | /* MSVR1 */ | ||
352 | /* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the | ||
353 | RTA. This is because otherwise DCD would get lost on the 1 parallel / 3 | ||
354 | serial option. | ||
355 | */ | ||
356 | #define MSVR1_CD 0x80 /* CD (DSR on Cirrus) */ | ||
357 | #define MSVR1_RTS 0x40 /* RTS (CTS on Cirrus) */ | ||
358 | #define MSVR1_RI 0x20 /* RI */ | ||
359 | #define MSVR1_DTR 0x10 /* DTR (CD on Cirrus) */ | ||
360 | #define MSVR1_CTS 0x01 /* CTS output pin (RTS on Cirrus) */ | ||
361 | /* Next two used to indicate state of tbusy and tstop to driver */ | ||
362 | #define MSVR1_TSTOP 0x08 /* Set if port flow controlled */ | ||
363 | #define MSVR1_TEMPTY 0x04 /* Set if port tx buffer empty */ | ||
364 | |||
365 | #define MSVR1_HOST 0xf3 /* The bits the host wants */ | ||
366 | |||
367 | /* MSVR2 */ | ||
368 | #define MSVR2_DSR 0x02 /* DSR output pin (DTR on Cirrus) */ | ||
369 | |||
370 | /* MCOR */ | ||
371 | #define MCOR_CD 0x80 /* CD (DSR on Cirrus) */ | ||
372 | #define MCOR_RTS 0x40 /* RTS (CTS on Cirrus) */ | ||
373 | #define MCOR_RI 0x20 /* RI */ | ||
374 | #define MCOR_DTR 0x10 /* DTR (CD on Cirrus) */ | ||
375 | |||
376 | #define MCOR_DEFAULT (MCOR_CD | MCOR_RTS | MCOR_RI | MCOR_DTR) | ||
377 | #define MCOR_FULLMODEM MCOR_DEFAULT | ||
378 | #define MCOR_RJ45 (MCOR_CD | MCOR_RTS | MCOR_DTR) | ||
379 | #define MCOR_RESTRICTED (MCOR_CD | MCOR_RTS) | ||
380 | |||
381 | /* More MCOR - H/W Handshake (flowcontrol) stuff */ | ||
382 | #define MCOR_THRESH8 0x08 /* eight characters then we stop */ | ||
383 | #define MCOR_THRESH9 0x09 /* nine characters then we stop */ | ||
384 | #define MCOR_THRESH10 0x0A /* ten characters then we stop */ | ||
385 | #define MCOR_THRESH11 0x0B /* eleven characters then we stop */ | ||
386 | |||
387 | #define MCOR_THRESHBITS 0x0F /* mask for ANDing out the above */ | ||
388 | |||
389 | #define MCOR_THRESHOLD MCOR_THRESH9 /* MUST BE GREATER THAN COR3_THRESHOLD */ | ||
390 | |||
391 | |||
392 | /* RTPR */ | ||
393 | #define RTPR_DEFAULT 0x02 /* Default */ | ||
394 | |||
395 | |||
396 | /* Defines for the subscripts of a CONFIG packet */ | ||
397 | #define CONFIG_COR1 1 /* Option register 1 */ | ||
398 | #define CONFIG_COR2 2 /* Option register 2 */ | ||
399 | #define CONFIG_COR4 3 /* Option register 4 */ | ||
400 | #define CONFIG_COR5 4 /* Option register 5 */ | ||
401 | #define CONFIG_TXXON 5 /* Tx XON character */ | ||
402 | #define CONFIG_TXXOFF 6 /* Tx XOFF character */ | ||
403 | #define CONFIG_RXXON 7 /* Rx XON character */ | ||
404 | #define CONFIG_RXXOFF 8 /* Rx XOFF character */ | ||
405 | #define CONFIG_LNEXT 9 /* LNEXT character */ | ||
406 | #define CONFIG_TXBAUD 10 /* Tx baud rate */ | ||
407 | #define CONFIG_RXBAUD 11 /* Rx baud rate */ | ||
408 | |||
409 | /* Port status stuff */ | ||
410 | #define IDLE_CLOSED 0 /* Closed */ | ||
411 | #define IDLE_OPEN 1 /* Idle open */ | ||
412 | #define IDLE_BREAK 2 /* Idle on break */ | ||
413 | |||
414 | /* Subscript of MODEM STATUS packet */ | ||
415 | #define MODEM_VALUE 3 /* Current values of handshake pins */ | ||
416 | /* Subscript of SBREAK packet */ | ||
417 | #define BREAK_LENGTH 1 /* Length of a break in slices of 0.01 seconds | ||
418 | 0 = stay on break until an EBREAK command | ||
419 | is sent */ | ||
420 | |||
421 | |||
422 | #define PRE_EMPTIVE 0x80 /* Pre-emptive bit in command field */ | ||
423 | |||
424 | /* Packet types going from Host to remote - with the exception of OPEN, MOPEN, | ||
425 | CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not | ||
426 | be used | ||
427 | */ | ||
428 | #define OPEN 0x00 /* Open a port */ | ||
429 | #define CONFIG 0x01 /* Configure a port */ | ||
430 | #define MOPEN 0x02 /* Modem open (block for DCD) */ | ||
431 | #define CLOSE 0x03 /* Close a port */ | ||
432 | #define WFLUSH (0x04 | PRE_EMPTIVE) /* Write flush */ | ||
433 | #define RFLUSH (0x05 | PRE_EMPTIVE) /* Read flush */ | ||
434 | #define RESUME (0x06 | PRE_EMPTIVE) /* Resume if xoffed */ | ||
435 | #define SBREAK 0x07 /* Start break */ | ||
436 | #define EBREAK 0x08 /* End break */ | ||
437 | #define SUSPEND (0x09 | PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */ | ||
438 | #define FCLOSE (0x0a | PRE_EMPTIVE) /* Force close */ | ||
439 | #define XPRINT 0x0b /* Xprint packet */ | ||
440 | #define MBIS (0x0c | PRE_EMPTIVE) /* Set modem lines */ | ||
441 | #define MBIC (0x0d | PRE_EMPTIVE) /* Clear modem lines */ | ||
442 | #define MSET (0x0e | PRE_EMPTIVE) /* Set modem lines */ | ||
443 | #define PCLOSE 0x0f /* Pseudo close - Leaves rx/tx enabled */ | ||
444 | #define MGET (0x10 | PRE_EMPTIVE) /* Force update of modem status */ | ||
445 | #define MEMDUMP (0x11 | PRE_EMPTIVE) /* Send back mem from addr supplied */ | ||
446 | #define READ_REGISTER (0x12 | PRE_EMPTIVE) /* Read CD1400 register (debug) */ | ||
447 | |||
448 | /* "Command" packets going from remote to host COMPLETE and MODEM_STATUS | ||
449 | use data[4] / data[3] to indicate current state and modem status respectively | ||
450 | */ | ||
451 | |||
452 | #define COMPLETE (0x20 | PRE_EMPTIVE) | ||
453 | /* Command complete */ | ||
454 | #define BREAK_RECEIVED (0x21 | PRE_EMPTIVE) | ||
455 | /* Break received */ | ||
456 | #define MODEM_STATUS (0x22 | PRE_EMPTIVE) | ||
457 | /* Change in modem status */ | ||
458 | |||
459 | /* "Command" packet that could go either way - handshake wake-up */ | ||
460 | #define HANDSHAKE (0x23 | PRE_EMPTIVE) | ||
461 | /* Wake-up to HOST / RTA */ | ||
462 | |||
463 | #endif | ||
diff --git a/drivers/char/rio/cmd.h b/drivers/char/rio/cmd.h new file mode 100644 index 000000000000..c369edaea2b3 --- /dev/null +++ b/drivers/char/rio/cmd.h | |||
@@ -0,0 +1,84 @@ | |||
1 | |||
2 | |||
3 | /**************************************************************************** | ||
4 | ******* ******* | ||
5 | ******* C O M M A N D P A C K E T H E A D E R S | ||
6 | ******* ******* | ||
7 | **************************************************************************** | ||
8 | |||
9 | Author : Ian Nandhra | ||
10 | Date : | ||
11 | |||
12 | * | ||
13 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | |||
29 | Version : 0.01 | ||
30 | |||
31 | |||
32 | Mods | ||
33 | ---------------------------------------------------------------------------- | ||
34 | Date By Description | ||
35 | ---------------------------------------------------------------------------- | ||
36 | |||
37 | ***************************************************************************/ | ||
38 | |||
39 | |||
40 | #ifndef _cmd_h | ||
41 | #define _cmd_h | ||
42 | |||
43 | #ifndef lint | ||
44 | #ifdef SCCS | ||
45 | static char *_rio_cmd_h_sccs = "@(#)cmd.h 1.1" ; | ||
46 | #endif | ||
47 | #endif | ||
48 | |||
49 | |||
50 | #define PRE_EMPTIVE_CMD 0x80 | ||
51 | #define INLINE_CMD ~PRE_EMPTIVE_CMD | ||
52 | |||
53 | #define CMD_IGNORE_PKT ( (ushort) 0) | ||
54 | #define CMD_STATUS_REQ ( (ushort) 1) | ||
55 | #define CMD_UNIT_STATUS_REQ ( (ushort) 2) /* Is this needed ??? */ | ||
56 | #define CMD_CONF_PORT ( (ushort) 3) | ||
57 | #define CMD_CONF_UNIT ( (ushort) 4) | ||
58 | #define CMD_ROUTE_MAP_REQ ( (ushort) 5) | ||
59 | #define CMD_FLUSH_TX ( (ushort) 6) | ||
60 | #define CMD_FLUSH_RX ( (ushort) 7) | ||
61 | #define CMD_PARTION_PORT ( (ushort) 8) | ||
62 | #define CMD_RESET_PORT ( (ushort) 0x0a) | ||
63 | #define CMD_BOOT_UNIT ( (ushort) 0x0b) | ||
64 | #define CMD_FOUND_UNIT ( (ushort) 0x0c) | ||
65 | #define CMD_ATTACHED_RTA_2 ( (ushort) 0x0d) | ||
66 | #define CMD_PROVIDE_BOOT ( (ushort) 0x0e) | ||
67 | #define CMD_CIRRUS ( (ushort) 0x0f) | ||
68 | |||
69 | #define FORM_STATUS_PKT ( (ushort) 1 ) | ||
70 | #define FORM_POLL_PKT ( (ushort) 2 ) | ||
71 | #define FORM_LINK_STATUS_PKT ( (ushort) 3 ) | ||
72 | |||
73 | |||
74 | #define CMD_DATA_PORT ( (ushort) 1 ) | ||
75 | #define CMD_DATA ( (ushort) 2 ) | ||
76 | |||
77 | #define CMD_TX_PART ( (ushort) 2 ) | ||
78 | #define CMD_RX_PART ( (ushort) 3 ) | ||
79 | #define CMD_RX_LIMIT ( (ushort) 4 ) | ||
80 | |||
81 | #endif | ||
82 | |||
83 | /*********** end of file ***********/ | ||
84 | |||
diff --git a/drivers/char/rio/cmdblk.h b/drivers/char/rio/cmdblk.h new file mode 100644 index 000000000000..2b8efbdbee1c --- /dev/null +++ b/drivers/char/rio/cmdblk.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : cmdblk.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:09 | ||
26 | ** Retrieved : 11/6/98 11:34:20 | ||
27 | ** | ||
28 | ** ident @(#)cmdblk.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_cmdblk_h__ | ||
34 | #define __rio_cmdblk_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | #ifndef lint | ||
38 | static char *_cmdblk_h_sccs_ = "@(#)cmdblk.h 1.2"; | ||
39 | #endif | ||
40 | #endif | ||
41 | |||
42 | /* | ||
43 | ** the structure of a command block, used to queue commands destined for | ||
44 | ** a rup. | ||
45 | */ | ||
46 | |||
47 | struct CmdBlk | ||
48 | { | ||
49 | struct CmdBlk *NextP; /* Pointer to next command block */ | ||
50 | struct PKT Packet; /* A packet, to copy to the rup */ | ||
51 | /* The func to call to check if OK */ | ||
52 | int (*PreFuncP)(int, struct CmdBlk *); | ||
53 | int PreArg; /* The arg for the func */ | ||
54 | /* The func to call when completed */ | ||
55 | int (*PostFuncP)(int, struct CmdBlk *); | ||
56 | int PostArg; /* The arg for the func */ | ||
57 | }; | ||
58 | |||
59 | #define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4)) | ||
60 | #endif | ||
diff --git a/drivers/char/rio/cmdpkt.h b/drivers/char/rio/cmdpkt.h new file mode 100644 index 000000000000..46befd354f20 --- /dev/null +++ b/drivers/char/rio/cmdpkt.h | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : cmdpkt.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:09 | ||
26 | ** Retrieved : 11/6/98 11:34:20 | ||
27 | ** | ||
28 | ** ident @(#)cmdpkt.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | #ifndef __rio_cmdpkt_h__ | ||
33 | #define __rio_cmdpkt_h__ | ||
34 | |||
35 | #ifdef SCCS_LABELS | ||
36 | #ifndef lint | ||
37 | static char *_cmdpkt_h_sccs_ = "@(#)cmdpkt.h 1.2"; | ||
38 | #endif | ||
39 | #endif | ||
40 | |||
41 | /* | ||
42 | ** overlays for the data area of a packet. Used in both directions | ||
43 | ** (to build a packet to send, and to interpret a packet that arrives) | ||
44 | ** and is very inconvenient for MIPS, so they appear as two separate | ||
45 | ** structures - those used for modifying/reading packets on the card | ||
46 | ** and those for modifying/reading packets in real memory, which have an _M | ||
47 | ** suffix. | ||
48 | */ | ||
49 | |||
50 | #define RTA_BOOT_DATA_SIZE (PKT_MAX_DATA_LEN-2) | ||
51 | |||
52 | /* | ||
53 | ** The boot information packet looks like this: | ||
54 | ** This structure overlays a PktCmd->CmdData structure, and so starts | ||
55 | ** at Data[2] in the actual pkt! | ||
56 | */ | ||
57 | struct BootSequence | ||
58 | { | ||
59 | WORD NumPackets; | ||
60 | WORD LoadBase; | ||
61 | WORD CodeSize; | ||
62 | }; | ||
63 | |||
64 | #define BOOT_SEQUENCE_LEN 8 | ||
65 | |||
66 | struct SamTop | ||
67 | { | ||
68 | BYTE Unit; | ||
69 | BYTE Link; | ||
70 | }; | ||
71 | |||
72 | struct CmdHdr | ||
73 | { | ||
74 | BYTE PcCommand; | ||
75 | union | ||
76 | { | ||
77 | BYTE PcPhbNum; | ||
78 | BYTE PcLinkNum; | ||
79 | BYTE PcIDNum; | ||
80 | } U0; | ||
81 | }; | ||
82 | |||
83 | |||
84 | struct PktCmd | ||
85 | { | ||
86 | union | ||
87 | { | ||
88 | struct | ||
89 | { | ||
90 | struct CmdHdr CmdHdr; | ||
91 | struct BootSequence PcBootSequence; | ||
92 | } S1; | ||
93 | struct | ||
94 | { | ||
95 | WORD PcSequence; | ||
96 | BYTE PcBootData[RTA_BOOT_DATA_SIZE]; | ||
97 | } S2; | ||
98 | struct | ||
99 | { | ||
100 | WORD __crud__; | ||
101 | BYTE PcUniqNum[4]; /* this is really a uint. */ | ||
102 | BYTE PcModuleTypes; /* what modules are fitted */ | ||
103 | } S3; | ||
104 | struct | ||
105 | { | ||
106 | struct CmdHdr CmdHdr; | ||
107 | BYTE __undefined__; | ||
108 | BYTE PcModemStatus; | ||
109 | BYTE PcPortStatus; | ||
110 | BYTE PcSubCommand; /* commands like mem or register dump */ | ||
111 | WORD PcSubAddr; /* Address for command */ | ||
112 | BYTE PcSubData[64]; /* Date area for command */ | ||
113 | } S4; | ||
114 | struct | ||
115 | { | ||
116 | struct CmdHdr CmdHdr; | ||
117 | BYTE PcCommandText[1]; | ||
118 | BYTE __crud__[20]; | ||
119 | BYTE PcIDNum2; /* It had to go somewhere! */ | ||
120 | } S5; | ||
121 | struct | ||
122 | { | ||
123 | struct CmdHdr CmdHdr; | ||
124 | struct SamTop Topology[LINKS_PER_UNIT]; | ||
125 | } S6; | ||
126 | } U1; | ||
127 | }; | ||
128 | |||
129 | struct PktCmd_M | ||
130 | { | ||
131 | union | ||
132 | { | ||
133 | struct | ||
134 | { | ||
135 | struct | ||
136 | { | ||
137 | uchar PcCommand; | ||
138 | union | ||
139 | { | ||
140 | uchar PcPhbNum; | ||
141 | uchar PcLinkNum; | ||
142 | uchar PcIDNum; | ||
143 | } U0; | ||
144 | } CmdHdr; | ||
145 | struct | ||
146 | { | ||
147 | ushort NumPackets; | ||
148 | ushort LoadBase; | ||
149 | ushort CodeSize; | ||
150 | } PcBootSequence; | ||
151 | } S1; | ||
152 | struct | ||
153 | { | ||
154 | ushort PcSequence; | ||
155 | uchar PcBootData[RTA_BOOT_DATA_SIZE]; | ||
156 | } S2; | ||
157 | struct | ||
158 | { | ||
159 | ushort __crud__; | ||
160 | uchar PcUniqNum[4]; /* this is really a uint. */ | ||
161 | uchar PcModuleTypes; /* what modules are fitted */ | ||
162 | } S3; | ||
163 | struct | ||
164 | { | ||
165 | ushort __cmd_hdr__; | ||
166 | uchar __undefined__; | ||
167 | uchar PcModemStatus; | ||
168 | uchar PcPortStatus; | ||
169 | uchar PcSubCommand; | ||
170 | ushort PcSubAddr; | ||
171 | uchar PcSubData[64]; | ||
172 | } S4; | ||
173 | struct | ||
174 | { | ||
175 | ushort __cmd_hdr__; | ||
176 | uchar PcCommandText[1]; | ||
177 | uchar __crud__[20]; | ||
178 | uchar PcIDNum2; /* Tacked on end */ | ||
179 | } S5; | ||
180 | struct | ||
181 | { | ||
182 | ushort __cmd_hdr__; | ||
183 | struct Top Topology[LINKS_PER_UNIT]; | ||
184 | } S6; | ||
185 | } U1; | ||
186 | }; | ||
187 | |||
188 | #define Command U1.S1.CmdHdr.PcCommand | ||
189 | #define PhbNum U1.S1.CmdHdr.U0.PcPhbNum | ||
190 | #define IDNum U1.S1.CmdHdr.U0.PcIDNum | ||
191 | #define IDNum2 U1.S5.PcIDNum2 | ||
192 | #define LinkNum U1.S1.CmdHdr.U0.PcLinkNum | ||
193 | #define Sequence U1.S2.PcSequence | ||
194 | #define BootData U1.S2.PcBootData | ||
195 | #define BootSequence U1.S1.PcBootSequence | ||
196 | #define UniqNum U1.S3.PcUniqNum | ||
197 | #define ModemStatus U1.S4.PcModemStatus | ||
198 | #define PortStatus U1.S4.PcPortStatus | ||
199 | #define SubCommand U1.S4.PcSubCommand | ||
200 | #define SubAddr U1.S4.PcSubAddr | ||
201 | #define SubData U1.S4.PcSubData | ||
202 | #define CommandText U1.S5.PcCommandText | ||
203 | #define RouteTopology U1.S6.Topology | ||
204 | #define ModuleTypes U1.S3.PcModuleTypes | ||
205 | |||
206 | #endif | ||
diff --git a/drivers/char/rio/control.h b/drivers/char/rio/control.h new file mode 100644 index 000000000000..1712f6261dd1 --- /dev/null +++ b/drivers/char/rio/control.h | |||
@@ -0,0 +1,62 @@ | |||
1 | |||
2 | |||
3 | /**************************************************************************** | ||
4 | ******* ******* | ||
5 | ******* C O N T R O L P A C K E T H E A D E R S | ||
6 | ******* ******* | ||
7 | **************************************************************************** | ||
8 | |||
9 | Author : Jon Brawn | ||
10 | Date : | ||
11 | |||
12 | * | ||
13 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | |||
29 | Version : 0.01 | ||
30 | |||
31 | |||
32 | Mods | ||
33 | ---------------------------------------------------------------------------- | ||
34 | Date By Description | ||
35 | ---------------------------------------------------------------------------- | ||
36 | |||
37 | ***************************************************************************/ | ||
38 | |||
39 | |||
40 | #ifndef _control_h | ||
41 | #define _control_h | ||
42 | |||
43 | #ifndef lint | ||
44 | /* static char *_rio_control_h_sccs = "@(#)control.h 1.4"; */ | ||
45 | #endif | ||
46 | |||
47 | #define CONTROL '^' | ||
48 | #define IFOAD ( CONTROL + 1 ) | ||
49 | #define IDENTIFY ( CONTROL + 2 ) | ||
50 | #define ZOMBIE ( CONTROL + 3 ) | ||
51 | #define UFOAD ( CONTROL + 4 ) | ||
52 | #define IWAIT ( CONTROL + 5 ) | ||
53 | |||
54 | #define IFOAD_MAGIC 0xF0AD /* of course */ | ||
55 | #define ZOMBIE_MAGIC (~0xDEAD) /* not dead -> zombie */ | ||
56 | #define UFOAD_MAGIC 0xD1E /* kill-your-neighbour */ | ||
57 | #define IWAIT_MAGIC 0xB1DE /* Bide your time */ | ||
58 | |||
59 | #endif | ||
60 | |||
61 | /*********** end of file ***********/ | ||
62 | |||
diff --git a/drivers/char/rio/daemon.h b/drivers/char/rio/daemon.h new file mode 100644 index 000000000000..62dba0e68b3e --- /dev/null +++ b/drivers/char/rio/daemon.h | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : daemon.h | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 11:34:09 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)daemon.h 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_daemon_h__ | ||
34 | #define __rio_daemon_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | #ifndef lint | ||
38 | static char *_daemon_h_sccs_ = "@(#)daemon.h 1.3"; | ||
39 | #endif | ||
40 | #endif | ||
41 | |||
42 | |||
43 | /* | ||
44 | ** structures used on /dev/rio | ||
45 | */ | ||
46 | |||
47 | struct Error | ||
48 | { | ||
49 | uint Error; | ||
50 | uint Entry; | ||
51 | uint Other; | ||
52 | }; | ||
53 | |||
54 | struct DownLoad | ||
55 | { | ||
56 | char *DataP; | ||
57 | uint Count; | ||
58 | uint ProductCode; | ||
59 | }; | ||
60 | |||
61 | /* | ||
62 | ** A few constants.... | ||
63 | */ | ||
64 | #ifndef MAX_VERSION_LEN | ||
65 | #define MAX_VERSION_LEN 256 | ||
66 | #endif | ||
67 | |||
68 | #ifndef MAX_XP_CTRL_LEN | ||
69 | #define MAX_XP_CTRL_LEN 16 /* ALSO IN PORT.H */ | ||
70 | #endif | ||
71 | |||
72 | struct PortSetup | ||
73 | { | ||
74 | uint From; /* Set/Clear XP & IXANY Control from this port.... */ | ||
75 | uint To; /* .... to this port */ | ||
76 | uint XpCps; /* at this speed */ | ||
77 | char XpOn[MAX_XP_CTRL_LEN]; /* this is the start string */ | ||
78 | char XpOff[MAX_XP_CTRL_LEN]; /* this is the stop string */ | ||
79 | uchar IxAny; /* enable/disable IXANY */ | ||
80 | uchar IxOn; /* enable/disable IXON */ | ||
81 | uchar Lock; /* lock port params */ | ||
82 | uchar Store; /* store params across closes */ | ||
83 | uchar Drain; /* close only when drained */ | ||
84 | }; | ||
85 | |||
86 | struct LpbReq | ||
87 | { | ||
88 | uint Host; | ||
89 | uint Link; | ||
90 | struct LPB *LpbP; | ||
91 | }; | ||
92 | |||
93 | struct RupReq | ||
94 | { | ||
95 | uint HostNum; | ||
96 | uint RupNum; | ||
97 | struct RUP *RupP; | ||
98 | }; | ||
99 | |||
100 | struct PortReq | ||
101 | { | ||
102 | uint SysPort; | ||
103 | struct Port *PortP; | ||
104 | }; | ||
105 | |||
106 | struct StreamInfo | ||
107 | { | ||
108 | uint SysPort; | ||
109 | #if 0 | ||
110 | queue_t RQueue; | ||
111 | queue_t WQueue; | ||
112 | #else | ||
113 | int RQueue; | ||
114 | int WQueue; | ||
115 | #endif | ||
116 | }; | ||
117 | |||
118 | struct HostReq | ||
119 | { | ||
120 | uint HostNum; | ||
121 | struct Host *HostP; | ||
122 | }; | ||
123 | |||
124 | struct HostDpRam | ||
125 | { | ||
126 | uint HostNum; | ||
127 | struct DpRam *DpRamP; | ||
128 | }; | ||
129 | |||
130 | struct DebugCtrl | ||
131 | { | ||
132 | uint SysPort; | ||
133 | uint Debug; | ||
134 | uint Wait; | ||
135 | }; | ||
136 | |||
137 | struct MapInfo | ||
138 | { | ||
139 | uint FirstPort; /* 8 ports, starting from this (tty) number */ | ||
140 | uint RtaUnique; /* reside on this RTA (unique number) */ | ||
141 | }; | ||
142 | |||
143 | struct MapIn | ||
144 | { | ||
145 | uint NumEntries; /* How many port sets are we mapping? */ | ||
146 | struct MapInfo *MapInfoP; /* Pointer to (user space) info */ | ||
147 | }; | ||
148 | |||
149 | struct SendPack | ||
150 | { | ||
151 | unsigned int PortNum; | ||
152 | unsigned char Len; | ||
153 | unsigned char Data[PKT_MAX_DATA_LEN]; | ||
154 | }; | ||
155 | |||
156 | struct SpecialRupCmd | ||
157 | { | ||
158 | struct PKT Packet; | ||
159 | unsigned short Host; | ||
160 | unsigned short RupNum; | ||
161 | }; | ||
162 | |||
163 | struct IdentifyRta | ||
164 | { | ||
165 | ulong RtaUnique; | ||
166 | uchar ID; | ||
167 | }; | ||
168 | |||
169 | struct KillNeighbour | ||
170 | { | ||
171 | ulong UniqueNum; | ||
172 | uchar Link; | ||
173 | }; | ||
174 | |||
175 | struct rioVersion { | ||
176 | char version[MAX_VERSION_LEN]; | ||
177 | char relid[MAX_VERSION_LEN]; | ||
178 | int buildLevel; | ||
179 | char buildDate[MAX_VERSION_LEN]; | ||
180 | }; | ||
181 | |||
182 | |||
183 | /* | ||
184 | ** RIOC commands are for the daemon type operations | ||
185 | ** | ||
186 | ** 09.12.1998 ARG - ESIL 0776 part fix | ||
187 | ** Definition for 'RIOC' also appears in rioioctl.h, so we'd better do a | ||
188 | ** #ifndef here first. | ||
189 | ** rioioctl.h also now has #define 'RIO_QUICK_CHECK' as this ioctl is now | ||
190 | ** allowed to be used by customers. | ||
191 | */ | ||
192 | #ifndef RIOC | ||
193 | #define RIOC ('R'<<8)|('i'<<16)|('o'<<24) | ||
194 | #endif | ||
195 | |||
196 | /* | ||
197 | ** Boot stuff | ||
198 | */ | ||
199 | #define RIO_GET_TABLE (RIOC | 100) | ||
200 | #define RIO_PUT_TABLE (RIOC | 101) | ||
201 | #define RIO_ASSIGN_RTA (RIOC | 102) | ||
202 | #define RIO_DELETE_RTA (RIOC | 103) | ||
203 | #define RIO_HOST_FOAD (RIOC | 104) | ||
204 | #define RIO_QUICK_CHECK (RIOC | 105) | ||
205 | #define RIO_SIGNALS_ON (RIOC | 106) | ||
206 | #define RIO_SIGNALS_OFF (RIOC | 107) | ||
207 | #define RIO_CHANGE_NAME (RIOC | 108) | ||
208 | #define RIO_DOWNLOAD (RIOC | 109) | ||
209 | #define RIO_GET_LOG (RIOC | 110) | ||
210 | #define RIO_SETUP_PORTS (RIOC | 111) | ||
211 | #define RIO_ALL_MODEM (RIOC | 112) | ||
212 | |||
213 | /* | ||
214 | ** card state, debug stuff | ||
215 | */ | ||
216 | #define RIO_NUM_HOSTS (RIOC | 120) | ||
217 | #define RIO_HOST_LPB (RIOC | 121) | ||
218 | #define RIO_HOST_RUP (RIOC | 122) | ||
219 | #define RIO_HOST_PORT (RIOC | 123) | ||
220 | #define RIO_PARMS (RIOC | 124) | ||
221 | #define RIO_HOST_REQ (RIOC | 125) | ||
222 | #define RIO_READ_CONFIG (RIOC | 126) | ||
223 | #define RIO_SET_CONFIG (RIOC | 127) | ||
224 | #define RIO_VERSID (RIOC | 128) | ||
225 | #define RIO_FLAGS (RIOC | 129) | ||
226 | #define RIO_SETDEBUG (RIOC | 130) | ||
227 | #define RIO_GETDEBUG (RIOC | 131) | ||
228 | #define RIO_READ_LEVELS (RIOC | 132) | ||
229 | #define RIO_SET_FAST_BUS (RIOC | 133) | ||
230 | #define RIO_SET_SLOW_BUS (RIOC | 134) | ||
231 | #define RIO_SET_BYTE_MODE (RIOC | 135) | ||
232 | #define RIO_SET_WORD_MODE (RIOC | 136) | ||
233 | #define RIO_STREAM_INFO (RIOC | 137) | ||
234 | #define RIO_START_POLLER (RIOC | 138) | ||
235 | #define RIO_STOP_POLLER (RIOC | 139) | ||
236 | #define RIO_LAST_ERROR (RIOC | 140) | ||
237 | #define RIO_TICK (RIOC | 141) | ||
238 | #define RIO_TOCK (RIOC | 241) /* I did this on purpose, you know. */ | ||
239 | #define RIO_SEND_PACKET (RIOC | 142) | ||
240 | #define RIO_SET_BUSY (RIOC | 143) | ||
241 | #define SPECIAL_RUP_CMD (RIOC | 144) | ||
242 | #define RIO_FOAD_RTA (RIOC | 145) | ||
243 | #define RIO_ZOMBIE_RTA (RIOC | 146) | ||
244 | #define RIO_IDENTIFY_RTA (RIOC | 147) | ||
245 | #define RIO_KILL_NEIGHBOUR (RIOC | 148) | ||
246 | #define RIO_DEBUG_MEM (RIOC | 149) | ||
247 | /* | ||
248 | ** 150 - 167 used..... See below | ||
249 | */ | ||
250 | #define RIO_GET_PORT_SETUP (RIOC | 168) | ||
251 | #define RIO_RESUME (RIOC | 169) | ||
252 | #define RIO_MESG (RIOC | 170) | ||
253 | #define RIO_NO_MESG (RIOC | 171) | ||
254 | #define RIO_WHAT_MESG (RIOC | 172) | ||
255 | #define RIO_HOST_DPRAM (RIOC | 173) | ||
256 | #define RIO_MAP_B50_TO_50 (RIOC | 174) | ||
257 | #define RIO_MAP_B50_TO_57600 (RIOC | 175) | ||
258 | #define RIO_MAP_B110_TO_110 (RIOC | 176) | ||
259 | #define RIO_MAP_B110_TO_115200 (RIOC | 177) | ||
260 | #define RIO_GET_PORT_PARAMS (RIOC | 178) | ||
261 | #define RIO_SET_PORT_PARAMS (RIOC | 179) | ||
262 | #define RIO_GET_PORT_TTY (RIOC | 180) | ||
263 | #define RIO_SET_PORT_TTY (RIOC | 181) | ||
264 | #define RIO_SYSLOG_ONLY (RIOC | 182) | ||
265 | #define RIO_SYSLOG_CONS (RIOC | 183) | ||
266 | #define RIO_CONS_ONLY (RIOC | 184) | ||
267 | #define RIO_BLOCK_OPENS (RIOC | 185) | ||
268 | |||
269 | /* | ||
270 | ** 02.03.1999 ARG - ESIL 0820 fix : | ||
271 | ** RIOBootMode is no longer use by the driver, so these ioctls | ||
272 | ** are now obsolete : | ||
273 | ** | ||
274 | #define RIO_GET_BOOT_MODE (RIOC | 186) | ||
275 | #define RIO_SET_BOOT_MODE (RIOC | 187) | ||
276 | ** | ||
277 | */ | ||
278 | |||
279 | #define RIO_MEM_DUMP (RIOC | 189) | ||
280 | #define RIO_READ_REGISTER (RIOC | 190) | ||
281 | #define RIO_GET_MODTYPE (RIOC | 191) | ||
282 | #define RIO_SET_TIMER (RIOC | 192) | ||
283 | #define RIO_READ_CHECK (RIOC | 196) | ||
284 | #define RIO_WAITING_FOR_RESTART (RIOC | 197) | ||
285 | #define RIO_BIND_RTA (RIOC | 198) | ||
286 | #define RIO_GET_BINDINGS (RIOC | 199) | ||
287 | #define RIO_PUT_BINDINGS (RIOC | 200) | ||
288 | |||
289 | #define RIO_MAKE_DEV (RIOC | 201) | ||
290 | #define RIO_MINOR (RIOC | 202) | ||
291 | |||
292 | #define RIO_IDENTIFY_DRIVER (RIOC | 203) | ||
293 | #define RIO_DISPLAY_HOST_CFG (RIOC | 204) | ||
294 | |||
295 | |||
296 | /* | ||
297 | ** MAKE_DEV / MINOR stuff | ||
298 | */ | ||
299 | #define RIO_DEV_DIRECT 0x0000 | ||
300 | #define RIO_DEV_MODEM 0x0200 | ||
301 | #define RIO_DEV_XPRINT 0x0400 | ||
302 | #define RIO_DEV_MASK 0x0600 | ||
303 | |||
304 | /* | ||
305 | ** port management, xprint stuff | ||
306 | */ | ||
307 | #define rIOCN(N) (RIOC|(N)) | ||
308 | #define rIOCR(N,T) (RIOC|(N)) | ||
309 | #define rIOCW(N,T) (RIOC|(N)) | ||
310 | |||
311 | #define RIO_GET_XP_ON rIOCR(150,char[16]) /* start xprint string */ | ||
312 | #define RIO_SET_XP_ON rIOCW(151,char[16]) | ||
313 | #define RIO_GET_XP_OFF rIOCR(152,char[16]) /* finish xprint string */ | ||
314 | #define RIO_SET_XP_OFF rIOCW(153,char[16]) | ||
315 | #define RIO_GET_XP_CPS rIOCR(154,int) /* xprint CPS */ | ||
316 | #define RIO_SET_XP_CPS rIOCW(155,int) | ||
317 | #define RIO_GET_IXANY rIOCR(156,int) /* ixany allowed? */ | ||
318 | #define RIO_SET_IXANY rIOCW(157,int) | ||
319 | #define RIO_SET_IXANY_ON rIOCN(158) /* allow ixany */ | ||
320 | #define RIO_SET_IXANY_OFF rIOCN(159) /* disallow ixany */ | ||
321 | #define RIO_GET_MODEM rIOCR(160,int) /* port is modem/direct line? */ | ||
322 | #define RIO_SET_MODEM rIOCW(161,int) | ||
323 | #define RIO_SET_MODEM_ON rIOCN(162) /* port is a modem */ | ||
324 | #define RIO_SET_MODEM_OFF rIOCN(163) /* port is direct */ | ||
325 | #define RIO_GET_IXON rIOCR(164,int) /* ixon allowed? */ | ||
326 | #define RIO_SET_IXON rIOCW(165,int) | ||
327 | #define RIO_SET_IXON_ON rIOCN(166) /* allow ixon */ | ||
328 | #define RIO_SET_IXON_OFF rIOCN(167) /* disallow ixon */ | ||
329 | |||
330 | #define RIO_GET_SIVIEW ((('s')<<8) | 106) /* backwards compatible with SI */ | ||
331 | |||
332 | #define RIO_IOCTL_UNKNOWN -2 | ||
333 | |||
334 | #endif | ||
diff --git a/drivers/char/rio/data.h b/drivers/char/rio/data.h new file mode 100644 index 000000000000..dabc2d1fa40f --- /dev/null +++ b/drivers/char/rio/data.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : data.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:09 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)data.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_datadex__ | ||
34 | #define __rio_datadex__ | ||
35 | |||
36 | #ifndef lint | ||
37 | static char *_data_h_sccs_ = "@(#)data.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | #endif | ||
diff --git a/drivers/char/rio/debug.h b/drivers/char/rio/debug.h new file mode 100644 index 000000000000..b6e0d0935552 --- /dev/null +++ b/drivers/char/rio/debug.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | ** File: debug.h | ||
3 | ** | ||
4 | ** Author: David Dix | ||
5 | ** | ||
6 | ** Created: 12th March 1993 | ||
7 | ** | ||
8 | ** Last modified: 93/04/27 | ||
9 | ** | ||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef _debug_h_ | ||
29 | #define _debug_h_ | ||
30 | |||
31 | |||
32 | #if defined(DCIRRUS) | ||
33 | #define DBPACKET(pkt, opt, str, chn) debug_packet((pkt), (opt), (str), (chn)) | ||
34 | #else | ||
35 | #define DBPACKET(pkt, opt, str, c) | ||
36 | #endif /* DCIRRUS */ | ||
37 | |||
38 | |||
39 | #endif /* _debug_h_ */ | ||
diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h new file mode 100644 index 000000000000..2e7309e27622 --- /dev/null +++ b/drivers/char/rio/defaults.h | |||
@@ -0,0 +1,59 @@ | |||
1 | |||
2 | /**************************************************************************** | ||
3 | ******* ******* | ||
4 | ******* D E F A U L T S | ||
5 | ******* ******* | ||
6 | **************************************************************************** | ||
7 | |||
8 | Author : Ian Nandhra | ||
9 | Date : | ||
10 | |||
11 | * | ||
12 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | |||
28 | Version : 0.01 | ||
29 | |||
30 | |||
31 | Mods | ||
32 | ---------------------------------------------------------------------------- | ||
33 | Date By Description | ||
34 | ---------------------------------------------------------------------------- | ||
35 | |||
36 | ***************************************************************************/ | ||
37 | |||
38 | #ifndef lint | ||
39 | #ifdef SCCS | ||
40 | static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1" ; | ||
41 | #endif | ||
42 | #endif | ||
43 | |||
44 | |||
45 | #define MILLISECOND (int) (1000/64) /* 15.625 low ticks */ | ||
46 | #define SECOND (int) 15625 /* Low priority ticks */ | ||
47 | |||
48 | #ifdef RTA | ||
49 | #define RX_LIMIT (ushort) 3 | ||
50 | #endif | ||
51 | #ifdef HOST | ||
52 | #define RX_LIMIT (ushort) 1 | ||
53 | #endif | ||
54 | |||
55 | #define LINK_TIMEOUT (int) (POLL_PERIOD / 2) | ||
56 | |||
57 | |||
58 | /*********** end of file ***********/ | ||
59 | |||
diff --git a/drivers/char/rio/eisa.h b/drivers/char/rio/eisa.h new file mode 100644 index 000000000000..59371b0528b0 --- /dev/null +++ b/drivers/char/rio/eisa.h | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | |||
7 | * | ||
8 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | ** | ||
24 | ** Module : eisa.h | ||
25 | ** SID : 1.2 | ||
26 | ** Last Modified : 11/6/98 11:34:10 | ||
27 | ** Retrieved : 11/6/98 11:34:21 | ||
28 | ** | ||
29 | ** ident @(#)eisa.h 1.2 | ||
30 | ** | ||
31 | ** ----------------------------------------------------------------------------- | ||
32 | */ | ||
33 | |||
34 | #ifndef __rio_eisa_h__ | ||
35 | #define __rio_eisa_h__ | ||
36 | |||
37 | #ifdef SCCS_LABELS | ||
38 | #ifndef lint | ||
39 | static char *_eisa_h_sccs_ = "@(#)eisa.h 1.2"; | ||
40 | #endif | ||
41 | #endif | ||
42 | |||
43 | /* | ||
44 | ** things to do with the EISA bus | ||
45 | */ | ||
46 | |||
47 | #define RIO_EISA_STRING_ADDRESS 0xfffd9 /* where EISA is stored */ | ||
48 | |||
49 | #define RIO_MAX_EISA_SLOTS 16 /* how many EISA slots? */ | ||
50 | |||
51 | #define RIO_EISA_IDENT 0x984D /* Specialix */ | ||
52 | #define RIO_EISA_PRODUCT_CODE 0x14 /* Code 14 */ | ||
53 | #define RIO_EISA_ENABLE_BIT 0x01 /* To enable card */ | ||
54 | |||
55 | #define EISA_MEMORY_BASE_LO 0xC00 /* A16-A23 */ | ||
56 | #define EISA_MEMORY_BASE_HI 0xC01 /* A24-A31 */ | ||
57 | #define EISA_INTERRUPT_VEC 0xC02 /* see below */ | ||
58 | #define EISA_CONTROL_PORT 0xC02 /* see below */ | ||
59 | #define EISA_INTERRUPT_RESET 0xC03 /* read to clear IRQ */ | ||
60 | |||
61 | #define EISA_PRODUCT_IDENT_LO 0xC80 /* where RIO_EISA_IDENT is */ | ||
62 | #define EISA_PRODUCT_IDENT_HI 0xC81 | ||
63 | #define EISA_PRODUCT_NUMBER 0xC82 /* where PROD_CODE is */ | ||
64 | #define EISA_REVISION_NUMBER 0xC83 /* revision (1dp) */ | ||
65 | #define EISA_ENABLE 0xC84 /* set LSB to enable card */ | ||
66 | #define EISA_UNIQUE_NUM_0 0xC88 /* vomit */ | ||
67 | #define EISA_UNIQUE_NUM_1 0xC8A | ||
68 | #define EISA_UNIQUE_NUM_2 0xC90 /* bit strangely arranged */ | ||
69 | #define EISA_UNIQUE_NUM_3 0xC92 | ||
70 | #define EISA_MANUF_YEAR 0xC98 /* when */ | ||
71 | #define EISA_MANUF_WEEK 0xC9A /* more when */ | ||
72 | |||
73 | #define EISA_TP_BOOT_FROM_RAM 0x01 | ||
74 | #define EISA_TP_BOOT_FROM_LINK 0x00 | ||
75 | #define EISA_TP_FAST_LINKS 0x02 | ||
76 | #define EISA_TP_SLOW_LINKS 0x00 | ||
77 | #define EISA_TP_BUS_ENABLE 0x04 | ||
78 | #define EISA_TP_BUS_DISABLE 0x00 | ||
79 | #define EISA_TP_RUN 0x08 | ||
80 | #define EISA_TP_RESET 0x00 | ||
81 | #define EISA_POLLED 0x00 | ||
82 | #define EISA_IRQ_3 0x30 | ||
83 | #define EISA_IRQ_4 0x40 | ||
84 | #define EISA_IRQ_5 0x50 | ||
85 | #define EISA_IRQ_6 0x60 | ||
86 | #define EISA_IRQ_7 0x70 | ||
87 | #define EISA_IRQ_9 0x90 | ||
88 | #define EISA_IRQ_10 0xA0 | ||
89 | #define EISA_IRQ_11 0xB0 | ||
90 | #define EISA_IRQ_12 0xC0 | ||
91 | #define EISA_IRQ_14 0xE0 | ||
92 | #define EISA_IRQ_15 0xF0 | ||
93 | |||
94 | #define EISA_INTERRUPT_MASK 0xF0 | ||
95 | #define EISA_CONTROL_MASK 0x0F | ||
96 | |||
97 | #define RIO_EISA_DEFAULT_MODE EISA_TP_SLOW_LINKS | ||
98 | |||
99 | #define RIOEisaToIvec(X) (uchar )((uchar)((X) & EISA_INTERRUPT_MASK)>>4) | ||
100 | |||
101 | #define INBZ(z,x) inb(((z)<<12) | (x)) | ||
102 | #define OUTBZ(z,x,y) outb((((z)<<12) | (x)), y) | ||
103 | |||
104 | #endif /* __rio_eisa_h__ */ | ||
diff --git a/drivers/char/rio/enable.h b/drivers/char/rio/enable.h new file mode 100644 index 000000000000..8e9a419e15b0 --- /dev/null +++ b/drivers/char/rio/enable.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* E N A B L E H E A D E R S | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef lint | ||
38 | #ifdef SCCS | ||
39 | static char *_rio_enable_h_sccs = "@(#)enable.h 1.1" ; | ||
40 | #endif | ||
41 | #endif | ||
42 | |||
43 | |||
44 | #define ENABLE_LTT TRUE | ||
45 | #define ENABLE_LRT TRUE | ||
46 | |||
47 | |||
48 | /*********** end of file ***********/ | ||
49 | |||
50 | |||
diff --git a/drivers/char/rio/error.h b/drivers/char/rio/error.h new file mode 100644 index 000000000000..229438e355f2 --- /dev/null +++ b/drivers/char/rio/error.h | |||
@@ -0,0 +1,85 @@ | |||
1 | |||
2 | /**************************************************************************** | ||
3 | ******* ******* | ||
4 | ******* E R R O R H E A D E R F I L E | ||
5 | ******* ******* | ||
6 | **************************************************************************** | ||
7 | |||
8 | Author : Ian Nandhra | ||
9 | Date : | ||
10 | |||
11 | * | ||
12 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | |||
28 | Version : 0.01 | ||
29 | |||
30 | |||
31 | Mods | ||
32 | ---------------------------------------------------------------------------- | ||
33 | Date By Description | ||
34 | ---------------------------------------------------------------------------- | ||
35 | |||
36 | ***************************************************************************/ | ||
37 | |||
38 | #ifndef lint | ||
39 | /* static char *_rio_error_h_sccs = "@(#)error.h 1.3"; */ | ||
40 | #endif | ||
41 | |||
42 | #define E_NO_ERROR ((ushort) 0) | ||
43 | #define E_PROCESS_NOT_INIT ((ushort) 1) | ||
44 | #define E_LINK_TIMEOUT ((ushort) 2) | ||
45 | #define E_NO_ROUTE ((ushort) 3) | ||
46 | #define E_CONFUSED ((ushort) 4) | ||
47 | #define E_HOME ((ushort) 5) | ||
48 | #define E_CSUM_FAIL ((ushort) 6) | ||
49 | #define E_DISCONNECTED ((ushort) 7) | ||
50 | #define E_BAD_RUP ((ushort) 8) | ||
51 | #define E_NO_VIRGIN ((ushort) 9) | ||
52 | #define E_BOOT_RUP_BUSY ((ushort) 10) | ||
53 | |||
54 | |||
55 | |||
56 | /************************************************* | ||
57 | * Parsed to mem_halt() | ||
58 | ************************************************/ | ||
59 | #define E_CHANALLOC ((ushort) 0x80) | ||
60 | #define E_POLL_ALLOC ((ushort) 0x81) | ||
61 | #define E_LTTWAKE ((ushort) 0x82) | ||
62 | #define E_LTT_ALLOC ((ushort) 0x83) | ||
63 | #define E_LRT_ALLOC ((ushort) 0x84) | ||
64 | #define E_CIRRUS ((ushort) 0x85) | ||
65 | #define E_MONITOR ((ushort) 0x86) | ||
66 | #define E_PHB_ALLOC ((ushort) 0x87) | ||
67 | #define E_ARRAY_ALLOC ((ushort) 0x88) | ||
68 | #define E_QBUF_ALLOC ((ushort) 0x89) | ||
69 | #define E_PKT_ALLOC ((ushort) 0x8a) | ||
70 | #define E_GET_TX_Q_BUF ((ushort) 0x8b) | ||
71 | #define E_GET_RX_Q_BUF ((ushort) 0x8c) | ||
72 | #define E_MEM_OUT ((ushort) 0x8d) | ||
73 | #define E_MMU_INIT ((ushort) 0x8e) | ||
74 | #define E_LTT_INIT ((ushort) 0x8f) | ||
75 | #define E_LRT_INIT ((ushort) 0x90) | ||
76 | #define E_LINK_RUN ((ushort) 0x91) | ||
77 | #define E_MONITOR_ALLOC ((ushort) 0x92) | ||
78 | #define E_MONITOR_INIT ((ushort) 0x93) | ||
79 | #define E_POLL_INIT ((ushort) 0x94) | ||
80 | |||
81 | |||
82 | /*********** end of file ***********/ | ||
83 | |||
84 | |||
85 | |||
diff --git a/drivers/char/rio/errors.h b/drivers/char/rio/errors.h new file mode 100644 index 000000000000..f920b9f3e2bd --- /dev/null +++ b/drivers/char/rio/errors.h | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : errors.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:10 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)errors.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_errors_h__ | ||
34 | #define __rio_errors_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | #ifndef lint | ||
38 | static char *_errors_h_sccs_ = "@(#)errors.h 1.2"; | ||
39 | #endif | ||
40 | #endif | ||
41 | |||
42 | /* | ||
43 | ** error codes | ||
44 | */ | ||
45 | |||
46 | #define NOTHING_WRONG_AT_ALL 0 | ||
47 | #define BAD_CHARACTER_IN_NAME 1 | ||
48 | #define TABLE_ENTRY_ISNT_PROPERLY_NULL 2 | ||
49 | #define UNKNOWN_HOST_NUMBER 3 | ||
50 | #define ZERO_RTA_ID 4 | ||
51 | #define BAD_RTA_ID 5 | ||
52 | #define DUPLICATED_RTA_ID 6 | ||
53 | #define DUPLICATE_UNIQUE_NUMBER 7 | ||
54 | #define BAD_TTY_NUMBER 8 | ||
55 | #define TTY_NUMBER_IN_USE 9 | ||
56 | #define NAME_USED_TWICE 10 | ||
57 | #define HOST_ID_NOT_ZERO 11 | ||
58 | #define BOOT_IN_PROGRESS 12 | ||
59 | #define COPYIN_FAILED 13 | ||
60 | #define HOST_FILE_TOO_LARGE 14 | ||
61 | #define COPYOUT_FAILED 15 | ||
62 | #define NOT_SUPER_USER 16 | ||
63 | #define RIO_ALREADY_POLLING 17 | ||
64 | |||
65 | #define ID_NUMBER_OUT_OF_RANGE 18 | ||
66 | #define PORT_NUMBER_OUT_OF_RANGE 19 | ||
67 | #define HOST_NUMBER_OUT_OF_RANGE 20 | ||
68 | #define RUP_NUMBER_OUT_OF_RANGE 21 | ||
69 | #define TTY_NUMBER_OUT_OF_RANGE 22 | ||
70 | #define LINK_NUMBER_OUT_OF_RANGE 23 | ||
71 | |||
72 | #define HOST_NOT_RUNNING 24 | ||
73 | #define IOCTL_COMMAND_UNKNOWN 25 | ||
74 | #define RIO_SYSTEM_HALTED 26 | ||
75 | #define WAIT_FOR_DRAIN_BROKEN 27 | ||
76 | #define PORT_NOT_MAPPED_INTO_SYSTEM 28 | ||
77 | #define EXCLUSIVE_USE_SET 29 | ||
78 | #define WAIT_FOR_NOT_CLOSING_BROKEN 30 | ||
79 | #define WAIT_FOR_PORT_TO_OPEN_BROKEN 31 | ||
80 | #define WAIT_FOR_CARRIER_BROKEN 32 | ||
81 | #define WAIT_FOR_NOT_IN_USE_BROKEN 33 | ||
82 | #define WAIT_FOR_CAN_ADD_COMMAND_BROKEN 34 | ||
83 | #define WAIT_FOR_ADD_COMMAND_BROKEN 35 | ||
84 | #define WAIT_FOR_NOT_PARAM_BROKEN 36 | ||
85 | #define WAIT_FOR_RETRY_BROKEN 37 | ||
86 | #define HOST_HAS_ALREADY_BEEN_BOOTED 38 | ||
87 | #define UNIT_IS_IN_USE 39 | ||
88 | #define COULDNT_FIND_ENTRY 40 | ||
89 | #define RTA_UNIQUE_NUMBER_ZERO 41 | ||
90 | #define CLOSE_COMMAND_FAILED 42 | ||
91 | #define WAIT_FOR_CLOSE_BROKEN 43 | ||
92 | #define CPS_VALUE_OUT_OF_RANGE 44 | ||
93 | #define ID_ALREADY_IN_USE 45 | ||
94 | #define SIGNALS_ALREADY_SET 46 | ||
95 | #define NOT_RECEIVING_PROCESS 47 | ||
96 | #define RTA_NUMBER_WRONG 48 | ||
97 | #define NO_SUCH_PRODUCT 49 | ||
98 | #define HOST_SYSPORT_BAD 50 | ||
99 | #define ID_NOT_TENTATIVE 51 | ||
100 | #define XPRINT_CPS_OUT_OF_RANGE 52 | ||
101 | #define NOT_ENOUGH_CORE_FOR_PCI_COPY 53 | ||
102 | |||
103 | |||
104 | #endif /* __rio_errors_h__ */ | ||
diff --git a/drivers/char/rio/formpkt.h b/drivers/char/rio/formpkt.h new file mode 100644 index 000000000000..a8b65ae0de90 --- /dev/null +++ b/drivers/char/rio/formpkt.h | |||
@@ -0,0 +1,154 @@ | |||
1 | |||
2 | |||
3 | /**************************************************************************** | ||
4 | ******* ******* | ||
5 | ******* F O R M P A C K E T H E A D E R F I L E | ||
6 | ******* ******* | ||
7 | **************************************************************************** | ||
8 | |||
9 | Author : Ian Nandhra | ||
10 | Date : | ||
11 | |||
12 | * | ||
13 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | |||
29 | Version : 0.01 | ||
30 | |||
31 | |||
32 | Mods | ||
33 | ---------------------------------------------------------------------------- | ||
34 | Date By Description | ||
35 | ---------------------------------------------------------------------------- | ||
36 | |||
37 | ***************************************************************************/ | ||
38 | |||
39 | #ifndef _formpkt_h | ||
40 | #define _formpkt_h 1 | ||
41 | |||
42 | #ifndef lint | ||
43 | #ifdef SCCS | ||
44 | static char *_rio_formpkt_h_sccs = "@(#)formpkt.h 1.1" ; | ||
45 | #endif | ||
46 | #endif | ||
47 | |||
48 | typedef struct FORM_BOOT_PKT_1 FORM_BOOT_PKT_1 ; | ||
49 | struct FORM_BOOT_PKT_1 { | ||
50 | ushort pkt_number ; | ||
51 | ushort pkt_total ; | ||
52 | ushort boot_top ; | ||
53 | } ; | ||
54 | |||
55 | typedef struct FORM_BOOT_PKT_2 FORM_BOOT_PKT_2 ; | ||
56 | struct FORM_BOOT_PKT_2 { | ||
57 | ushort pkt_number ; | ||
58 | char boot_data[10] ; | ||
59 | } ; | ||
60 | |||
61 | |||
62 | typedef struct FORM_ATTACH_RTA FORM_ATTACH_RTA ; | ||
63 | struct FORM_ATTACH_RTA { | ||
64 | char cmd_code ; | ||
65 | char booter_serial[4] ; | ||
66 | char booter_link ; | ||
67 | char bootee_serial[4] ; | ||
68 | char bootee_link ; | ||
69 | } ; | ||
70 | |||
71 | |||
72 | typedef struct FORM_BOOT_ID FORM_BOOT_ID ; | ||
73 | struct FORM_BOOT_ID { | ||
74 | char cmd_code ; | ||
75 | char bootee_serial[4] ; | ||
76 | char bootee_prod_id ; | ||
77 | char bootee_link ; | ||
78 | } ; | ||
79 | |||
80 | |||
81 | |||
82 | typedef struct FORM_ROUTE_1 FORM_ROUTE_1 ; | ||
83 | struct FORM_ROUTE_1 { | ||
84 | char cmd_code ; | ||
85 | char pkt_number ; | ||
86 | char total_in_sequence ; | ||
87 | char unit_id ; | ||
88 | char host_unit_id ; | ||
89 | } ; | ||
90 | |||
91 | typedef struct FORM_ROUTE_2 FORM_ROUTE_2 ; | ||
92 | struct FORM_ROUTE_2 { | ||
93 | char cmd_code ; | ||
94 | char pkt_number ; | ||
95 | char total_in_sequence ; | ||
96 | char route_data[9] ; | ||
97 | } ; | ||
98 | |||
99 | typedef struct FORM_ROUTE_REQ FORM_ROUTE_REQ ; | ||
100 | struct FORM_ROUTE_REQ { | ||
101 | char cmd_code ; | ||
102 | char pkt_number ; | ||
103 | char total_in_sequence ; | ||
104 | char route_data[10] ; | ||
105 | } ; | ||
106 | |||
107 | |||
108 | typedef struct FORM_ERROR FORM_ERROR ; | ||
109 | struct FORM_ERROR { | ||
110 | char cmd_code ; | ||
111 | char error_code ; | ||
112 | |||
113 | } ; | ||
114 | |||
115 | typedef struct FORM_STATUS FORM_STATUS ; | ||
116 | struct FORM_STATUS { | ||
117 | char cmd_code ; | ||
118 | char status_code ; | ||
119 | char last_packet_valid ; | ||
120 | char tx_buffer ; | ||
121 | char rx_buffer ; | ||
122 | char port_status ; | ||
123 | char phb_status ; | ||
124 | } ; | ||
125 | |||
126 | |||
127 | typedef struct FORM_LINK_STATUS FORM_LINK_STATUS ; | ||
128 | struct FORM_LINK_STATUS { | ||
129 | char cmd_code ; | ||
130 | char status_code ; | ||
131 | char link_number ; | ||
132 | ushort rx_errors ; | ||
133 | ushort tx_errors ; | ||
134 | ushort csum_errors ; | ||
135 | ushort disconnects ; | ||
136 | } ; | ||
137 | |||
138 | |||
139 | |||
140 | typedef struct FORM_PARTITION FORM_PARTITION ; | ||
141 | struct FORM_PARTITION { | ||
142 | char cmd_code ; | ||
143 | char status_code ; | ||
144 | char port_number ; | ||
145 | char tx_max ; | ||
146 | char rx_max ; | ||
147 | char rx_limit ; | ||
148 | } ; | ||
149 | |||
150 | |||
151 | #endif | ||
152 | |||
153 | /*********** end of file ***********/ | ||
154 | |||
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h new file mode 100644 index 000000000000..e8f3860f4726 --- /dev/null +++ b/drivers/char/rio/func.h | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : func.h | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 11:34:10 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)func.h 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __func_h_def | ||
34 | #define __func_h_def | ||
35 | |||
36 | #include <linux/kdev_t.h> | ||
37 | |||
38 | #ifdef SCCS_LABELS | ||
39 | #ifndef lint | ||
40 | static char *_func_h_sccs_ = "@(#)func.h 1.3"; | ||
41 | #endif | ||
42 | #endif | ||
43 | |||
44 | /* rioboot.c */ | ||
45 | int RIOBootCodeRTA(struct rio_info *, struct DownLoad *); | ||
46 | int RIOBootCodeHOST(struct rio_info *, register struct DownLoad *); | ||
47 | int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *); | ||
48 | void msec_timeout(struct Host *); | ||
49 | int RIOBootRup(struct rio_info *, uint, struct Host *, struct PKT *); | ||
50 | int RIOBootOk(struct rio_info *,struct Host *, ulong); | ||
51 | int RIORtaBound(struct rio_info *, uint); | ||
52 | void FillSlot(int, int, uint, struct Host *); | ||
53 | |||
54 | /* riocmd.c */ | ||
55 | int RIOFoadRta(struct Host *, struct Map *); | ||
56 | int RIOZombieRta(struct Host *, struct Map *); | ||
57 | int RIOCommandRta(struct rio_info *, uint, int (* func)( struct Host *, | ||
58 | struct Map *)); | ||
59 | int RIOIdentifyRta(struct rio_info *, caddr_t); | ||
60 | int RIOKillNeighbour(struct rio_info *, caddr_t); | ||
61 | int RIOSuspendBootRta(struct Host *, int, int); | ||
62 | int RIOFoadWakeup(struct rio_info *); | ||
63 | struct CmdBlk * RIOGetCmdBlk(void); | ||
64 | void RIOFreeCmdBlk(struct CmdBlk *); | ||
65 | int RIOQueueCmdBlk(struct Host *, uint, struct CmdBlk *); | ||
66 | void RIOPollHostCommands(struct rio_info *, struct Host *); | ||
67 | int RIOWFlushMark(int, struct CmdBlk *); | ||
68 | int RIORFlushEnable(int, struct CmdBlk *); | ||
69 | int RIOUnUse(int, struct CmdBlk *); | ||
70 | void ShowPacket(uint, struct PKT *); | ||
71 | |||
72 | /* rioctrl.c */ | ||
73 | int copyin(int, caddr_t, int); | ||
74 | int riocontrol(struct rio_info *, dev_t,int,caddr_t,int); | ||
75 | int RIOPreemptiveCmd(struct rio_info *,struct Port *,uchar); | ||
76 | |||
77 | /* rioinit.c */ | ||
78 | void rioinit(struct rio_info *, struct RioHostInfo *); | ||
79 | void RIOInitHosts(struct rio_info *, struct RioHostInfo *); | ||
80 | void RIOISAinit(struct rio_info *,int); | ||
81 | int RIODoAT(struct rio_info *, int, int); | ||
82 | caddr_t RIOCheckForATCard(int); | ||
83 | int RIOAssignAT(struct rio_info *, int, caddr_t, int); | ||
84 | int RIOBoardTest(paddr_t, caddr_t, uchar, int); | ||
85 | void RIOAllocDataStructs(struct rio_info *); | ||
86 | void RIOSetupDataStructs(struct rio_info *); | ||
87 | int RIODefaultName(struct rio_info *, struct Host *, uint); | ||
88 | struct rioVersion * RIOVersid(void); | ||
89 | int RIOMapin(paddr_t, int, caddr_t *); | ||
90 | void RIOMapout(paddr_t, long, caddr_t); | ||
91 | void RIOHostReset(uint, volatile struct DpRam *, uint); | ||
92 | |||
93 | /* riointr.c */ | ||
94 | void RIOTxEnable(char *); | ||
95 | void RIOServiceHost(struct rio_info *, struct Host *, int); | ||
96 | int riotproc(struct rio_info *, register struct ttystatics *, int, int); | ||
97 | |||
98 | /* rioparam.c */ | ||
99 | int RIOParam(struct Port *, int, int, int); | ||
100 | int RIODelay(struct Port *PortP, int); | ||
101 | int RIODelay_ni(struct Port *PortP, int); | ||
102 | void ms_timeout(struct Port *); | ||
103 | int can_add_transmit(struct PKT **, struct Port *); | ||
104 | void add_transmit(struct Port *); | ||
105 | void put_free_end(struct Host *, struct PKT *); | ||
106 | int can_remove_receive(struct PKT **, struct Port *); | ||
107 | void remove_receive(struct Port *); | ||
108 | |||
109 | /* rioroute.c */ | ||
110 | int RIORouteRup(struct rio_info *, uint, struct Host *, struct PKT *); | ||
111 | void RIOFixPhbs(struct rio_info *, struct Host *, uint); | ||
112 | uint GetUnitType(uint); | ||
113 | int RIOSetChange(struct rio_info *); | ||
114 | int RIOFindFreeID(struct rio_info *, struct Host *, uint *, uint *); | ||
115 | |||
116 | |||
117 | /* riotty.c */ | ||
118 | |||
119 | int riotopen(struct tty_struct * tty, struct file * filp); | ||
120 | int riotclose(void *ptr); | ||
121 | int riotioctl(struct rio_info *, struct tty_struct *, register int, register caddr_t); | ||
122 | void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg); | ||
123 | |||
124 | /* riotable.c */ | ||
125 | int RIONewTable(struct rio_info *); | ||
126 | int RIOApel(struct rio_info *); | ||
127 | int RIODeleteRta(struct rio_info *, struct Map *); | ||
128 | int RIOAssignRta(struct rio_info *, struct Map *); | ||
129 | int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *); | ||
130 | int RIOChangeName(struct rio_info *, struct Map*); | ||
131 | |||
132 | #if 0 | ||
133 | /* riodrvr.c */ | ||
134 | struct rio_info * rio_install(struct RioHostInfo *); | ||
135 | int rio_uninstall(register struct rio_info *); | ||
136 | int rio_open(struct rio_info *, int, struct file *); | ||
137 | int rio_close(struct rio_info *, struct file *); | ||
138 | int rio_read(struct rio_info *, struct file *, char *, int); | ||
139 | int rio_write(struct rio_info *, struct file * f, char *, int); | ||
140 | int rio_ioctl(struct rio_info *, struct file *, int, char *); | ||
141 | int rio_select(struct rio_info *, struct file * f, int, struct sel *); | ||
142 | int rio_intr(char *); | ||
143 | int rio_isr_thread(char *); | ||
144 | struct rio_info * rio_info_store( int cmd, struct rio_info * p); | ||
145 | #endif | ||
146 | |||
147 | extern int rio_pcicopy(char *src, char *dst, int n); | ||
148 | extern int rio_minor (struct tty_struct *tty); | ||
149 | extern int rio_ismodem (struct tty_struct *tty); | ||
150 | extern void rio_udelay (int usecs); | ||
151 | |||
152 | extern void rio_start_card_running (struct Host * HostP); | ||
153 | |||
154 | #endif /* __func_h_def */ | ||
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h new file mode 100644 index 000000000000..4c65963870a4 --- /dev/null +++ b/drivers/char/rio/host.h | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : host.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:10 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)host.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_host_h__ | ||
34 | #define __rio_host_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | #ifndef lint | ||
38 | static char *_host_h_sccs_ = "@(#)host.h 1.2"; | ||
39 | #endif | ||
40 | #endif | ||
41 | |||
42 | /* | ||
43 | ** the host structure - one per host card in the system. | ||
44 | */ | ||
45 | |||
46 | #define MAX_EXTRA_UNITS 64 | ||
47 | |||
48 | /* | ||
49 | ** Host data structure. This is used for the software equiv. of | ||
50 | ** the host. | ||
51 | */ | ||
52 | struct Host | ||
53 | { | ||
54 | uchar Type; /* RIO_EISA, RIO_MCA, ... */ | ||
55 | uchar Ivec; /* POLLED or ivec number */ | ||
56 | uchar Mode; /* Control stuff */ | ||
57 | uchar Slot; /* Slot */ | ||
58 | volatile caddr_t Caddr; /* KV address of DPRAM */ | ||
59 | volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */ | ||
60 | paddr_t PaddrP; /* Phys. address of DPRAM */ | ||
61 | char Name[MAX_NAME_LEN]; /* The name of the host */ | ||
62 | uint UniqueNum; /* host unique number */ | ||
63 | spinlock_t HostLock; /* Lock structure for MPX */ | ||
64 | /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */ | ||
65 | /*struct lockb HostLock; *//* Lock structure for MPX */ | ||
66 | uint WorkToBeDone; /* set to true each interrupt */ | ||
67 | uint InIntr; /* Being serviced? */ | ||
68 | uint IntSrvDone;/* host's interrupt has been serviced */ | ||
69 | int (*Copy)( caddr_t, caddr_t, int ); /* copy func */ | ||
70 | struct timer_list timer; | ||
71 | /* | ||
72 | ** I M P O R T A N T ! | ||
73 | ** | ||
74 | ** The rest of this data structure is cleared to zero after | ||
75 | ** a RIO_HOST_FOAD command. | ||
76 | */ | ||
77 | |||
78 | ulong Flags; /* Whats going down */ | ||
79 | #define RC_WAITING 0 | ||
80 | #define RC_STARTUP 1 | ||
81 | #define RC_RUNNING 2 | ||
82 | #define RC_STUFFED 3 | ||
83 | #define RC_SOMETHING 4 | ||
84 | #define RC_SOMETHING_NEW 5 | ||
85 | #define RC_SOMETHING_ELSE 6 | ||
86 | #define RC_READY 7 | ||
87 | #define RUN_STATE 7 | ||
88 | /* | ||
89 | ** Boot mode applies to the way in which hosts in this system will | ||
90 | ** boot RTAs | ||
91 | */ | ||
92 | #define RC_BOOT_ALL 0x8 /* Boot all RTAs attached */ | ||
93 | #define RC_BOOT_OWN 0x10 /* Only boot RTAs bound to this system */ | ||
94 | #define RC_BOOT_NONE 0x20 /* Don't boot any RTAs (slave mode) */ | ||
95 | |||
96 | struct Top Topology[LINKS_PER_UNIT]; /* one per link */ | ||
97 | struct Map Mapping[MAX_RUP]; /* Mappings for host */ | ||
98 | struct PHB *PhbP; /* Pointer to the PHB array */ | ||
99 | ushort *PhbNumP; /* Ptr to Number of PHB's */ | ||
100 | struct LPB *LinkStrP ; /* Link Structure Array */ | ||
101 | struct RUP *RupP; /* Sixteen real rups here */ | ||
102 | struct PARM_MAP *ParmMapP; /* points to the parmmap */ | ||
103 | uint ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */ | ||
104 | uint NumExtraBooted; /* how many of the above */ | ||
105 | /* | ||
106 | ** Twenty logical rups. | ||
107 | ** The first sixteen are the real Rup entries (above), the last four | ||
108 | ** are the link RUPs. | ||
109 | */ | ||
110 | struct UnixRup UnixRups[MAX_RUP+LINKS_PER_UNIT]; | ||
111 | int timeout_id; /* For calling 100 ms delays */ | ||
112 | int timeout_sem;/* For calling 100 ms delays */ | ||
113 | long locks; /* long req'd for set_bit --RR */ | ||
114 | char ____end_marker____; | ||
115 | }; | ||
116 | #define Control CardP->DpControl | ||
117 | #define SetInt CardP->DpSetInt | ||
118 | #define ResetTpu CardP->DpResetTpu | ||
119 | #define ResetInt CardP->DpResetInt | ||
120 | #define Signature CardP->DpSignature | ||
121 | #define Sram1 CardP->DpSram1 | ||
122 | #define Sram2 CardP->DpSram2 | ||
123 | #define Sram3 CardP->DpSram3 | ||
124 | #define Scratch CardP->DpScratch | ||
125 | #define __ParmMapR CardP->DpParmMapR | ||
126 | #define SLX CardP->DpSlx | ||
127 | #define Revision CardP->DpRevision | ||
128 | #define Unique CardP->DpUnique | ||
129 | #define Year CardP->DpYear | ||
130 | #define Week CardP->DpWeek | ||
131 | |||
132 | #define RIO_DUMBPARM 0x0860 /* what not to expect */ | ||
133 | |||
134 | #endif | ||
diff --git a/drivers/char/rio/hosthw.h b/drivers/char/rio/hosthw.h new file mode 100644 index 000000000000..f6f31ece6e32 --- /dev/null +++ b/drivers/char/rio/hosthw.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* H O S T H A R D W A R E | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra / Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | |||
38 | #ifndef lint | ||
39 | #ifdef SCCS_LABELS | ||
40 | static char *_rio_hosthw_h_sccs = "@(#)hosthw.h 1.2" ; | ||
41 | #endif | ||
42 | #endif | ||
43 | |||
44 | #define SET_OTHER_INTERRUPT ( (volatile u_short *) 0x7c80 ) | ||
45 | #define SET_EISA_INTERRUPT ( (volatile u_short *) 0x7ef0 ) | ||
46 | |||
47 | #define EISA_HOST 0x30 | ||
48 | #define AT_HOST 0xa0 | ||
49 | #define MCA_HOST 0xb0 | ||
50 | #define PCI_HOST 0xd0 | ||
51 | |||
52 | #define PRODUCT_MASK 0xf0 | ||
53 | |||
54 | |||
55 | /*********** end of file ***********/ | ||
56 | |||
57 | |||
diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h new file mode 100644 index 000000000000..972250348f4a --- /dev/null +++ b/drivers/char/rio/link.h | |||
@@ -0,0 +1,188 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* L I N K | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra / Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _link_h | ||
38 | #define _link_h 1 | ||
39 | |||
40 | #ifndef lint | ||
41 | #ifdef SCCS_LABELS | ||
42 | /* static char *_rio_link_h_sccs = "@(#)link.h 1.15"; */ | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | |||
47 | |||
48 | /************************************************* | ||
49 | * Define the Link Status stuff | ||
50 | ************************************************/ | ||
51 | #define LRT_ACTIVE ((ushort) 0x01) | ||
52 | #define LRT_SPARE1 ((ushort) 0x02) | ||
53 | #define INTRO_RCVD ((ushort) 0x04) | ||
54 | #define FORCED_DISCONNECT ((ushort) 0x08) | ||
55 | #define LRT_SPARE2 ((ushort) 0x80) | ||
56 | |||
57 | #define TOP_OF_RTA_RAM ((ushort) 0x7000) | ||
58 | #define HOST_SERIAL_POINTER (unsigned char **) (TOP_OF_RTA_RAM - 2 * sizeof (ushort)) | ||
59 | |||
60 | /* Flags for ltt_status */ | ||
61 | #define WAITING_ACK (ushort) 0x0001 | ||
62 | #define DATA_SENT (ushort) 0x0002 | ||
63 | #define WAITING_RUP (ushort) 0x0004 | ||
64 | #define WAITING_RETRY (ushort) 0x0008 | ||
65 | #define WAITING_TOPOLOGY (ushort) 0x0010 | ||
66 | #define SEND_SYNC (ushort) 0x0020 | ||
67 | #define FOAD_THIS_LINK (ushort) 0x0040 | ||
68 | #define REQUEST_SYNC (ushort) 0x0080 | ||
69 | #define REMOTE_DYING (ushort) 0x0100 | ||
70 | #define DIE_NOW (ushort) 0x0200 | ||
71 | |||
72 | /* Boot request stuff */ | ||
73 | #define BOOT_REQUEST ((ushort) 0) /* Request for a boot */ | ||
74 | #define BOOT_ABORT ((ushort) 1) /* Abort a boot */ | ||
75 | #define BOOT_SEQUENCE ((ushort) 2) /* Packet with the number of packets | ||
76 | and load address */ | ||
77 | #define BOOT_COMPLETED ((ushort) 3) /* Boot completed */ | ||
78 | |||
79 | /* States that a link can be in */ | ||
80 | #define LINK_DISCONNECTED ((ushort) 0) /* Disconnected */ | ||
81 | #define LINK_BOOT1 ((ushort) 1) /* Trying to send 1st stage boot */ | ||
82 | #define LINK_BOOT2 ((ushort) 2) /* Trying to send 2nd stage boot */ | ||
83 | #define LINK_BOOT2WAIT ((ushort) 3) /* Waiting for selftest results */ | ||
84 | #define LINK_BOOT3 ((ushort) 4) /* Trying to send 3rd stage boots */ | ||
85 | #define LINK_SYNC ((ushort) 5) /* Syncing */ | ||
86 | |||
87 | #define LINK_INTRO ((ushort) 10) /* Introductory packet */ | ||
88 | #define LINK_SUPPLYID ((ushort) 11) /* Trying to supply an ID */ | ||
89 | #define LINK_TOPOLOGY ((ushort) 12) /* Send a topology update */ | ||
90 | #define LINK_REQUESTID ((ushort) 13) /* Waiting for an ID */ | ||
91 | #define LINK_CONNECTED ((ushort) 14) /* Connected */ | ||
92 | |||
93 | #define LINK_INTERCONNECT ((ushort) 20) /* Subnets interconnected */ | ||
94 | |||
95 | #define LINK_SPARE ((ushort) 40) | ||
96 | |||
97 | /* | ||
98 | ** Set the default timeout for link communications. | ||
99 | */ | ||
100 | #define LINKTIMEOUT (400 * MILLISECOND) | ||
101 | |||
102 | /* | ||
103 | ** LED stuff | ||
104 | */ | ||
105 | #if defined(RTA) | ||
106 | #define LED_OFF ((ushort) 0) /* LED off */ | ||
107 | #define LED_RED ((ushort) 1) /* LED Red */ | ||
108 | #define LED_GREEN ((ushort) 2) /* LED Green */ | ||
109 | #define LED_ORANGE ((ushort) 4) /* LED Orange */ | ||
110 | #define LED_1TO8_OPEN ((ushort) 1) /* Port 1->8 LED on */ | ||
111 | #define LED_9TO16_OPEN ((ushort) 2) /* Port 9->16 LED on */ | ||
112 | #define LED_SET_COLOUR(colour) (link->led = (colour)) | ||
113 | #define LED_OR_COLOUR(colour) (link->led |= (colour)) | ||
114 | #define LED_TIMEOUT(time) (link->led_timeout = RioTimePlus(RioTime(),(time))) | ||
115 | #else | ||
116 | #define LED_SET_COLOUR(colour) | ||
117 | #define LED_OR_COLOUR(colour) | ||
118 | #define LED_TIMEOUT(time) | ||
119 | #endif /* RTA */ | ||
120 | |||
121 | struct LPB { | ||
122 | WORD link_number ; /* Link Number */ | ||
123 | Channel_ptr in_ch ; /* Link In Channel */ | ||
124 | Channel_ptr out_ch ; /* Link Out Channel */ | ||
125 | #ifdef RTA | ||
126 | uchar stat_led ; /* Port open leds */ | ||
127 | uchar led ; /* True, light led! */ | ||
128 | #endif | ||
129 | BYTE attached_serial[4]; /* Attached serial number */ | ||
130 | BYTE attached_host_serial[4]; | ||
131 | /* Serial number of Host who | ||
132 | booted the other end */ | ||
133 | WORD descheduled ; /* Currently Descheduled */ | ||
134 | WORD state; /* Current state */ | ||
135 | WORD send_poll ; /* Send a Poll Packet */ | ||
136 | Process_ptr ltt_p ; /* Process Descriptor */ | ||
137 | Process_ptr lrt_p ; /* Process Descriptor */ | ||
138 | WORD lrt_status ; /* Current lrt status */ | ||
139 | WORD ltt_status ; /* Current ltt status */ | ||
140 | WORD timeout ; /* Timeout value */ | ||
141 | WORD topology; /* Topology bits */ | ||
142 | WORD mon_ltt ; | ||
143 | WORD mon_lrt ; | ||
144 | WORD WaitNoBoot ; /* Secs to hold off booting */ | ||
145 | PKT_ptr add_packet_list; /* Add packets to here */ | ||
146 | PKT_ptr remove_packet_list; /* Send packets from here */ | ||
147 | #ifdef RTA | ||
148 | #ifdef DCIRRUS | ||
149 | #define QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1) | ||
150 | #else | ||
151 | #define QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1) | ||
152 | #endif | ||
153 | PKT_ptr_ptr rd_add ; /* Add a new Packet here */ | ||
154 | Q_BUF_ptr rd_add_qb; /* Pointer to the add Q buf */ | ||
155 | PKT_ptr_ptr rd_add_st_qbb ; /* Pointer to start of the Q's buf */ | ||
156 | PKT_ptr_ptr rd_add_end_qbb ; /* Pointer to the end of the Q's buf */ | ||
157 | PKT_ptr_ptr rd_remove ; /* Remove a Packet here */ | ||
158 | Q_BUF_ptr rd_remove_qb ; /* Pointer to the remove Q buf */ | ||
159 | PKT_ptr_ptr rd_remove_st_qbb ; /* Pointer to the start of the Q buf */ | ||
160 | PKT_ptr_ptr rd_remove_end_qbb ; /* Pointer to the end of the Q buf */ | ||
161 | ushort pkts_in_q ; /* Packets in queue */ | ||
162 | #endif | ||
163 | |||
164 | Channel_ptr lrt_fail_chan ; /* Lrt's failure channel */ | ||
165 | Channel_ptr ltt_fail_chan ; /* Ltt's failure channel */ | ||
166 | |||
167 | #if defined (HOST) || defined (INKERNEL) | ||
168 | /* RUP structure for HOST to driver communications */ | ||
169 | struct RUP rup ; | ||
170 | #endif | ||
171 | struct RUP link_rup; /* RUP for the link (POLL, | ||
172 | topology etc.) */ | ||
173 | WORD attached_link ; /* Number of attached link */ | ||
174 | WORD csum_errors ; /* csum errors */ | ||
175 | WORD num_disconnects ; /* number of disconnects */ | ||
176 | WORD num_sync_rcvd ; /* # sync's received */ | ||
177 | WORD num_sync_rqst ; /* # sync requests */ | ||
178 | WORD num_tx ; /* Num pkts sent */ | ||
179 | WORD num_rx ; /* Num pkts received */ | ||
180 | WORD module_attached; /* Module tpyes of attached */ | ||
181 | WORD led_timeout; /* LED timeout */ | ||
182 | WORD first_port; /* First port to service */ | ||
183 | WORD last_port; /* Last port to service */ | ||
184 | } ; | ||
185 | |||
186 | #endif | ||
187 | |||
188 | /*********** end of file ***********/ | ||
diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h new file mode 100644 index 000000000000..d53843abe02d --- /dev/null +++ b/drivers/char/rio/linux_compat.h | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * (C) 2000 R.E.Wolff@BitWizard.nl | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/interrupt.h> | ||
20 | |||
21 | |||
22 | #define disable(oldspl) save_flags (oldspl) | ||
23 | #define restore(oldspl) restore_flags (oldspl) | ||
24 | |||
25 | #define sysbrk(x) kmalloc ((x),in_interrupt()? GFP_ATOMIC : GFP_KERNEL) | ||
26 | #define sysfree(p,size) kfree ((p)) | ||
27 | |||
28 | #define WBYTE(p,v) writeb(v, &p) | ||
29 | #define RBYTE(p) readb (&p) | ||
30 | #define WWORD(p,v) writew(v, &p) | ||
31 | #define RWORD(p) readw(&p) | ||
32 | #define WINDW(p,v) writew(v, p) | ||
33 | #define RINDW(p) readw(p) | ||
34 | |||
35 | #define DEBUG_ALL | ||
36 | |||
37 | #define cprintf printk | ||
38 | |||
39 | #ifdef __KERNEL__ | ||
40 | #define INKERNEL | ||
41 | #endif | ||
42 | |||
43 | struct ttystatics { | ||
44 | struct termios tm; | ||
45 | }; | ||
46 | |||
47 | #define bzero(d, n) memset((d), 0, (n)) | ||
48 | #define bcopy(src, dest, n) memcpy ((dest), (src), (n)) | ||
49 | |||
50 | #define SEM_SIGIGNORE 0x1234 | ||
51 | |||
52 | #ifdef DEBUG_SEM | ||
53 | #define swait(a,b) printk ("waiting: " __FILE__ " line %d\n", __LINE__) | ||
54 | #define ssignal(sem) printk ("signalling: " __FILE__ " line %d\n", __LINE__) | ||
55 | |||
56 | #define sreset(sem) printk ("sreset: " __FILE__ "\n") | ||
57 | #define sem_init(sem,v) printk ("sreset: " __FILE__ "\n") | ||
58 | #endif | ||
59 | |||
60 | |||
61 | #define getpid() (current->pid) | ||
62 | |||
63 | #define QSIZE SERIAL_XMIT_SIZE | ||
64 | |||
65 | #define pseterr(errno) return (- errno) | ||
66 | |||
67 | #define V_CBAUD CBAUD | ||
68 | |||
69 | /* For one reason or another rioboot.c uses delay instead of RIODelay. */ | ||
70 | #define delay(x,y) RIODelay(NULL, y) | ||
71 | |||
72 | extern int rio_debug; | ||
73 | |||
74 | #define RIO_DEBUG_INIT 0x000001 | ||
75 | #define RIO_DEBUG_BOOT 0x000002 | ||
76 | #define RIO_DEBUG_CMD 0x000004 | ||
77 | #define RIO_DEBUG_CTRL 0x000008 | ||
78 | #define RIO_DEBUG_INTR 0x000010 | ||
79 | #define RIO_DEBUG_PARAM 0x000020 | ||
80 | #define RIO_DEBUG_ROUTE 0x000040 | ||
81 | #define RIO_DEBUG_TABLE 0x000080 | ||
82 | #define RIO_DEBUG_TTY 0x000100 | ||
83 | #define RIO_DEBUG_FLOW 0x000200 | ||
84 | #define RIO_DEBUG_MODEMSIGNALS 0x000400 | ||
85 | #define RIO_DEBUG_PROBE 0x000800 | ||
86 | #define RIO_DEBUG_CLEANUP 0x001000 | ||
87 | #define RIO_DEBUG_IFLOW 0x002000 | ||
88 | #define RIO_DEBUG_PFE 0x004000 | ||
89 | #define RIO_DEBUG_REC 0x008000 | ||
90 | #define RIO_DEBUG_SPINLOCK 0x010000 | ||
91 | #define RIO_DEBUG_DELAY 0x020000 | ||
92 | #define RIO_DEBUG_MOD_COUNT 0x040000 | ||
93 | |||
94 | /* Copied over from riowinif.h . This is ugly. The winif file declares | ||
95 | also much other stuff which is incompatible with the headers from | ||
96 | the older driver. The older driver includes "brates.h" which shadows | ||
97 | the definitions from Linux, and is incompatible... */ | ||
98 | |||
99 | /* RxBaud and TxBaud definitions... */ | ||
100 | #define RIO_B0 0x00 /* RTS / DTR signals dropped */ | ||
101 | #define RIO_B50 0x01 /* 50 baud */ | ||
102 | #define RIO_B75 0x02 /* 75 baud */ | ||
103 | #define RIO_B110 0x03 /* 110 baud */ | ||
104 | #define RIO_B134 0x04 /* 134.5 baud */ | ||
105 | #define RIO_B150 0x05 /* 150 baud */ | ||
106 | #define RIO_B200 0x06 /* 200 baud */ | ||
107 | #define RIO_B300 0x07 /* 300 baud */ | ||
108 | #define RIO_B600 0x08 /* 600 baud */ | ||
109 | #define RIO_B1200 0x09 /* 1200 baud */ | ||
110 | #define RIO_B1800 0x0A /* 1800 baud */ | ||
111 | #define RIO_B2400 0x0B /* 2400 baud */ | ||
112 | #define RIO_B4800 0x0C /* 4800 baud */ | ||
113 | #define RIO_B9600 0x0D /* 9600 baud */ | ||
114 | #define RIO_B19200 0x0E /* 19200 baud */ | ||
115 | #define RIO_B38400 0x0F /* 38400 baud */ | ||
116 | #define RIO_B56000 0x10 /* 56000 baud */ | ||
117 | #define RIO_B57600 0x11 /* 57600 baud */ | ||
118 | #define RIO_B64000 0x12 /* 64000 baud */ | ||
119 | #define RIO_B115200 0x13 /* 115200 baud */ | ||
120 | #define RIO_B2000 0x14 /* 2000 baud */ | ||
121 | |||
122 | |||
diff --git a/drivers/char/rio/list.h b/drivers/char/rio/list.h new file mode 100644 index 000000000000..a4f7f1f56255 --- /dev/null +++ b/drivers/char/rio/list.h | |||
@@ -0,0 +1,196 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* L I S T ******* | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Jeremy Rolls. | ||
8 | Date : 04-Nov-1990 | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | ***************************************************************************/ | ||
35 | |||
36 | #ifndef _list_h | ||
37 | #define _list_h 1 | ||
38 | |||
39 | #ifdef SCCS_LABELS | ||
40 | #ifndef lint | ||
41 | static char *_rio_list_h_sccs = "@(#)list.h 1.9" ; | ||
42 | #endif | ||
43 | #endif | ||
44 | |||
45 | #define PKT_IN_USE 0x1 | ||
46 | |||
47 | #ifdef INKERNEL | ||
48 | |||
49 | #define ZERO_PTR (ushort) 0x8000 | ||
50 | #define CaD PortP->Caddr | ||
51 | |||
52 | /* | ||
53 | ** We can add another packet to a transmit queue if the packet pointer pointed | ||
54 | ** to by the TxAdd pointer has PKT_IN_USE clear in its address. | ||
55 | */ | ||
56 | |||
57 | #ifndef linux | ||
58 | #if defined( MIPS ) && !defined( MIPSEISA ) | ||
59 | /* May the shoes of the Devil dance on your grave for creating this */ | ||
60 | #define can_add_transmit(PacketP,PortP) \ | ||
61 | (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \ | ||
62 | & (PKT_IN_USE<<2))) | ||
63 | |||
64 | #elif defined(MIPSEISA) || defined(nx6000) || \ | ||
65 | defined(drs6000) || defined(UWsparc) | ||
66 | |||
67 | #define can_add_transmit(PacketP,PortP) \ | ||
68 | (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,RINDW(PortP->TxAdd))) \ | ||
69 | & PKT_IN_USE)) | ||
70 | |||
71 | #else | ||
72 | #define can_add_transmit(PacketP,PortP) \ | ||
73 | (!((uint)(PacketP = (struct PKT *)RIO_PTR(CaD,*PortP->TxAdd)) \ | ||
74 | & PKT_IN_USE)) | ||
75 | #endif | ||
76 | |||
77 | /* | ||
78 | ** To add a packet to the queue, you set the PKT_IN_USE bit in the address, | ||
79 | ** and then move the TxAdd pointer along one position to point to the next | ||
80 | ** packet pointer. You must wrap the pointer from the end back to the start. | ||
81 | */ | ||
82 | #if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc) | ||
83 | # define add_transmit(PortP) \ | ||
84 | WINDW(PortP->TxAdd,RINDW(PortP->TxAdd) | PKT_IN_USE);\ | ||
85 | if (PortP->TxAdd == PortP->TxEnd)\ | ||
86 | PortP->TxAdd = PortP->TxStart;\ | ||
87 | else\ | ||
88 | PortP->TxAdd++;\ | ||
89 | WWORD(PortP->PhbP->tx_add , RIO_OFF(CaD,PortP->TxAdd)); | ||
90 | #elif defined(AIX) | ||
91 | # define add_transmit(PortP) \ | ||
92 | {\ | ||
93 | register ushort *TxAddP = (ushort *)RIO_PTR(Cad,PortP->TxAddO);\ | ||
94 | WINDW( TxAddP, RINDW( TxAddP ) | PKT_IN_USE );\ | ||
95 | if (PortP->TxAddO == PortP->TxEndO )\ | ||
96 | PortP->TxAddO = PortP->TxStartO;\ | ||
97 | else\ | ||
98 | PortP->TxAddO += sizeof(ushort);\ | ||
99 | WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->tx_add , PortP->TxAddO );\ | ||
100 | } | ||
101 | #else | ||
102 | # define add_transmit(PortP) \ | ||
103 | *PortP->TxAdd |= PKT_IN_USE;\ | ||
104 | if (PortP->TxAdd == PortP->TxEnd)\ | ||
105 | PortP->TxAdd = PortP->TxStart;\ | ||
106 | else\ | ||
107 | PortP->TxAdd++;\ | ||
108 | PortP->PhbP->tx_add = RIO_OFF(CaD,PortP->TxAdd); | ||
109 | #endif | ||
110 | |||
111 | /* | ||
112 | ** can_remove_receive( PacketP, PortP ) returns non-zero if PKT_IN_USE is set | ||
113 | ** for the next packet on the queue. It will also set PacketP to point to the | ||
114 | ** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear, | ||
115 | ** then can_remove_receive() returns 0. | ||
116 | */ | ||
117 | #if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc) | ||
118 | # define can_remove_receive(PacketP,PortP) \ | ||
119 | ((RINDW(PortP->RxRemove) & PKT_IN_USE) ? \ | ||
120 | (PacketP=(struct PKT *)RIO_PTR(CaD,(RINDW(PortP->RxRemove) & ~PKT_IN_USE))):0) | ||
121 | #elif defined(AIX) | ||
122 | # define can_remove_receive(PacketP,PortP) \ | ||
123 | ((RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & PKT_IN_USE) ? \ | ||
124 | (PacketP=(struct PKT *)RIO_PTR(Cad,RINDW((ushort *)RIO_PTR(Cad,PortP->RxRemoveO)) & ~PKT_IN_USE)):0) | ||
125 | #else | ||
126 | # define can_remove_receive(PacketP,PortP) \ | ||
127 | ((*PortP->RxRemove & PKT_IN_USE) ? \ | ||
128 | (PacketP=(struct PKT *)RIO_PTR(CaD,(*PortP->RxRemove & ~PKT_IN_USE))):0) | ||
129 | #endif | ||
130 | |||
131 | |||
132 | /* | ||
133 | ** Will God see it within his heart to forgive us for this thing that | ||
134 | ** we have created? To remove a packet from the receive queue you clear | ||
135 | ** its PKT_IN_USE bit, and then bump the pointers. Once the pointers | ||
136 | ** get to the end, they must be wrapped back to the start. | ||
137 | */ | ||
138 | #if defined(MIPS) || defined(nx6000) || defined(drs6000) || defined(UWsparc) | ||
139 | # define remove_receive(PortP) \ | ||
140 | WINDW(PortP->RxRemove, (RINDW(PortP->RxRemove) & ~PKT_IN_USE));\ | ||
141 | if (PortP->RxRemove == PortP->RxEnd)\ | ||
142 | PortP->RxRemove = PortP->RxStart;\ | ||
143 | else\ | ||
144 | PortP->RxRemove++;\ | ||
145 | WWORD(PortP->PhbP->rx_remove , RIO_OFF(CaD,PortP->RxRemove)); | ||
146 | #elif defined(AIX) | ||
147 | # define remove_receive(PortP) \ | ||
148 | {\ | ||
149 | register ushort *RxRemoveP = (ushort *)RIO_PTR(Cad,PortP->RxRemoveO);\ | ||
150 | WINDW( RxRemoveP, RINDW( RxRemoveP ) & ~PKT_IN_USE );\ | ||
151 | if (PortP->RxRemoveO == PortP->RxEndO)\ | ||
152 | PortP->RxRemoveO = PortP->RxStartO;\ | ||
153 | else\ | ||
154 | PortP->RxRemoveO += sizeof(ushort);\ | ||
155 | WWORD(((PHB *)RIO_PTR(Cad,PortP->PhbO))->rx_remove, PortP->RxRemoveO );\ | ||
156 | } | ||
157 | #else | ||
158 | # define remove_receive(PortP) \ | ||
159 | *PortP->RxRemove &= ~PKT_IN_USE;\ | ||
160 | if (PortP->RxRemove == PortP->RxEnd)\ | ||
161 | PortP->RxRemove = PortP->RxStart;\ | ||
162 | else\ | ||
163 | PortP->RxRemove++;\ | ||
164 | PortP->PhbP->rx_remove = RIO_OFF(CaD,PortP->RxRemove); | ||
165 | #endif | ||
166 | #endif | ||
167 | |||
168 | |||
169 | #else /* !IN_KERNEL */ | ||
170 | |||
171 | #define ZERO_PTR NULL | ||
172 | |||
173 | |||
174 | #ifdef HOST | ||
175 | /* #define can_remove_transmit(pkt,phb) ((((char*)pkt = (*(char**)(phb->tx_remove))-1) || 1)) && (*phb->u3.s2.tx_remove_ptr & PKT_IN_USE)) */ | ||
176 | #define remove_transmit(phb) *phb->u3.s2.tx_remove_ptr &= ~(ushort)PKT_IN_USE;\ | ||
177 | if (phb->tx_remove == phb->tx_end)\ | ||
178 | phb->tx_remove = phb->tx_start;\ | ||
179 | else\ | ||
180 | phb->tx_remove++; | ||
181 | #define can_add_receive(phb) !(*phb->u4.s2.rx_add_ptr & PKT_IN_USE) | ||
182 | #define add_receive(pkt,phb) *phb->rx_add = pkt;\ | ||
183 | *phb->u4.s2.rx_add_ptr |= PKT_IN_USE;\ | ||
184 | if (phb->rx_add == phb->rx_end)\ | ||
185 | phb->rx_add = phb->rx_start;\ | ||
186 | else\ | ||
187 | phb->rx_add++; | ||
188 | #endif | ||
189 | #endif | ||
190 | |||
191 | #ifdef RTA | ||
192 | #define splx(oldspl) if ((oldspl) == 0) spl0() | ||
193 | #endif | ||
194 | |||
195 | #endif /* ifndef _list.h */ | ||
196 | /*********** end of file ***********/ | ||
diff --git a/drivers/char/rio/lrt.h b/drivers/char/rio/lrt.h new file mode 100644 index 000000000000..bbac8fa18fee --- /dev/null +++ b/drivers/char/rio/lrt.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* L R T | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra / Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef lint | ||
38 | #ifdef SCCS_LABELS | ||
39 | static char *_rio_lrt_h_sccs = "@(#)lrt.h 1.1" ; | ||
40 | #endif | ||
41 | #endif | ||
42 | |||
43 | |||
44 | #ifdef DCIRRUS | ||
45 | #define LRT_STACK (unsigned short) 600 | ||
46 | #else | ||
47 | #define LRT_STACK (ushort) 200 | ||
48 | #endif | ||
49 | |||
50 | |||
51 | |||
52 | /*********** end of file ***********/ | ||
53 | |||
54 | |||
55 | |||
diff --git a/drivers/char/rio/ltt.h b/drivers/char/rio/ltt.h new file mode 100644 index 000000000000..f27dcecf03ca --- /dev/null +++ b/drivers/char/rio/ltt.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* L T T | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra / Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef lint | ||
38 | #ifdef SCCS_LABELS | ||
39 | static char *_rio_ltt_h_sccs = "@(#)ltt.h 1.1" ; | ||
40 | #endif | ||
41 | #endif | ||
42 | |||
43 | #ifdef DCIRRUS | ||
44 | #define LTT_STACK (unsigned short) 600 | ||
45 | #else | ||
46 | #define LTT_STACK (ushort) 200 | ||
47 | #endif | ||
48 | |||
49 | |||
50 | |||
51 | |||
52 | /*********** end of file ***********/ | ||
53 | |||
54 | |||
55 | |||
diff --git a/drivers/char/rio/lttwake.h b/drivers/char/rio/lttwake.h new file mode 100644 index 000000000000..fe17d0ee4933 --- /dev/null +++ b/drivers/char/rio/lttwake.h | |||
@@ -0,0 +1,53 @@ | |||
1 | |||
2 | |||
3 | |||
4 | /**************************************************************************** | ||
5 | ******* ******* | ||
6 | ******* L T T W A K E U P H E A D E R | ||
7 | ******* ******* | ||
8 | **************************************************************************** | ||
9 | |||
10 | Author : Ian Nandhra | ||
11 | Date : | ||
12 | |||
13 | * | ||
14 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | |||
30 | Version : 0.01 | ||
31 | |||
32 | |||
33 | Mods | ||
34 | ---------------------------------------------------------------------------- | ||
35 | Date By Description | ||
36 | ---------------------------------------------------------------------------- | ||
37 | |||
38 | ***************************************************************************/ | ||
39 | |||
40 | #ifndef lint | ||
41 | #ifdef SCCS_LABELS | ||
42 | static char *_rio_lttwake_h_sccs = "@(#)lttwake.h 1.1" ; | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | #define LTT_WAKEUP_STACK 500 | ||
47 | #define LTT_WAKEUP_INTERVAL (int) (500 * MILLISECOND) | ||
48 | |||
49 | |||
50 | /*********** end of file ***********/ | ||
51 | |||
52 | |||
53 | |||
diff --git a/drivers/char/rio/map.h b/drivers/char/rio/map.h new file mode 100644 index 000000000000..400645a1ff28 --- /dev/null +++ b/drivers/char/rio/map.h | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : map.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:11 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)map.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_map_h__ | ||
34 | #define __rio_map_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_map_h_sccs_ = "@(#)map.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** mapping structure passed to and from the config.rio program to | ||
42 | ** determine the current topology of the world | ||
43 | */ | ||
44 | |||
45 | #define MAX_MAP_ENTRY 17 | ||
46 | #define TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS) | ||
47 | #define MAX_NAME_LEN 32 | ||
48 | |||
49 | struct Map | ||
50 | { | ||
51 | uint HostUniqueNum; /* Supporting hosts unique number */ | ||
52 | uint RtaUniqueNum; /* Unique number */ | ||
53 | /* | ||
54 | ** The next two IDs must be swapped on big-endian architectures | ||
55 | ** when using a v2.04 /etc/rio/config with a v3.00 driver (when | ||
56 | ** upgrading for example). | ||
57 | */ | ||
58 | ushort ID; /* ID used in the subnet */ | ||
59 | ushort ID2; /* ID of 2nd block of 8 for 16 port */ | ||
60 | ulong Flags; /* Booted, ID Given, Disconnected */ | ||
61 | ulong SysPort; /* First tty mapped to this port */ | ||
62 | struct Top Topology[LINKS_PER_UNIT]; /* ID connected to each link */ | ||
63 | char Name[MAX_NAME_LEN]; /* Cute name by which RTA is known */ | ||
64 | }; | ||
65 | |||
66 | /* | ||
67 | ** Flag values: | ||
68 | */ | ||
69 | #define RTA_BOOTED 0x00000001 | ||
70 | #define RTA_NEWBOOT 0x00000010 | ||
71 | #define MSG_DONE 0x00000020 | ||
72 | #define RTA_INTERCONNECT 0x00000040 | ||
73 | #define RTA16_SECOND_SLOT 0x00000080 | ||
74 | #define BEEN_HERE 0x00000100 | ||
75 | #define SLOT_TENTATIVE 0x40000000 | ||
76 | #define SLOT_IN_USE 0x80000000 | ||
77 | |||
78 | /* | ||
79 | ** HostUniqueNum is the unique number from the host card that this RTA | ||
80 | ** is to be connected to. | ||
81 | ** RtaUniqueNum is the unique number of the RTA concerned. It will be ZERO | ||
82 | ** if the slot in the table is unused. If it is the same as the HostUniqueNum | ||
83 | ** then this slot represents a host card. | ||
84 | ** Flags contains current boot/route state info | ||
85 | ** SysPort is a value in the range 0-504, being the number of the first tty | ||
86 | ** on this RTA. Each RTA supports 8 ports. The SysPort value must be modulo 8. | ||
87 | ** SysPort 0-127 correspond to /dev/ttyr001 to /dev/ttyr128, with minor | ||
88 | ** numbers 0-127. SysPort 128-255 correspond to /dev/ttyr129 to /dev/ttyr256, | ||
89 | ** again with minor numbers 0-127, and so on for SysPorts 256-383 and 384-511 | ||
90 | ** ID will be in the range 0-16 for a `known' RTA. ID will be 0xFFFF for an | ||
91 | ** unused slot/unknown ID etc. | ||
92 | ** The Topology array contains the ID of the unit connected to each of the | ||
93 | ** four links on this unit. The entry will be 0xFFFF if NOTHING is connected | ||
94 | ** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link. | ||
95 | ** The Name field is a null-terminated string, upto 31 characters, containing | ||
96 | ** the 'cute' name that the sysadmin/users know the RTA by. It is permissible | ||
97 | ** for this string to contain any character in the range \040 to \176 inclusive. | ||
98 | ** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The | ||
99 | ** special character '%' IS allowable, and needs no special action. | ||
100 | ** | ||
101 | */ | ||
102 | |||
103 | #endif | ||
diff --git a/drivers/char/rio/mca.h b/drivers/char/rio/mca.h new file mode 100644 index 000000000000..08a327e473af --- /dev/null +++ b/drivers/char/rio/mca.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : mca.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:11 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)mca.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_mca_h__ | ||
34 | #define __rio_mca_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_mca_h_sccs_ = "@(#)mca.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** Micro Channel stuff | ||
42 | */ | ||
43 | |||
44 | #define McaMaxSlots 8 | ||
45 | #define McaSlotSelect 0x96 | ||
46 | #define McaSlotEnable 0x08 | ||
47 | #define McaIdLow 0x100 | ||
48 | #define McaIdHigh 0x101 | ||
49 | #define McaIrqEnable 0x102 | ||
50 | #define McaMemory 0x103 | ||
51 | #define McaRIOId 0x6a5c | ||
52 | #define McaIrq9 0x00 | ||
53 | #define McaIrq3 0x02 | ||
54 | #define McaIrq4 0x04 | ||
55 | #define McaIrq7 0x06 | ||
56 | #define McaIrq10 0x08 | ||
57 | #define McaIrq11 0x0A | ||
58 | #define McaIrq12 0x0C | ||
59 | #define McaIrq15 0x0E | ||
60 | #define McaIrqMask 0x0E | ||
61 | #define McaCardEnable 0x01 | ||
62 | #define McaAddress(X) (((X)&0xFF)<<16) | ||
63 | |||
64 | #define McaTpFastLinks 0x40 | ||
65 | #define McaTpSlowLinks 0x00 | ||
66 | #define McaTpBootFromRam 0x01 | ||
67 | #define McaTpBootFromLink 0x00 | ||
68 | #define McaTpBusEnable 0x02 | ||
69 | #define McaTpBusDisable 0x00 | ||
70 | |||
71 | #define RIO_MCA_DEFAULT_MODE SLOW_LINKS | ||
72 | |||
73 | #endif /* __rio_mca_h__ */ | ||
diff --git a/drivers/char/rio/mesg.h b/drivers/char/rio/mesg.h new file mode 100644 index 000000000000..9cf6c0bacea4 --- /dev/null +++ b/drivers/char/rio/mesg.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : mesg.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:12 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)mesg.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_mesg_h__ | ||
34 | #define __rio_mesg_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_mesg_h_sccs_ = "@(#)mesg.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | |||
41 | #endif /* __rio_mesg_h__ */ | ||
diff --git a/drivers/char/rio/param.h b/drivers/char/rio/param.h new file mode 100644 index 000000000000..2dc30b9aab37 --- /dev/null +++ b/drivers/char/rio/param.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : param.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:12 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)param.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_param_h__ | ||
34 | #define __rio_param_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_param_h_sccs_ = "@(#)param.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | |||
41 | /* | ||
42 | ** the param command block, as used in OPEN and PARAM calls. | ||
43 | */ | ||
44 | |||
45 | struct phb_param | ||
46 | { | ||
47 | BYTE Cmd; /* It is very important that these line up */ | ||
48 | BYTE Cor1; /* with what is expected at the other end. */ | ||
49 | BYTE Cor2; /* to confirm that you've got it right, */ | ||
50 | BYTE Cor4; /* check with cirrus/cirrus.h */ | ||
51 | BYTE Cor5; | ||
52 | BYTE TxXon; /* Transmit X-On character */ | ||
53 | BYTE TxXoff; /* Transmit X-Off character */ | ||
54 | BYTE RxXon; /* Receive X-On character */ | ||
55 | BYTE RxXoff; /* Receive X-Off character */ | ||
56 | BYTE LNext; /* Literal-next character */ | ||
57 | BYTE TxBaud; /* Transmit baudrate */ | ||
58 | BYTE RxBaud; /* Receive baudrate */ | ||
59 | }; | ||
60 | |||
61 | #endif | ||
diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h new file mode 100644 index 000000000000..46f99dfdac8d --- /dev/null +++ b/drivers/char/rio/parmmap.h | |||
@@ -0,0 +1,96 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* H O S T M E M O R Y M A P | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra / Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | 6/4/1991 jonb Made changes to accommodate Mips R3230 bus | ||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _parmap_h | ||
38 | #define _parmap_h | ||
39 | |||
40 | |||
41 | #ifdef SCCS_LABELS | ||
42 | #ifndef lint | ||
43 | /* static char *_rio_parmmap_h_sccs = "@(#)parmmap.h 1.4"; */ | ||
44 | #endif | ||
45 | #endif | ||
46 | |||
47 | typedef struct PARM_MAP PARM_MAP ; | ||
48 | |||
49 | struct PARM_MAP | ||
50 | { | ||
51 | PHB_ptr phb_ptr ; /* Pointer to the PHB array */ | ||
52 | WORD_ptr phb_num_ptr ; /* Ptr to Number of PHB's */ | ||
53 | FREE_LIST_ptr free_list; /* Free List pointer */ | ||
54 | FREE_LIST_ptr free_list_end; /* Free List End pointer */ | ||
55 | Q_BUF_ptr_ptr q_free_list_ptr ; /* Ptr to Q_BUF variable */ | ||
56 | BYTE_ptr unit_id_ptr ; /* Unit Id */ | ||
57 | LPB_ptr link_str_ptr ; /* Link Structure Array */ | ||
58 | BYTE_ptr bootloader_1 ; /* 1st Stage Boot Loader */ | ||
59 | BYTE_ptr bootloader_2 ; /* 2nd Stage Boot Loader */ | ||
60 | WORD_ptr port_route_map_ptr ; /* Port Route Map */ | ||
61 | ROUTE_STR_ptr route_ptr ; /* Unit Route Map */ | ||
62 | NUMBER_ptr map_present ; /* Route Map present */ | ||
63 | NUMBER pkt_num ; /* Total number of packets */ | ||
64 | NUMBER q_num ; /* Total number of Q packets */ | ||
65 | WORD buffers_per_port ; /* Number of buffers per port */ | ||
66 | WORD heap_size ; /* Initial size of heap */ | ||
67 | WORD heap_left ; /* Current Heap left */ | ||
68 | WORD error ; /* Error code */ | ||
69 | WORD tx_max; /* Max number of tx pkts per phb */ | ||
70 | WORD rx_max; /* Max number of rx pkts per phb */ | ||
71 | WORD rx_limit; /* For high / low watermarks */ | ||
72 | NUMBER links ; /* Links to use */ | ||
73 | NUMBER timer ; /* Interrupts per second */ | ||
74 | RUP_ptr rups ; /* Pointer to the RUPs */ | ||
75 | WORD max_phb ; /* Mostly for debugging */ | ||
76 | WORD living ; /* Just increments!! */ | ||
77 | WORD init_done ; /* Initialisation over */ | ||
78 | WORD booting_link ; | ||
79 | WORD idle_count ; /* Idle time counter */ | ||
80 | WORD busy_count ; /* Busy counter */ | ||
81 | WORD idle_control ; /* Control Idle Process */ | ||
82 | #if defined(HOST) || defined(INKERNEL) | ||
83 | WORD tx_intr; /* TX interrupt pending */ | ||
84 | WORD rx_intr; /* RX interrupt pending */ | ||
85 | WORD rup_intr; /* RUP interrupt pending */ | ||
86 | #endif | ||
87 | #if defined(RTA) | ||
88 | WORD dying_count; /* Count of processes dead */ | ||
89 | #endif | ||
90 | } ; | ||
91 | |||
92 | #endif | ||
93 | |||
94 | /*********** end of file ***********/ | ||
95 | |||
96 | |||
diff --git a/drivers/char/rio/pci.h b/drivers/char/rio/pci.h new file mode 100644 index 000000000000..dc635bd25194 --- /dev/null +++ b/drivers/char/rio/pci.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : pci.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:12 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)pci.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_pci_h__ | ||
34 | #define __rio_pci_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_pci_h_sccs_ = "@(#)pci.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** PCI stuff | ||
42 | */ | ||
43 | |||
44 | #define PCITpFastClock 0x80 | ||
45 | #define PCITpSlowClock 0x00 | ||
46 | #define PCITpFastLinks 0x40 | ||
47 | #define PCITpSlowLinks 0x00 | ||
48 | #define PCITpIntEnable 0x04 | ||
49 | #define PCITpIntDisable 0x00 | ||
50 | #define PCITpBusEnable 0x02 | ||
51 | #define PCITpBusDisable 0x00 | ||
52 | #define PCITpBootFromRam 0x01 | ||
53 | #define PCITpBootFromLink 0x00 | ||
54 | |||
55 | #define RIO_PCI_VENDOR 0x11CB | ||
56 | #define RIO_PCI_DEVICE 0x8000 | ||
57 | #define RIO_PCI_BASE_CLASS 0x02 | ||
58 | #define RIO_PCI_SUB_CLASS 0x80 | ||
59 | #define RIO_PCI_PROG_IFACE 0x00 | ||
60 | |||
61 | #define RIO_PCI_RID 0x0008 | ||
62 | #define RIO_PCI_BADR0 0x0010 | ||
63 | #define RIO_PCI_INTLN 0x003C | ||
64 | #define RIO_PCI_INTPIN 0x003D | ||
65 | |||
66 | #define RIO_PCI_MEM_SIZE 65536 | ||
67 | |||
68 | #define RIO_PCI_TURBO_TP 0x80 | ||
69 | #define RIO_PCI_FAST_LINKS 0x40 | ||
70 | #define RIO_PCI_INT_ENABLE 0x04 | ||
71 | #define RIO_PCI_TP_BUS_ENABLE 0x02 | ||
72 | #define RIO_PCI_BOOT_FROM_RAM 0x01 | ||
73 | |||
74 | #define RIO_PCI_DEFAULT_MODE 0x05 | ||
75 | |||
76 | #endif /* __rio_pci_h__ */ | ||
diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h new file mode 100644 index 000000000000..e1483a0e30bd --- /dev/null +++ b/drivers/char/rio/phb.h | |||
@@ -0,0 +1,293 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* P H B H E A D E R ******* | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra, Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _phb_h | ||
38 | #define _phb_h 1 | ||
39 | |||
40 | #ifdef SCCS_LABELS | ||
41 | #ifndef lint | ||
42 | /* static char *_rio_phb_h_sccs = "@(#)phb.h 1.12"; */ | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | |||
47 | /************************************************* | ||
48 | * Set the LIMIT values. | ||
49 | ************************************************/ | ||
50 | #ifdef RTA | ||
51 | #define RX_LIMIT (ushort) 3 | ||
52 | #endif | ||
53 | #ifdef HOST | ||
54 | #define RX_LIMIT (ushort) 1 | ||
55 | #endif | ||
56 | |||
57 | |||
58 | /************************************************* | ||
59 | * Handshake asserted. Deasserted by the LTT(s) | ||
60 | ************************************************/ | ||
61 | #define PHB_HANDSHAKE_SET ((ushort) 0x001) /* Set by LRT */ | ||
62 | |||
63 | #define PHB_HANDSHAKE_RESET ((ushort) 0x002) /* Set by ISR / driver */ | ||
64 | |||
65 | #define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET) | ||
66 | /* Reset by ltt */ | ||
67 | |||
68 | |||
69 | /************************************************* | ||
70 | * Maximum number of PHB's | ||
71 | ************************************************/ | ||
72 | #if defined (HOST) || defined (INKERNEL) | ||
73 | #define MAX_PHB ((ushort) 128) /* range 0-127 */ | ||
74 | #else | ||
75 | #define MAX_PHB ((ushort) 8) /* range 0-7 */ | ||
76 | #endif | ||
77 | |||
78 | /************************************************* | ||
79 | * Defines for the mode fields | ||
80 | ************************************************/ | ||
81 | #define TXPKT_INCOMPLETE 0x0001 /* Previous tx packet not completed */ | ||
82 | #define TXINTR_ENABLED 0x0002 /* Tx interrupt is enabled */ | ||
83 | #define TX_TAB3 0x0004 /* TAB3 mode */ | ||
84 | #define TX_OCRNL 0x0008 /* OCRNL mode */ | ||
85 | #define TX_ONLCR 0x0010 /* ONLCR mode */ | ||
86 | #define TX_SENDSPACES 0x0020 /* Send n spaces command needs | ||
87 | completing */ | ||
88 | #define TX_SENDNULL 0x0040 /* Escaping NULL needs completing */ | ||
89 | #define TX_SENDLF 0x0080 /* LF -> CR LF needs completing */ | ||
90 | #define TX_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel | ||
91 | port */ | ||
92 | #define TX_HANGOVER (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL) | ||
93 | #define TX_DTRFLOW 0x0200 /* DTR tx flow control */ | ||
94 | #define TX_DTRFLOWED 0x0400 /* DTR is low - don't allow more data | ||
95 | into the FIFO */ | ||
96 | #define TX_DATAINFIFO 0x0800 /* There is data in the FIFO */ | ||
97 | #define TX_BUSY 0x1000 /* Data in FIFO, shift or holding regs */ | ||
98 | |||
99 | #define RX_SPARE 0x0001 /* SPARE */ | ||
100 | #define RXINTR_ENABLED 0x0002 /* Rx interrupt enabled */ | ||
101 | #define RX_ICRNL 0x0008 /* ICRNL mode */ | ||
102 | #define RX_INLCR 0x0010 /* INLCR mode */ | ||
103 | #define RX_IGNCR 0x0020 /* IGNCR mode */ | ||
104 | #define RX_CTSFLOW 0x0040 /* CTSFLOW enabled */ | ||
105 | #define RX_IXOFF 0x0080 /* IXOFF enabled */ | ||
106 | #define RX_CTSFLOWED 0x0100 /* CTSFLOW and CTS dropped */ | ||
107 | #define RX_IXOFFED 0x0200 /* IXOFF and xoff sent */ | ||
108 | #define RX_BUFFERED 0x0400 /* Try and pass on complete packets */ | ||
109 | |||
110 | #define PORT_ISOPEN 0x0001 /* Port open? */ | ||
111 | #define PORT_HUPCL 0x0002 /* Hangup on close? */ | ||
112 | #define PORT_MOPENPEND 0x0004 /* Modem open pending */ | ||
113 | #define PORT_ISPARALLEL 0x0008 /* Parallel port */ | ||
114 | #define PORT_BREAK 0x0010 /* Port on break */ | ||
115 | #define PORT_STATUSPEND 0x0020 /* Status packet pending */ | ||
116 | #define PORT_BREAKPEND 0x0040 /* Break packet pending */ | ||
117 | #define PORT_MODEMPEND 0x0080 /* Modem status packet pending */ | ||
118 | #define PORT_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel | ||
119 | port */ | ||
120 | #define PORT_FULLMODEM 0x0200 /* Full modem signals */ | ||
121 | #define PORT_RJ45 0x0400 /* RJ45 connector - no RI signal */ | ||
122 | #define PORT_RESTRICTED 0x0600 /* Restricted connector - no RI / DTR */ | ||
123 | |||
124 | #define PORT_MODEMBITS 0x0600 /* Mask for modem fields */ | ||
125 | |||
126 | #define PORT_WCLOSE 0x0800 /* Waiting for close */ | ||
127 | #define PORT_HANDSHAKEFIX 0x1000 /* Port has H/W flow control fix */ | ||
128 | #define PORT_WASPCLOSED 0x2000 /* Port closed with PCLOSE */ | ||
129 | #define DUMPMODE 0x4000 /* Dump RTA mem */ | ||
130 | #define READ_REG 0x8000 /* Read CD1400 register */ | ||
131 | |||
132 | |||
133 | |||
134 | /************************************************************************** | ||
135 | * PHB Structure | ||
136 | * A few words. | ||
137 | * | ||
138 | * Normally Packets are added to the end of the list and removed from | ||
139 | * the start. The pointer tx_add points to a SPACE to put a Packet. | ||
140 | * The pointer tx_remove points to the next Packet to remove | ||
141 | *************************************************************************/ | ||
142 | #ifndef INKERNEL | ||
143 | #define src_unit u2.s2.unit | ||
144 | #define src_port u2.s2.port | ||
145 | #define dest_unit u1.s1.unit | ||
146 | #define dest_port u1.s1.port | ||
147 | #endif | ||
148 | #ifdef HOST | ||
149 | #define tx_start u3.s1.tx_start_ptr_ptr | ||
150 | #define tx_add u3.s1.tx_add_ptr_ptr | ||
151 | #define tx_end u3.s1.tx_end_ptr_ptr | ||
152 | #define tx_remove u3.s1.tx_remove_ptr_ptr | ||
153 | #define rx_start u4.s1.rx_start_ptr_ptr | ||
154 | #define rx_add u4.s1.rx_add_ptr_ptr | ||
155 | #define rx_end u4.s1.rx_end_ptr_ptr | ||
156 | #define rx_remove u4.s1.rx_remove_ptr_ptr | ||
157 | #endif | ||
158 | typedef struct PHB PHB ; | ||
159 | struct PHB { | ||
160 | #ifdef RTA | ||
161 | ushort port; | ||
162 | #endif | ||
163 | #ifdef INKERNEL | ||
164 | WORD source; | ||
165 | #else | ||
166 | union | ||
167 | { | ||
168 | ushort source; /* Complete source */ | ||
169 | struct | ||
170 | { | ||
171 | unsigned char unit; /* Source unit */ | ||
172 | unsigned char port; /* Source port */ | ||
173 | } s2; | ||
174 | } u2; | ||
175 | #endif | ||
176 | WORD handshake ; | ||
177 | WORD status ; | ||
178 | NUMBER timeout ; /* Maximum of 1.9 seconds */ | ||
179 | WORD link ; /* Send down this link */ | ||
180 | #ifdef INKERNEL | ||
181 | WORD destination; | ||
182 | #else | ||
183 | union | ||
184 | { | ||
185 | ushort destination; /* Complete destination */ | ||
186 | struct | ||
187 | { | ||
188 | unsigned char unit; /* Destination unit */ | ||
189 | unsigned char port; /* Destination port */ | ||
190 | } s1; | ||
191 | } u1; | ||
192 | #endif | ||
193 | #ifdef RTA | ||
194 | ushort tx_pkts_added; | ||
195 | ushort tx_pkts_removed; | ||
196 | Q_BUF_ptr tx_q_start ; /* Start of the Q list chain */ | ||
197 | short num_tx_q_bufs ; /* Number of Q buffers in the chain */ | ||
198 | PKT_ptr_ptr tx_add ; /* Add a new Packet here */ | ||
199 | Q_BUF_ptr tx_add_qb; /* Pointer to the add Q buf */ | ||
200 | PKT_ptr_ptr tx_add_st_qbb ; /* Pointer to start of the Q's buf */ | ||
201 | PKT_ptr_ptr tx_add_end_qbb ; /* Pointer to the end of the Q's buf */ | ||
202 | PKT_ptr_ptr tx_remove ; /* Remove a Packet here */ | ||
203 | Q_BUF_ptr tx_remove_qb ; /* Pointer to the remove Q buf */ | ||
204 | PKT_ptr_ptr tx_remove_st_qbb ; /* Pointer to the start of the Q buf */ | ||
205 | PKT_ptr_ptr tx_remove_end_qbb ; /* Pointer to the end of the Q buf */ | ||
206 | #endif | ||
207 | #ifdef INKERNEL | ||
208 | PKT_ptr_ptr tx_start ; | ||
209 | PKT_ptr_ptr tx_end ; | ||
210 | PKT_ptr_ptr tx_add ; | ||
211 | PKT_ptr_ptr tx_remove ; | ||
212 | #endif | ||
213 | #ifdef HOST | ||
214 | union | ||
215 | { | ||
216 | struct | ||
217 | { | ||
218 | PKT_ptr_ptr tx_start_ptr_ptr; | ||
219 | PKT_ptr_ptr tx_end_ptr_ptr; | ||
220 | PKT_ptr_ptr tx_add_ptr_ptr; | ||
221 | PKT_ptr_ptr tx_remove_ptr_ptr; | ||
222 | } s1; | ||
223 | struct | ||
224 | { | ||
225 | ushort * tx_start_ptr; | ||
226 | ushort * tx_end_ptr; | ||
227 | ushort * tx_add_ptr; | ||
228 | ushort * tx_remove_ptr; | ||
229 | } s2; | ||
230 | } u3; | ||
231 | #endif | ||
232 | |||
233 | #ifdef RTA | ||
234 | ushort rx_pkts_added; | ||
235 | ushort rx_pkts_removed; | ||
236 | Q_BUF_ptr rx_q_start ; /* Start of the Q list chain */ | ||
237 | short num_rx_q_bufs ; /* Number of Q buffers in the chain */ | ||
238 | PKT_ptr_ptr rx_add ; /* Add a new Packet here */ | ||
239 | Q_BUF_ptr rx_add_qb ; /* Pointer to the add Q buf */ | ||
240 | PKT_ptr_ptr rx_add_st_qbb ; /* Pointer to start of the Q's buf */ | ||
241 | PKT_ptr_ptr rx_add_end_qbb ; /* Pointer to the end of the Q's buf */ | ||
242 | PKT_ptr_ptr rx_remove ; /* Remove a Packet here */ | ||
243 | Q_BUF_ptr rx_remove_qb ; /* Pointer to the remove Q buf */ | ||
244 | PKT_ptr_ptr rx_remove_st_qbb ; /* Pointer to the start of the Q buf */ | ||
245 | PKT_ptr_ptr rx_remove_end_qbb ; /* Pointer to the end of the Q buf */ | ||
246 | #endif | ||
247 | #ifdef INKERNEL | ||
248 | PKT_ptr_ptr rx_start ; | ||
249 | PKT_ptr_ptr rx_end ; | ||
250 | PKT_ptr_ptr rx_add ; | ||
251 | PKT_ptr_ptr rx_remove ; | ||
252 | #endif | ||
253 | #ifdef HOST | ||
254 | union | ||
255 | { | ||
256 | struct | ||
257 | { | ||
258 | PKT_ptr_ptr rx_start_ptr_ptr; | ||
259 | PKT_ptr_ptr rx_end_ptr_ptr; | ||
260 | PKT_ptr_ptr rx_add_ptr_ptr; | ||
261 | PKT_ptr_ptr rx_remove_ptr_ptr; | ||
262 | } s1; | ||
263 | struct | ||
264 | { | ||
265 | ushort * rx_start_ptr; | ||
266 | ushort * rx_end_ptr; | ||
267 | ushort * rx_add_ptr; | ||
268 | ushort * rx_remove_ptr; | ||
269 | } s2; | ||
270 | } u4; | ||
271 | #endif | ||
272 | |||
273 | #ifdef RTA /* some fields for the remotes */ | ||
274 | ushort flush_count; /* Count of write flushes */ | ||
275 | ushort txmode; /* Modes for tx */ | ||
276 | ushort rxmode; /* Modes for rx */ | ||
277 | ushort portmode; /* Generic modes */ | ||
278 | ushort column; /* TAB3 column count */ | ||
279 | ushort tx_subscript; /* (TX) Subscript into data field */ | ||
280 | ushort rx_subscript; /* (RX) Subscript into data field */ | ||
281 | PKT_ptr rx_incomplete; /* Hold an incomplete packet here */ | ||
282 | ushort modem_bits; /* Modem bits to mask */ | ||
283 | ushort lastModem; /* Modem control lines. */ | ||
284 | ushort addr; /* Address for sub commands */ | ||
285 | ushort MonitorTstate; /* TRUE if monitoring tstop */ | ||
286 | #endif | ||
287 | |||
288 | } ; | ||
289 | |||
290 | #endif | ||
291 | |||
292 | /*********** end of file ***********/ | ||
293 | |||
diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h new file mode 100644 index 000000000000..66bb2ff0f694 --- /dev/null +++ b/drivers/char/rio/pkt.h | |||
@@ -0,0 +1,120 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* P A C K E T H E A D E R F I L E | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra / Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _pkt_h | ||
38 | #define _pkt_h 1 | ||
39 | |||
40 | |||
41 | #ifdef SCCS_LABELS | ||
42 | #ifndef lint | ||
43 | /* static char *_rio_pkt_h_sccs = "@(#)pkt.h 1.8"; */ | ||
44 | #endif | ||
45 | #endif | ||
46 | |||
47 | #define MAX_TTL 0xf | ||
48 | #define PKT_CMD_BIT ((ushort) 0x080) | ||
49 | #define PKT_CMD_DATA ((ushort) 0x080) | ||
50 | |||
51 | #define PKT_ACK ((ushort) 0x040) | ||
52 | |||
53 | #define PKT_TGL ((ushort) 0x020) | ||
54 | |||
55 | #define PKT_LEN_MASK ((ushort) 0x07f) | ||
56 | |||
57 | #define DATA_WNDW ((ushort) 0x10) | ||
58 | #define PKT_TTL_MASK ((ushort) 0x0f) | ||
59 | |||
60 | #define PKT_MAX_DATA_LEN 72 | ||
61 | |||
62 | #define PKT_LENGTH sizeof(struct PKT) | ||
63 | #define SYNC_PKT_LENGTH (PKT_LENGTH + 4) | ||
64 | |||
65 | #define CONTROL_PKT_LEN_MASK PKT_LEN_MASK | ||
66 | #define CONTROL_PKT_CMD_BIT PKT_CMD_BIT | ||
67 | #define CONTROL_PKT_ACK (PKT_ACK << 8) | ||
68 | #define CONTROL_PKT_TGL (PKT_TGL << 8) | ||
69 | #define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8) | ||
70 | #define CONTROL_DATA_WNDW (DATA_WNDW << 8) | ||
71 | |||
72 | struct PKT { | ||
73 | #ifdef INKERNEL | ||
74 | BYTE dest_unit ; /* Destination Unit Id */ | ||
75 | BYTE dest_port ; /* Destination POrt */ | ||
76 | BYTE src_unit ; /* Source Unit Id */ | ||
77 | BYTE src_port ; /* Source POrt */ | ||
78 | #else | ||
79 | union | ||
80 | { | ||
81 | ushort destination; /* Complete destination */ | ||
82 | struct | ||
83 | { | ||
84 | unsigned char unit; /* Destination unit */ | ||
85 | unsigned char port; /* Destination port */ | ||
86 | } s1; | ||
87 | } u1; | ||
88 | union | ||
89 | { | ||
90 | ushort source; /* Complete source */ | ||
91 | struct | ||
92 | { | ||
93 | unsigned char unit; /* Source unit */ | ||
94 | unsigned char port; /* Source port */ | ||
95 | } s2; | ||
96 | } u2; | ||
97 | #endif | ||
98 | #ifdef INKERNEL | ||
99 | BYTE len ; | ||
100 | BYTE control; | ||
101 | #else | ||
102 | union | ||
103 | { | ||
104 | ushort control; | ||
105 | struct | ||
106 | { | ||
107 | unsigned char len; | ||
108 | unsigned char control; | ||
109 | } s3; | ||
110 | } u3; | ||
111 | #endif | ||
112 | BYTE data[PKT_MAX_DATA_LEN] ; | ||
113 | /* Actual data :-) */ | ||
114 | WORD csum ; /* C-SUM */ | ||
115 | } ; | ||
116 | #endif | ||
117 | |||
118 | /*********** end of file ***********/ | ||
119 | |||
120 | |||
diff --git a/drivers/char/rio/poll.h b/drivers/char/rio/poll.h new file mode 100644 index 000000000000..d9b8e983e175 --- /dev/null +++ b/drivers/char/rio/poll.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* P O L L | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra / Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _poll_h | ||
38 | #define _poll_h | ||
39 | |||
40 | #ifndef lint | ||
41 | #ifdef SCCS_LABELS | ||
42 | static char *_rio_poll_h_sccs = "@(#)poll.h 1.2" ; | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | |||
47 | #ifdef HOST | ||
48 | #define POLL_STACK 100 | ||
49 | #endif | ||
50 | #ifdef RTA | ||
51 | #define POLL_STACK 200 | ||
52 | #endif | ||
53 | |||
54 | #define POLL_PERIOD (int) SECOND | ||
55 | |||
56 | /* The various poll commands */ | ||
57 | #define POLL_POLL 0 /* We are connected and happy.. */ | ||
58 | #define POLL_INTRO 1 /* Introduction packet */ | ||
59 | #define POLL_TOPOLOGY 2 /* Topology update */ | ||
60 | #define POLL_ASSIGN 3 /* ID assign */ | ||
61 | #define POLL_FOAD 4 /* F*** Off And Die */ | ||
62 | #define POLL_LMD 5 /* Let Me Die */ | ||
63 | #define POLL_DYB 6 /* Die You Ba***** */ | ||
64 | |||
65 | /* The way data fields are split up for POLL packets */ | ||
66 | #define POLL_HOST_SERIAL 2 /* Host who booted me */ | ||
67 | #define POLL_MY_SERIAL 6 /* My serial number */ | ||
68 | #define POLL_YOUR_ID 1 /* Your ID number */ | ||
69 | #define POLL_TOPOLOGY_FIELDS 2 /* Topology maps */ | ||
70 | |||
71 | #endif | ||
72 | |||
73 | /*********** end of file ***********/ | ||
74 | |||
75 | |||
76 | |||
diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h new file mode 100644 index 000000000000..8506af06aa9f --- /dev/null +++ b/drivers/char/rio/port.h | |||
@@ -0,0 +1,245 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : port.h | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 11:34:12 | ||
26 | ** Retrieved : 11/6/98 11:34:21 | ||
27 | ** | ||
28 | ** ident @(#)port.h 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_port_h__ | ||
34 | #define __rio_port_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_port_h_sccs_ = "@(#)port.h 1.3"; | ||
38 | #endif | ||
39 | |||
40 | |||
41 | #undef VPIX | ||
42 | |||
43 | |||
44 | /* | ||
45 | ** the port data structure - one per port in the system | ||
46 | */ | ||
47 | |||
48 | #ifdef STATS | ||
49 | struct RIOStats | ||
50 | { | ||
51 | /* | ||
52 | ** interrupt statistics | ||
53 | */ | ||
54 | uint BreakIntCnt; | ||
55 | uint ModemOffCnt; | ||
56 | uint ModemOnCnt; | ||
57 | uint RxIntCnt; | ||
58 | uint TxIntCnt; | ||
59 | /* | ||
60 | ** throughput statistics | ||
61 | */ | ||
62 | uint RxCharCnt; | ||
63 | uint RxPktCnt; | ||
64 | uint RxSaveCnt; | ||
65 | uint TxCharCnt; | ||
66 | uint TxPktCnt; | ||
67 | /* | ||
68 | ** driver entry statistics | ||
69 | */ | ||
70 | uint CloseCnt; | ||
71 | uint IoctlCnt; | ||
72 | uint OpenCnt; | ||
73 | uint ReadCnt; | ||
74 | uint WriteCnt; | ||
75 | /* | ||
76 | ** proc statistics | ||
77 | */ | ||
78 | uint BlockCnt; | ||
79 | uint OutputCnt; | ||
80 | uint ResumeCnt; | ||
81 | uint RflushCnt; | ||
82 | uint SuspendCnt; | ||
83 | uint TbreakCnt; | ||
84 | uint TimeoutCnt; | ||
85 | uint UnblockCnt; | ||
86 | uint WflushCnt; | ||
87 | uint WFBodgeCnt; | ||
88 | }; | ||
89 | #endif | ||
90 | |||
91 | /* | ||
92 | ** Port data structure | ||
93 | */ | ||
94 | struct Port | ||
95 | { | ||
96 | struct gs_port gs; | ||
97 | int PortNum; /* RIO port no., 0-511 */ | ||
98 | struct Host *HostP; | ||
99 | volatile caddr_t Caddr; | ||
100 | ushort HostPort; /* Port number on host card */ | ||
101 | uchar RupNum; /* Number of RUP for port */ | ||
102 | uchar ID2; /* Second ID of RTA for port */ | ||
103 | ulong State; /* FLAGS for open & xopen */ | ||
104 | #define RIO_LOPEN 0x00001 /* Local open */ | ||
105 | #define RIO_MOPEN 0x00002 /* Modem open */ | ||
106 | #define RIO_WOPEN 0x00004 /* Waiting for open */ | ||
107 | #define RIO_CLOSING 0x00008 /* The port is being close */ | ||
108 | #define RIO_XPBUSY 0x00010 /* Transparent printer busy */ | ||
109 | #define RIO_BREAKING 0x00020 /* Break in progress */ | ||
110 | #define RIO_DIRECT 0x00040 /* Doing Direct output */ | ||
111 | #define RIO_EXCLUSIVE 0x00080 /* Stream open for exclusive use */ | ||
112 | #define RIO_NDELAY 0x00100 /* Stream is open FNDELAY */ | ||
113 | #define RIO_CARR_ON 0x00200 /* Stream has carrier present */ | ||
114 | #define RIO_XPWANTR 0x00400 /* Stream wanted by Xprint */ | ||
115 | #define RIO_RBLK 0x00800 /* Stream is read-blocked */ | ||
116 | #define RIO_BUSY 0x01000 /* Stream is BUSY for write */ | ||
117 | #define RIO_TIMEOUT 0x02000 /* Stream timeout in progress */ | ||
118 | #define RIO_TXSTOP 0x04000 /* Stream output is stopped */ | ||
119 | #define RIO_WAITFLUSH 0x08000 /* Stream waiting for flush */ | ||
120 | #define RIO_DYNOROD 0x10000 /* Drain failed */ | ||
121 | #define RIO_DELETED 0x20000 /* RTA has been deleted */ | ||
122 | #define RIO_ISSCANCODE 0x40000 /* This line is in scancode mode */ | ||
123 | #define RIO_USING_EUC 0x100000 /* Using extended Unix chars */ | ||
124 | #define RIO_CAN_COOK 0x200000 /* This line can do cooking */ | ||
125 | #define RIO_TRIAD_MODE 0x400000 /* Enable TRIAD special ops. */ | ||
126 | #define RIO_TRIAD_BLOCK 0x800000 /* Next read will block */ | ||
127 | #define RIO_TRIAD_FUNC 0x1000000 /* Seen a function key coming in */ | ||
128 | #define RIO_THROTTLE_RX 0x2000000 /* RX needs to be throttled. */ | ||
129 | |||
130 | ulong Config; /* FLAGS for NOREAD.... */ | ||
131 | #define RIO_NOREAD 0x0001 /* Are not allowed to read port */ | ||
132 | #define RIO_NOWRITE 0x0002 /* Are not allowed to write port */ | ||
133 | #define RIO_NOXPRINT 0x0004 /* Are not allowed to xprint port */ | ||
134 | #define RIO_NOMASK 0x0007 /* All not allowed things */ | ||
135 | #define RIO_IXANY 0x0008 /* Port is allowed ixany */ | ||
136 | #define RIO_MODEM 0x0010 /* Stream is a modem device */ | ||
137 | #define RIO_IXON 0x0020 /* Port is allowed ixon */ | ||
138 | #define RIO_WAITDRAIN 0x0040 /* Wait for port to completely drain */ | ||
139 | #define RIO_MAP_50_TO_50 0x0080 /* Map 50 baud to 50 baud */ | ||
140 | #define RIO_MAP_110_TO_110 0x0100 /* Map 110 baud to 110 baud */ | ||
141 | |||
142 | /* | ||
143 | ** 15.10.1998 ARG - ESIL 0761 prt fix | ||
144 | ** As LynxOS does not appear to support Hardware Flow Control ..... | ||
145 | ** Define our own flow control flags in 'Config'. | ||
146 | */ | ||
147 | #define RIO_CTSFLOW 0x0200 /* RIO's own CTSFLOW flag */ | ||
148 | #define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */ | ||
149 | |||
150 | |||
151 | struct PHB *PhbP; /* pointer to PHB for port */ | ||
152 | WORD *TxAdd; /* Add packets here */ | ||
153 | WORD *TxStart; /* Start of add array */ | ||
154 | WORD *TxEnd; /* End of add array */ | ||
155 | WORD *RxRemove; /* Remove packets here */ | ||
156 | WORD *RxStart; /* Start of remove array */ | ||
157 | WORD *RxEnd; /* End of remove array */ | ||
158 | uint RtaUniqueNum; /* Unique number of RTA */ | ||
159 | ushort PortState; /* status of port */ | ||
160 | ushort ModemState; /* status of modem lines */ | ||
161 | ulong ModemLines; /* Modem bits sent to RTA */ | ||
162 | uchar CookMode; /* who expands CR/LF? */ | ||
163 | uchar ParamSem; /* Prevent write during param */ | ||
164 | uchar Mapped; /* if port mapped onto host */ | ||
165 | uchar SecondBlock; /* if port belongs to 2nd block | ||
166 | of 16 port RTA */ | ||
167 | uchar InUse; /* how many pre-emptive cmds */ | ||
168 | uchar Lock; /* if params locked */ | ||
169 | uchar Store; /* if params stored across closes */ | ||
170 | uchar FirstOpen; /* TRUE if first time port opened */ | ||
171 | uchar FlushCmdBodge; /* if doing a (non)flush */ | ||
172 | uchar MagicFlags; /* require intr processing */ | ||
173 | #define MAGIC_FLUSH 0x01 /* mirror of WflushFlag */ | ||
174 | #define MAGIC_REBOOT 0x02 /* RTA re-booted, re-open ports */ | ||
175 | #define MORE_OUTPUT_EYGOR 0x04 /* riotproc failed to empty clists */ | ||
176 | uchar WflushFlag; /* 1 How many WFLUSHs active */ | ||
177 | /* | ||
178 | ** Transparent print stuff | ||
179 | */ | ||
180 | struct Xprint | ||
181 | { | ||
182 | #ifndef MAX_XP_CTRL_LEN | ||
183 | #define MAX_XP_CTRL_LEN 16 /* ALSO IN DAEMON.H */ | ||
184 | #endif | ||
185 | uint XpCps; | ||
186 | char XpOn[MAX_XP_CTRL_LEN]; | ||
187 | char XpOff[MAX_XP_CTRL_LEN]; | ||
188 | ushort XpLen; /* strlen(XpOn)+strlen(XpOff) */ | ||
189 | uchar XpActive; | ||
190 | uchar XpLastTickOk; /* TRUE if we can process */ | ||
191 | #define XP_OPEN 00001 | ||
192 | #define XP_RUNABLE 00002 | ||
193 | struct ttystatics *XttyP; | ||
194 | } Xprint; | ||
195 | #ifdef VPIX | ||
196 | v86_t *StashP; | ||
197 | uint IntMask; | ||
198 | struct termss VpixSs; | ||
199 | uchar ModemStatusReg; /* Modem status register */ | ||
200 | #endif | ||
201 | uchar RxDataStart; | ||
202 | uchar Cor2Copy; /* copy of COR2 */ | ||
203 | char *Name; /* points to the Rta's name */ | ||
204 | #ifdef STATS | ||
205 | struct RIOStats Stat; /* ports statistics */ | ||
206 | #endif | ||
207 | char *TxRingBuffer; | ||
208 | ushort TxBufferIn; /* New data arrives here */ | ||
209 | ushort TxBufferOut; /* Intr removes data here */ | ||
210 | ushort OldTxBufferOut; /* Indicates if draining */ | ||
211 | int TimeoutId; /* Timeout ID */ | ||
212 | uint Debug; | ||
213 | uchar WaitUntilBooted; /* True if open should block */ | ||
214 | uint statsGather; /* True if gathering stats */ | ||
215 | ulong txchars; /* Chars transmitted */ | ||
216 | ulong rxchars; /* Chars received */ | ||
217 | ulong opens; /* port open count */ | ||
218 | ulong closes; /* port close count */ | ||
219 | ulong ioctls; /* ioctl count */ | ||
220 | uchar LastRxTgl; /* Last state of rx toggle bit */ | ||
221 | spinlock_t portSem; /* Lock using this sem */ | ||
222 | int MonitorTstate; /* Monitoring ? */ | ||
223 | int timeout_id; /* For calling 100 ms delays */ | ||
224 | int timeout_sem;/* For calling 100 ms delays */ | ||
225 | int firstOpen; /* First time open ? */ | ||
226 | char * p; /* save the global struc here .. */ | ||
227 | }; | ||
228 | |||
229 | struct ModuleInfo | ||
230 | { | ||
231 | char *Name; | ||
232 | uint Flags[4]; /* one per port on a module */ | ||
233 | }; | ||
234 | #endif | ||
235 | |||
236 | /* | ||
237 | ** This struct is required because trying to grab an entire Port structure | ||
238 | ** runs into problems with differing struct sizes between driver and config. | ||
239 | */ | ||
240 | struct PortParams { | ||
241 | uint Port; | ||
242 | ulong Config; | ||
243 | ulong State; | ||
244 | struct ttystatics *TtyP; | ||
245 | }; | ||
diff --git a/drivers/char/rio/proto.h b/drivers/char/rio/proto.h new file mode 100644 index 000000000000..ddff0ef84e3a --- /dev/null +++ b/drivers/char/rio/proto.h | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * | ||
3 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | #ifndef _prototypes_h | ||
20 | #define _prototypes_h | ||
21 | |||
22 | |||
23 | /* | ||
24 | ** boot.c | ||
25 | */ | ||
26 | void init_boot( char *p, short stage); | ||
27 | |||
28 | /* | ||
29 | ** disconct.c | ||
30 | */ | ||
31 | void kill_boot ( LPB *link ); | ||
32 | void disconnected( LPB *link ); | ||
33 | short boot_3( LPB *link, PKT *pkt ); | ||
34 | short send_3_pkt( LPB *link, PKT *pkt); | ||
35 | |||
36 | /* | ||
37 | ** error.c | ||
38 | */ | ||
39 | void du_error(void); | ||
40 | |||
41 | /* | ||
42 | ** formpkt.c | ||
43 | */ | ||
44 | ushort sum_it( PKT *pkt ) ; | ||
45 | void form_rup_pkt( RUP *form_rup, PKT *pkt ); | ||
46 | void form_poll_pkt ( int type, LPB *link, int node ); | ||
47 | void form_route_pkt ( int type, PKT *pkt, LPB *link ); | ||
48 | |||
49 | /* | ||
50 | ** idle.c | ||
51 | */ | ||
52 | void idle( Process *idle_p ); | ||
53 | |||
54 | /* | ||
55 | ** init.c | ||
56 | */ | ||
57 | void general_init(void); | ||
58 | void mem_halt( int error); | ||
59 | |||
60 | /* | ||
61 | ** linkinit.c | ||
62 | */ | ||
63 | void initlink( u_short number, LPB *link); | ||
64 | void runlink( LPB *link); | ||
65 | |||
66 | /* | ||
67 | ** list.c | ||
68 | */ | ||
69 | PKT *get_free_start(void); | ||
70 | void put_free_start( PKT *pkt); | ||
71 | |||
72 | #ifdef HOST | ||
73 | int can_remove_transmit ( PKT **pkt, PKT *pointer ); | ||
74 | #endif | ||
75 | |||
76 | #ifdef RTA | ||
77 | int spl7 ( void ); | ||
78 | int spl0 ( void ); | ||
79 | Q_BUF *get_free_q( void ); | ||
80 | PKT *get_free_end(void); | ||
81 | int add_end( PKT *pkt, PHB *phb, int type); | ||
82 | unsigned short free_packets( PHB *phb, int type); | ||
83 | int can_remove_start( PKT **pkt, PHB *phb, int type); | ||
84 | int can_add_start( PHB *phb, int type); | ||
85 | int can_add_end( PHB *phb, int type); | ||
86 | void put_free_end( PKT *pkt); | ||
87 | int remove_start( PKT **pkt, PHB *phb, int type); | ||
88 | #endif | ||
89 | |||
90 | /* | ||
91 | ** Lrt.c | ||
92 | */ | ||
93 | void lrt( Process *lrt_p, LPB *link ); | ||
94 | |||
95 | #ifdef RTA | ||
96 | void set_led_red ( LPB *link ); | ||
97 | #endif | ||
98 | |||
99 | /* | ||
100 | ** ltt.c | ||
101 | */ | ||
102 | void ltt( Process *ltt_p, LPB *link, PHB *phb_ptr[] ); | ||
103 | void send_poll ( LPB *link ); | ||
104 | void request_id ( LPB *link ); | ||
105 | void send_topology_update ( LPB *link ); | ||
106 | void send_topology ( LPB *link ); | ||
107 | void supply_id ( LPB *link ); | ||
108 | |||
109 | #ifdef RTA | ||
110 | void redirect_queue ( LPB *link, ushort flush ); | ||
111 | int obtain_rup ( int rup_number, PKT **pkt_address, LPB *link ); | ||
112 | #endif | ||
113 | |||
114 | #ifdef TESTING_PERF | ||
115 | int consume_cpu( void ); | ||
116 | #endif | ||
117 | |||
118 | /* | ||
119 | ** lttwake.c | ||
120 | */ | ||
121 | #ifdef HOST | ||
122 | void ltt_wakeup( Process *ltt_wakeup_p ); | ||
123 | #endif | ||
124 | |||
125 | /* | ||
126 | ** mapgen.c | ||
127 | */ | ||
128 | void generate_id_map( short mapping, ROUTE_STR route[] ); | ||
129 | void gen_map( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl ); | ||
130 | void adjust_ttl( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl); | ||
131 | void init_sys_map(void); | ||
132 | |||
133 | /* | ||
134 | ** mmu.c | ||
135 | */ | ||
136 | char *rio_malloc( unsigned int amount); | ||
137 | char *rio_calloc( unsigned int num, unsigned int size); | ||
138 | ERROR rio_mmu_init( uint total_mem ); | ||
139 | |||
140 | /* | ||
141 | ** partn.c | ||
142 | */ | ||
143 | void partition_tx( struct PHB *phb, u_short tx_size, u_short rx_size, u_short rx_limit); | ||
144 | |||
145 | /* | ||
146 | ** poll.c | ||
147 | */ | ||
148 | void tx_poll( Process *tx_poll_p); | ||
149 | |||
150 | /* | ||
151 | ** process.c | ||
152 | */ | ||
153 | int get_proc_space( Process **pd, int **pws, int wssize); | ||
154 | |||
155 | /* | ||
156 | ** readrom.c | ||
157 | */ | ||
158 | void read_serial_number(char *buf); | ||
159 | |||
160 | /* | ||
161 | ** rio.c | ||
162 | */ | ||
163 | int main( void ); | ||
164 | |||
165 | /* | ||
166 | ** route.c | ||
167 | */ | ||
168 | void route_update ( PKT *pkt, LPB *link); | ||
169 | |||
170 | /* | ||
171 | ** rtainit.c | ||
172 | */ | ||
173 | #if defined(RTA) | ||
174 | void rta_init(ushort RtaType); | ||
175 | #endif /* defined(RTA) */ | ||
176 | |||
177 | /* | ||
178 | ** rupboot.c | ||
179 | */ | ||
180 | void rup_boot( PKT *pkt, RUP *this_rup, LPB *link); | ||
181 | |||
182 | #ifdef RTA | ||
183 | void kill_your_neighbour( int link_to_kill ); | ||
184 | #endif | ||
185 | |||
186 | /* | ||
187 | ** rupcmd.c | ||
188 | */ | ||
189 | void rup_command( PKT *pkt, struct RUP *this_rup, LPB *link); | ||
190 | |||
191 | /* | ||
192 | ** ruperr.c | ||
193 | */ | ||
194 | void rup_error( PKT *pkt, RUP *this_rup, LPB *link ); | ||
195 | void illegal_cmd( PKT *src_pkt ); | ||
196 | |||
197 | /* | ||
198 | ** ruppoll.c | ||
199 | */ | ||
200 | void rup_poll( PKT *pkt, RUP *this_rup, LPB *link ); | ||
201 | |||
202 | /* | ||
203 | ** ruppower.c | ||
204 | */ | ||
205 | void rup_power( PKT *pkt, RUP *this_rup, LPB *link ); | ||
206 | |||
207 | /* | ||
208 | ** ruprm.c | ||
209 | */ | ||
210 | void rup_route_map( PKT *pkt, RUP *this_rup, LPB *link); | ||
211 | |||
212 | /* | ||
213 | ** rupstat.c | ||
214 | */ | ||
215 | void rup_status( PKT *pkt, RUP *this_rup, LPB *link); | ||
216 | |||
217 | /* | ||
218 | ** rupsync.c | ||
219 | */ | ||
220 | void rup_sync( PKT *pkt); | ||
221 | |||
222 | /* | ||
223 | ** rxpkt.c | ||
224 | */ | ||
225 | ERROR rx_pkt( PKT_ptr_ptr pkt_address, LPB *link); | ||
226 | |||
227 | /* | ||
228 | ** sendsts.c | ||
229 | */ | ||
230 | void send_status( PKT *requesting_pkt, RUP *this_rup); | ||
231 | |||
232 | /* | ||
233 | ** serial.c | ||
234 | */ | ||
235 | void assign_serial ( char *ser_in, char *ser_out); | ||
236 | int cmp_serial ( char *ser_1, char *ser_2); | ||
237 | |||
238 | /* | ||
239 | ** txpkt.c | ||
240 | */ | ||
241 | ERROR tx_pkt( PKT *pkt, LPB *link); | ||
242 | short send_sync( LPB *link); | ||
243 | |||
244 | #endif /* _prototypes_h */ | ||
diff --git a/drivers/char/rio/protsts.h b/drivers/char/rio/protsts.h new file mode 100644 index 000000000000..848111ac9380 --- /dev/null +++ b/drivers/char/rio/protsts.h | |||
@@ -0,0 +1,119 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* P R O T O C O L S T A T U S S T R U C T U R E ******* | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra / Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _protsts_h | ||
38 | #define _protsts_h 1 | ||
39 | |||
40 | |||
41 | #ifdef SCCS_LABELS | ||
42 | #ifndef lint | ||
43 | /* static char *_rio_protsts_h_sccs = "@(#)protsts.h 1.4"; */ | ||
44 | #endif | ||
45 | #endif | ||
46 | |||
47 | /************************************************* | ||
48 | * ACK bit. Last Packet received OK. Set by | ||
49 | * rxpkt to indicate that the Packet has been | ||
50 | * received OK and that the LTT must set the ACK | ||
51 | * bit in the next outward bound Packet | ||
52 | * and re-set by LTT's after xmit. | ||
53 | * | ||
54 | * Gets shoved into rx_status | ||
55 | ************************************************/ | ||
56 | #define PHB_RX_LAST_PKT_ACKED ((ushort) 0x080) | ||
57 | |||
58 | /******************************************************* | ||
59 | * The Rx TOGGLE bit. | ||
60 | * Stuffed into rx_status by RXPKT | ||
61 | ******************************************************/ | ||
62 | #define PHB_RX_DATA_WNDW ((ushort) 0x040) | ||
63 | |||
64 | /******************************************************* | ||
65 | * The Rx TOGGLE bit. Matches the setting in PKT.H | ||
66 | * Stuffed into rx_status | ||
67 | ******************************************************/ | ||
68 | #define PHB_RX_TGL ((ushort) 0x2000) | ||
69 | |||
70 | |||
71 | /************************************************* | ||
72 | * This bit is set by the LRT to indicate that | ||
73 | * an ACK (packet) must be returned. | ||
74 | * | ||
75 | * Gets shoved into tx_status | ||
76 | ************************************************/ | ||
77 | #define PHB_TX_SEND_PKT_ACK ((ushort) 0x08) | ||
78 | |||
79 | /************************************************* | ||
80 | * Set by LTT to indicate that an ACK is required | ||
81 | *************************************************/ | ||
82 | #define PHB_TX_ACK_RQRD ((ushort) 0x01) | ||
83 | |||
84 | |||
85 | /******************************************************* | ||
86 | * The Tx TOGGLE bit. | ||
87 | * Stuffed into tx_status by RXPKT from the PKT WndW | ||
88 | * field. Looked by the LTT when the NEXT Packet | ||
89 | * is going to be sent. | ||
90 | ******************************************************/ | ||
91 | #define PHB_TX_DATA_WNDW ((ushort) 0x04) | ||
92 | |||
93 | |||
94 | /******************************************************* | ||
95 | * The Tx TOGGLE bit. Matches the setting in PKT.H | ||
96 | * Stuffed into tx_status | ||
97 | ******************************************************/ | ||
98 | #define PHB_TX_TGL ((ushort) 0x02) | ||
99 | |||
100 | /******************************************************* | ||
101 | * Request intr bit. Set when the queue has gone quiet | ||
102 | * and the PHB has requested an interrupt. | ||
103 | ******************************************************/ | ||
104 | #define PHB_TX_INTR ((ushort) 0x100) | ||
105 | |||
106 | /******************************************************* | ||
107 | * SET if the PHB cannot send any more data down the | ||
108 | * Link | ||
109 | ******************************************************/ | ||
110 | #define PHB_TX_HANDSHAKE ((ushort) 0x010) | ||
111 | |||
112 | |||
113 | #define RUP_SEND_WNDW ((ushort) 0x08) ; | ||
114 | |||
115 | #endif | ||
116 | |||
117 | /*********** end of file ***********/ | ||
118 | |||
119 | |||
diff --git a/drivers/char/rio/qbuf.h b/drivers/char/rio/qbuf.h new file mode 100644 index 000000000000..1fce02f8fcfc --- /dev/null +++ b/drivers/char/rio/qbuf.h | |||
@@ -0,0 +1,67 @@ | |||
1 | |||
2 | /**************************************************************************** | ||
3 | ******* ******* | ||
4 | ******* Q U E U E B U F F E R S T R U C T U R E S | ||
5 | ******* ******* | ||
6 | **************************************************************************** | ||
7 | |||
8 | Author : Ian Nandhra / Jeremy Rolls | ||
9 | Date : | ||
10 | |||
11 | * | ||
12 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | |||
28 | Version : 0.01 | ||
29 | |||
30 | |||
31 | Mods | ||
32 | ---------------------------------------------------------------------------- | ||
33 | Date By Description | ||
34 | ---------------------------------------------------------------------------- | ||
35 | |||
36 | ***************************************************************************/ | ||
37 | |||
38 | #ifndef _qbuf_h | ||
39 | #define _qbuf_h 1 | ||
40 | |||
41 | #ifndef lint | ||
42 | #ifdef SCCS_LABELS | ||
43 | static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1" ; | ||
44 | #endif | ||
45 | #endif | ||
46 | |||
47 | |||
48 | |||
49 | #ifdef HOST | ||
50 | #define PKTS_PER_BUFFER 1 | ||
51 | #else | ||
52 | #define PKTS_PER_BUFFER (220 / PKT_LENGTH) | ||
53 | #endif | ||
54 | |||
55 | typedef struct Q_BUF Q_BUF ; | ||
56 | struct Q_BUF { | ||
57 | Q_BUF_ptr next ; | ||
58 | Q_BUF_ptr prev ; | ||
59 | PKT_ptr buf[PKTS_PER_BUFFER] ; | ||
60 | } ; | ||
61 | |||
62 | |||
63 | #endif | ||
64 | |||
65 | |||
66 | /*********** end of file ***********/ | ||
67 | |||
diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h new file mode 100644 index 000000000000..13a9931958b1 --- /dev/null +++ b/drivers/char/rio/rio.h | |||
@@ -0,0 +1,294 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 1998 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : rio.h | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 11:34:13 | ||
26 | ** Retrieved : 11/6/98 11:34:22 | ||
27 | ** | ||
28 | ** ident @(#)rio.h 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_rio_h__ | ||
34 | #define __rio_rio_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_rio_h_sccs_ = "@(#)rio.h 1.3"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** 30.09.1998 ARG - | ||
42 | ** Introduced driver version and host card type strings | ||
43 | */ | ||
44 | #define RIO_DRV_STR "Specialix RIO Driver" | ||
45 | #define RIO_AT_HOST_STR "ISA" | ||
46 | #define RIO_PCI_HOST_STR "PCI" | ||
47 | |||
48 | |||
49 | /* | ||
50 | ** rio_info_store() commands (arbitary values) : | ||
51 | */ | ||
52 | #define RIO_INFO_PUT 0xA4B3C2D1 | ||
53 | #define RIO_INFO_GET 0xF1E2D3C4 | ||
54 | |||
55 | |||
56 | /* | ||
57 | ** anything that I couldn't cram in somewhere else | ||
58 | */ | ||
59 | /* | ||
60 | #ifndef RIODEBUG | ||
61 | #define debug | ||
62 | #else | ||
63 | #define debug rioprint | ||
64 | #endif | ||
65 | */ | ||
66 | |||
67 | |||
68 | /* | ||
69 | ** Maximum numbers of things | ||
70 | */ | ||
71 | #define RIO_SLOTS 4 /* number of configuration slots */ | ||
72 | #define RIO_HOSTS 4 /* number of hosts that can be found */ | ||
73 | #define PORTS_PER_HOST 128 /* number of ports per host */ | ||
74 | #define LINKS_PER_UNIT 4 /* number of links from a host */ | ||
75 | #define RIO_PORTS (PORTS_PER_HOST * RIO_HOSTS) /* max. no. of ports */ | ||
76 | #define RTAS_PER_HOST (MAX_RUP) /* number of RTAs per host */ | ||
77 | #define PORTS_PER_RTA (PORTS_PER_HOST/RTAS_PER_HOST) /* ports on a rta */ | ||
78 | #define PORTS_PER_MODULE 4 /* number of ports on a plug-in module */ | ||
79 | /* number of modules on an RTA */ | ||
80 | #define MODULES_PER_RTA (PORTS_PER_RTA/PORTS_PER_MODULE) | ||
81 | #define MAX_PRODUCT 16 /* numbr of different product codes */ | ||
82 | #define MAX_MODULE_TYPES 16 /* number of different types of module */ | ||
83 | |||
84 | #define RIO_CONTROL_DEV 128 /* minor number of host/control device */ | ||
85 | #define RIO_INVALID_MAJOR 0 /* test first host card's major no for validity */ | ||
86 | |||
87 | /* | ||
88 | ** number of RTAs that can be bound to a master | ||
89 | */ | ||
90 | #define MAX_RTA_BINDINGS (MAX_RUP * RIO_HOSTS) | ||
91 | |||
92 | /* | ||
93 | ** Unit types | ||
94 | */ | ||
95 | #define PC_RTA16 0x90000000 | ||
96 | #define PC_RTA8 0xe0000000 | ||
97 | #define TYPE_HOST 0 | ||
98 | #define TYPE_RTA8 1 | ||
99 | #define TYPE_RTA16 2 | ||
100 | |||
101 | /* | ||
102 | ** Flag values returned by functions | ||
103 | */ | ||
104 | #define RIO_FAIL -1 | ||
105 | #define RIO_SUCCESS 0 | ||
106 | #define COPYFAIL -1 /* copy[in|out] failed */ | ||
107 | |||
108 | /* | ||
109 | ** SysPort value for something that hasn't any ports | ||
110 | */ | ||
111 | #define NO_PORT 0xFFFFFFFF | ||
112 | |||
113 | /* | ||
114 | ** Unit ID Of all hosts | ||
115 | */ | ||
116 | #define HOST_ID 0 | ||
117 | |||
118 | /* | ||
119 | ** Break bytes into nybles | ||
120 | */ | ||
121 | #define LONYBLE(X) ((X) & 0xF) | ||
122 | #define HINYBLE(X) (((X)>>4) & 0xF) | ||
123 | |||
124 | /* | ||
125 | ** Flag values passed into some functions | ||
126 | */ | ||
127 | #define DONT_SLEEP 0 | ||
128 | #define OK_TO_SLEEP 1 | ||
129 | |||
130 | #define DONT_PRINT 1 | ||
131 | #define DO_PRINT 0 | ||
132 | |||
133 | #define PRINT_TO_LOG_CONS 0 | ||
134 | #define PRINT_TO_CONS 1 | ||
135 | #define PRINT_TO_LOG 2 | ||
136 | |||
137 | /* | ||
138 | ** Timeout has trouble with times of less than 3 ticks... | ||
139 | */ | ||
140 | #define MIN_TIMEOUT 3 | ||
141 | |||
142 | /* | ||
143 | ** Generally useful constants | ||
144 | */ | ||
145 | #define HALF_A_SECOND ((HZ)>>1) | ||
146 | #define A_SECOND (HZ) | ||
147 | #define HUNDRED_HZ ((HZ/100)?(HZ/100):1) | ||
148 | #define FIFTY_HZ ((HZ/50)?(HZ/50):1) | ||
149 | #define TWENTY_HZ ((HZ/20)?(HZ/20):1) | ||
150 | #define TEN_HZ ((HZ/10)?(HZ/10):1) | ||
151 | #define FIVE_HZ ((HZ/5)?(HZ/5):1) | ||
152 | #define HUNDRED_MS TEN_HZ | ||
153 | #define FIFTY_MS TWENTY_HZ | ||
154 | #define TWENTY_MS FIFTY_HZ | ||
155 | #define TEN_MS HUNDRED_HZ | ||
156 | #define TWO_SECONDS ((A_SECOND)*2) | ||
157 | #define FIVE_SECONDS ((A_SECOND)*5) | ||
158 | #define TEN_SECONDS ((A_SECOND)*10) | ||
159 | #define FIFTEEN_SECONDS ((A_SECOND)*15) | ||
160 | #define TWENTY_SECONDS ((A_SECOND)*20) | ||
161 | #define HALF_A_MINUTE (A_MINUTE>>1) | ||
162 | #define A_MINUTE (A_SECOND*60) | ||
163 | #define FIVE_MINUTES (A_MINUTE*5) | ||
164 | #define QUARTER_HOUR (A_MINUTE*15) | ||
165 | #define HALF_HOUR (A_MINUTE*30) | ||
166 | #define HOUR (A_MINUTE*60) | ||
167 | |||
168 | #define SIXTEEN_MEG 0x1000000 | ||
169 | #define ONE_MEG 0x100000 | ||
170 | #define SIXTY_FOUR_K 0x10000 | ||
171 | |||
172 | #define RIO_AT_MEM_SIZE SIXTY_FOUR_K | ||
173 | #define RIO_EISA_MEM_SIZE SIXTY_FOUR_K | ||
174 | #define RIO_MCA_MEM_SIZE SIXTY_FOUR_K | ||
175 | |||
176 | #define POLL_VECTOR 0x100 | ||
177 | |||
178 | #define COOK_WELL 0 | ||
179 | #define COOK_MEDIUM 1 | ||
180 | #define COOK_RAW 2 | ||
181 | |||
182 | /* | ||
183 | ** Pointer manipulation stuff | ||
184 | ** RIO_PTR takes hostp->Caddr and the offset into the DP RAM area | ||
185 | ** and produces a UNIX caddr_t (pointer) to the object | ||
186 | ** RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and | ||
187 | ** returns the offset into the DP RAM area. | ||
188 | */ | ||
189 | #define RIO_PTR(C,O) (((caddr_t)(C))+(0xFFFF&(O))) | ||
190 | #define RIO_OFF(C,O) ((int)(O)-(int)(C)) | ||
191 | |||
192 | /* | ||
193 | ** How to convert from various different device number formats: | ||
194 | ** DEV is a dev number, as passed to open, close etc - NOT a minor | ||
195 | ** number! | ||
196 | ** | ||
197 | ** Note: LynxOS only gives us 8 bits for the device minor number, | ||
198 | ** so all this crap here to deal with 'modem' bits etc. is | ||
199 | ** just a load of irrelevant old bunkum! | ||
200 | ** This however does not stop us needing to define a value | ||
201 | ** for RIO_MODEMOFFSET which is required by the 'riomkdev' | ||
202 | ** utility in the New Config Utilities suite. | ||
203 | */ | ||
204 | /* 0-511: direct 512-1023: modem */ | ||
205 | #define RIO_MODEMOFFSET 0x200 /* doesn't mean anything */ | ||
206 | #define RIO_MODEM_MASK 0x1FF | ||
207 | #define RIO_MODEM_BIT 0x200 | ||
208 | #define RIO_UNMODEM(DEV) (MINOR(DEV) & RIO_MODEM_MASK) | ||
209 | #define RIO_ISMODEM(DEV) (MINOR(DEV) & RIO_MODEM_BIT) | ||
210 | #define RIO_PORT(DEV,FIRST_MAJ) ( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \ | ||
211 | + MINOR(DEV) | ||
212 | |||
213 | #define splrio spltty | ||
214 | |||
215 | #define RIO_IPL 5 | ||
216 | #define RIO_PRI (PZERO+10) | ||
217 | #define RIO_CLOSE_PRI PZERO-1 /* uninterruptible sleeps for close */ | ||
218 | |||
219 | typedef struct DbInf | ||
220 | { | ||
221 | uint Flag; | ||
222 | char Name[8]; | ||
223 | } DbInf; | ||
224 | |||
225 | #ifndef TRUE | ||
226 | #define TRUE (1==1) | ||
227 | #endif | ||
228 | #ifndef FALSE | ||
229 | #define FALSE (!TRUE) | ||
230 | #endif | ||
231 | |||
232 | #define CSUM(pkt_ptr) (((ushort *)(pkt_ptr))[0] + ((ushort *)(pkt_ptr))[1] + \ | ||
233 | ((ushort *)(pkt_ptr))[2] + ((ushort *)(pkt_ptr))[3] + \ | ||
234 | ((ushort *)(pkt_ptr))[4] + ((ushort *)(pkt_ptr))[5] + \ | ||
235 | ((ushort *)(pkt_ptr))[6] + ((ushort *)(pkt_ptr))[7] + \ | ||
236 | ((ushort *)(pkt_ptr))[8] + ((ushort *)(pkt_ptr))[9] ) | ||
237 | |||
238 | /* | ||
239 | ** This happy little macro copies SIZE bytes of data from FROM to TO | ||
240 | ** quite well. SIZE must be a constant. | ||
241 | */ | ||
242 | #define CCOPY( FROM, TO, SIZE ) { *(struct s { char data[SIZE]; } *)(TO) = *(struct s *)(FROM); } | ||
243 | |||
244 | /* | ||
245 | ** increment a buffer pointer modulo the size of the buffer... | ||
246 | */ | ||
247 | #define BUMP( P, I ) ((P) = (((P)+(I)) & RIOBufferMask)) | ||
248 | |||
249 | #define INIT_PACKET( PK, PP ) \ | ||
250 | { \ | ||
251 | *((uint *)PK) = PP->PacketInfo; \ | ||
252 | } | ||
253 | |||
254 | #define RIO_LINK_ENABLE 0x80FF /* FF is a hack, mainly for Mips, to */ | ||
255 | /* prevent a really stupid race condition. */ | ||
256 | |||
257 | #define NOT_INITIALISED 0 | ||
258 | #define INITIALISED 1 | ||
259 | |||
260 | #define NOT_POLLING 0 | ||
261 | #define POLLING 1 | ||
262 | |||
263 | #define NOT_CHANGED 0 | ||
264 | #define CHANGED 1 | ||
265 | |||
266 | #define NOT_INUSE 0 | ||
267 | |||
268 | #define DISCONNECT 0 | ||
269 | #define CONNECT 1 | ||
270 | |||
271 | |||
272 | /* | ||
273 | ** Machine types - these must NOT overlap with product codes 0-15 | ||
274 | */ | ||
275 | #define RIO_MIPS_R3230 31 | ||
276 | #define RIO_MIPS_R4030 32 | ||
277 | |||
278 | #define RIO_IO_UNKNOWN -2 | ||
279 | |||
280 | #undef MODERN | ||
281 | #define ERROR( E ) do { u.u_error = E; return OPENFAIL } while ( 0 ) | ||
282 | |||
283 | /* Defines for MPX line discipline routines */ | ||
284 | |||
285 | #define DIST_LINESW_OPEN 0x01 | ||
286 | #define DIST_LINESW_CLOSE 0x02 | ||
287 | #define DIST_LINESW_READ 0x04 | ||
288 | #define DIST_LINESW_WRITE 0x08 | ||
289 | #define DIST_LINESW_IOCTL 0x10 | ||
290 | #define DIST_LINESW_INPUT 0x20 | ||
291 | #define DIST_LINESW_OUTPUT 0x40 | ||
292 | #define DIST_LINESW_MDMINT 0x80 | ||
293 | |||
294 | #endif /* __rio_h__ */ | ||
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c new file mode 100644 index 000000000000..a91ae271cf0a --- /dev/null +++ b/drivers/char/rio/rio_linux.c | |||
@@ -0,0 +1,1380 @@ | |||
1 | |||
2 | /* rio_linux.c -- Linux driver for the Specialix RIO series cards. | ||
3 | * | ||
4 | * | ||
5 | * (C) 1999 R.E.Wolff@BitWizard.nl | ||
6 | * | ||
7 | * Specialix pays for the development and support of this driver. | ||
8 | * Please DO contact support@specialix.co.uk if you require | ||
9 | * support. But please read the documentation (rio.txt) first. | ||
10 | * | ||
11 | * | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License as | ||
15 | * published by the Free Software Foundation; either version 2 of | ||
16 | * the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be | ||
19 | * useful, but WITHOUT ANY WARRANTY; without even the implied | ||
20 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||
21 | * PURPOSE. See the GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public | ||
24 | * License along with this program; if not, write to the Free | ||
25 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, | ||
26 | * USA. | ||
27 | * | ||
28 | * Revision history: | ||
29 | * $Log: rio.c,v $ | ||
30 | * Revision 1.1 1999/07/11 10:13:54 wolff | ||
31 | * Initial revision | ||
32 | * | ||
33 | * */ | ||
34 | |||
35 | #include <linux/module.h> | ||
36 | #include <linux/config.h> | ||
37 | #include <linux/kdev_t.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/sched.h> | ||
41 | #include <linux/ioport.h> | ||
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/errno.h> | ||
44 | #include <linux/tty.h> | ||
45 | #include <linux/tty_flip.h> | ||
46 | #include <linux/mm.h> | ||
47 | #include <linux/serial.h> | ||
48 | #include <linux/fcntl.h> | ||
49 | #include <linux/major.h> | ||
50 | #include <linux/delay.h> | ||
51 | #include <linux/pci.h> | ||
52 | #include <linux/slab.h> | ||
53 | #include <linux/miscdevice.h> | ||
54 | #include <linux/init.h> | ||
55 | |||
56 | #include <linux/generic_serial.h> | ||
57 | #include <asm/uaccess.h> | ||
58 | |||
59 | #if BITS_PER_LONG != 32 | ||
60 | # error FIXME: this driver only works on 32-bit platforms | ||
61 | #endif | ||
62 | |||
63 | #include "linux_compat.h" | ||
64 | #include "typdef.h" | ||
65 | #include "pkt.h" | ||
66 | #include "daemon.h" | ||
67 | #include "rio.h" | ||
68 | #include "riospace.h" | ||
69 | #include "top.h" | ||
70 | #include "cmdpkt.h" | ||
71 | #include "map.h" | ||
72 | #include "riotypes.h" | ||
73 | #include "rup.h" | ||
74 | #include "port.h" | ||
75 | #include "riodrvr.h" | ||
76 | #include "rioinfo.h" | ||
77 | #include "func.h" | ||
78 | #include "errors.h" | ||
79 | #include "pci.h" | ||
80 | |||
81 | #include "parmmap.h" | ||
82 | #include "unixrup.h" | ||
83 | #include "board.h" | ||
84 | #include "host.h" | ||
85 | #include "error.h" | ||
86 | #include "phb.h" | ||
87 | #include "link.h" | ||
88 | #include "cmdblk.h" | ||
89 | #include "route.h" | ||
90 | #include "control.h" | ||
91 | #include "cirrus.h" | ||
92 | #include "rioioctl.h" | ||
93 | #include "param.h" | ||
94 | #include "list.h" | ||
95 | #include "sam.h" | ||
96 | #include "protsts.h" | ||
97 | #include "rioboard.h" | ||
98 | |||
99 | |||
100 | #include "rio_linux.h" | ||
101 | |||
102 | /* I don't think that this driver can handle more than 512 ports on | ||
103 | one machine. Specialix specifies max 4 boards in one machine. I don't | ||
104 | know why. If you want to try anyway you'll have to increase the number | ||
105 | of boards in rio.h. You'll have to allocate more majors if you need | ||
106 | more than 512 ports.... */ | ||
107 | |||
108 | #ifndef RIO_NORMAL_MAJOR0 | ||
109 | /* This allows overriding on the compiler commandline, or in a "major.h" | ||
110 | include or something like that */ | ||
111 | #define RIO_NORMAL_MAJOR0 154 | ||
112 | #define RIO_NORMAL_MAJOR1 156 | ||
113 | #endif | ||
114 | |||
115 | #ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 | ||
116 | #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 | ||
117 | #endif | ||
118 | |||
119 | #ifndef RIO_WINDOW_LEN | ||
120 | #define RIO_WINDOW_LEN 0x10000 | ||
121 | #endif | ||
122 | |||
123 | |||
124 | /* Configurable options: | ||
125 | (Don't be too sure that it'll work if you toggle them) */ | ||
126 | |||
127 | /* Am I paranoid or not ? ;-) */ | ||
128 | #undef RIO_PARANOIA_CHECK | ||
129 | |||
130 | |||
131 | /* 20 -> 2000 per second. The card should rate-limit interrupts at 1000 | ||
132 | Hz, but it is user configurable. I don't recommend going above 1000 | ||
133 | Hz. The interrupt ratelimit might trigger if the interrupt is | ||
134 | shared with a very active other device. | ||
135 | undef this if you want to disable the check.... | ||
136 | */ | ||
137 | #define IRQ_RATE_LIMIT 200 | ||
138 | |||
139 | #if 0 | ||
140 | /* Not implemented */ | ||
141 | /* | ||
142 | * The following defines are mostly for testing purposes. But if you need | ||
143 | * some nice reporting in your syslog, you can define them also. | ||
144 | */ | ||
145 | #define RIO_REPORT_FIFO | ||
146 | #define RIO_REPORT_OVERRUN | ||
147 | #endif | ||
148 | |||
149 | |||
150 | /* These constants are derived from SCO Source */ | ||
151 | static struct Conf | ||
152 | RIOConf = | ||
153 | { | ||
154 | /* locator */ "RIO Config here", | ||
155 | /* startuptime */ HZ*2, /* how long to wait for card to run */ | ||
156 | /* slowcook */ 0, /* TRUE -> always use line disc. */ | ||
157 | /* intrpolltime */ 1, /* The frequency of OUR polls */ | ||
158 | /* breakinterval */ 25, /* x10 mS XXX: units seem to be 1ms not 10! -- REW*/ | ||
159 | /* timer */ 10, /* mS */ | ||
160 | /* RtaLoadBase */ 0x7000, | ||
161 | /* HostLoadBase */ 0x7C00, | ||
162 | /* XpHz */ 5, /* number of Xprint hits per second */ | ||
163 | /* XpCps */ 120, /* Xprint characters per second */ | ||
164 | /* XpOn */ "\033d#", /* start Xprint for a wyse 60 */ | ||
165 | /* XpOff */ "\024", /* end Xprint for a wyse 60 */ | ||
166 | /* MaxXpCps */ 2000, /* highest Xprint speed */ | ||
167 | /* MinXpCps */ 10, /* slowest Xprint speed */ | ||
168 | /* SpinCmds */ 1, /* non-zero for mega fast boots */ | ||
169 | /* First Addr */ 0x0A0000, /* First address to look at */ | ||
170 | /* Last Addr */ 0xFF0000, /* Last address looked at */ | ||
171 | /* BufferSize */ 1024, /* Bytes per port of buffering */ | ||
172 | /* LowWater */ 256, /* how much data left before wakeup */ | ||
173 | /* LineLength */ 80, /* how wide is the console? */ | ||
174 | /* CmdTimeout */ HZ, /* how long a close command may take */ | ||
175 | }; | ||
176 | |||
177 | |||
178 | |||
179 | |||
180 | /* Function prototypes */ | ||
181 | |||
182 | static void rio_disable_tx_interrupts (void * ptr); | ||
183 | static void rio_enable_tx_interrupts (void * ptr); | ||
184 | static void rio_disable_rx_interrupts (void * ptr); | ||
185 | static void rio_enable_rx_interrupts (void * ptr); | ||
186 | static int rio_get_CD (void * ptr); | ||
187 | static void rio_shutdown_port (void * ptr); | ||
188 | static int rio_set_real_termios (void *ptr); | ||
189 | static void rio_hungup (void *ptr); | ||
190 | static void rio_close (void *ptr); | ||
191 | static int rio_chars_in_buffer (void * ptr); | ||
192 | static int rio_fw_ioctl (struct inode *inode, struct file *filp, | ||
193 | unsigned int cmd, unsigned long arg); | ||
194 | static int rio_init_drivers(void); | ||
195 | |||
196 | static void my_hd (void *addr, int len); | ||
197 | |||
198 | static struct tty_driver *rio_driver, *rio_driver2; | ||
199 | |||
200 | /* The name "p" is a bit non-descript. But that's what the rio-lynxos | ||
201 | sources use all over the place. */ | ||
202 | struct rio_info *p; | ||
203 | |||
204 | int rio_debug; | ||
205 | |||
206 | |||
207 | /* You can have the driver poll your card. | ||
208 | - Set rio_poll to 1 to poll every timer tick (10ms on Intel). | ||
209 | This is used when the card cannot use an interrupt for some reason. | ||
210 | */ | ||
211 | static int rio_poll = 1; | ||
212 | |||
213 | |||
214 | /* These are the only open spaces in my computer. Yours may have more | ||
215 | or less.... */ | ||
216 | static int rio_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000}; | ||
217 | |||
218 | #define NR_RIO_ADDRS (sizeof(rio_probe_addrs)/sizeof (int)) | ||
219 | |||
220 | |||
221 | /* Set the mask to all-ones. This alas, only supports 32 interrupts. | ||
222 | Some architectures may need more. -- Changed to LONG to | ||
223 | support up to 64 bits on 64bit architectures. -- REW 20/06/99 */ | ||
224 | long rio_irqmask = -1; | ||
225 | |||
226 | MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.nl>"); | ||
227 | MODULE_DESCRIPTION("RIO driver"); | ||
228 | MODULE_LICENSE("GPL"); | ||
229 | module_param(rio_poll, int, 0); | ||
230 | module_param(rio_debug, int, 0644); | ||
231 | module_param(rio_irqmask, long, 0); | ||
232 | |||
233 | static struct real_driver rio_real_driver = { | ||
234 | rio_disable_tx_interrupts, | ||
235 | rio_enable_tx_interrupts, | ||
236 | rio_disable_rx_interrupts, | ||
237 | rio_enable_rx_interrupts, | ||
238 | rio_get_CD, | ||
239 | rio_shutdown_port, | ||
240 | rio_set_real_termios, | ||
241 | rio_chars_in_buffer, | ||
242 | rio_close, | ||
243 | rio_hungup, | ||
244 | NULL | ||
245 | }; | ||
246 | |||
247 | /* | ||
248 | * Firmware loader driver specific routines | ||
249 | * | ||
250 | */ | ||
251 | |||
252 | static struct file_operations rio_fw_fops = { | ||
253 | .owner = THIS_MODULE, | ||
254 | .ioctl = rio_fw_ioctl, | ||
255 | }; | ||
256 | |||
257 | static struct miscdevice rio_fw_device = { | ||
258 | RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops | ||
259 | }; | ||
260 | |||
261 | |||
262 | |||
263 | |||
264 | |||
265 | #ifdef RIO_PARANOIA_CHECK | ||
266 | |||
267 | /* This doesn't work. Who's paranoid around here? Not me! */ | ||
268 | |||
269 | static inline int rio_paranoia_check(struct rio_port const * port, | ||
270 | char *name, const char *routine) | ||
271 | { | ||
272 | |||
273 | static const char *badmagic = | ||
274 | KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n"; | ||
275 | static const char *badinfo = | ||
276 | KERN_ERR "rio: Warning: null rio port for device %s in %s\n"; | ||
277 | |||
278 | if (!port) { | ||
279 | printk (badinfo, name, routine); | ||
280 | return 1; | ||
281 | } | ||
282 | if (port->magic != RIO_MAGIC) { | ||
283 | printk (badmagic, name, routine); | ||
284 | return 1; | ||
285 | } | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | #else | ||
290 | #define rio_paranoia_check(a,b,c) 0 | ||
291 | #endif | ||
292 | |||
293 | |||
294 | #ifdef DEBUG | ||
295 | static void my_hd (void *ad, int len) | ||
296 | { | ||
297 | int i, j, ch; | ||
298 | unsigned char *addr = ad; | ||
299 | |||
300 | for (i=0;i<len;i+=16) { | ||
301 | rio_dprintk (RIO_DEBUG_PARAM, "%08x ", (int) addr+i); | ||
302 | for (j=0;j<16;j++) { | ||
303 | rio_dprintk (RIO_DEBUG_PARAM, "%02x %s", addr[j+i], (j==7)?" ":""); | ||
304 | } | ||
305 | for (j=0;j<16;j++) { | ||
306 | ch = addr[j+i]; | ||
307 | rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch)); | ||
308 | } | ||
309 | rio_dprintk (RIO_DEBUG_PARAM, "\n"); | ||
310 | } | ||
311 | } | ||
312 | #else | ||
313 | #define my_hd(ad,len) do{/* nothing*/ } while (0) | ||
314 | #endif | ||
315 | |||
316 | |||
317 | /* Delay a number of jiffies, allowing a signal to interrupt */ | ||
318 | int RIODelay (struct Port *PortP, int njiffies) | ||
319 | { | ||
320 | func_enter (); | ||
321 | |||
322 | rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies); | ||
323 | msleep_interruptible(jiffies_to_msecs(njiffies)); | ||
324 | func_exit(); | ||
325 | |||
326 | if (signal_pending(current)) | ||
327 | return RIO_FAIL; | ||
328 | else | ||
329 | return !RIO_FAIL; | ||
330 | } | ||
331 | |||
332 | |||
333 | /* Delay a number of jiffies, disallowing a signal to interrupt */ | ||
334 | int RIODelay_ni (struct Port *PortP, int njiffies) | ||
335 | { | ||
336 | func_enter (); | ||
337 | |||
338 | rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies); | ||
339 | msleep(jiffies_to_msecs(njiffies)); | ||
340 | func_exit(); | ||
341 | return !RIO_FAIL; | ||
342 | } | ||
343 | |||
344 | |||
345 | int rio_minor(struct tty_struct *tty) | ||
346 | { | ||
347 | return tty->index + (tty->driver == rio_driver) ? 0 : 256; | ||
348 | } | ||
349 | |||
350 | |||
351 | int rio_ismodem(struct tty_struct *tty) | ||
352 | { | ||
353 | return 1; | ||
354 | } | ||
355 | |||
356 | |||
357 | void rio_udelay (int usecs) | ||
358 | { | ||
359 | udelay (usecs); | ||
360 | } | ||
361 | |||
362 | static int rio_set_real_termios (void *ptr) | ||
363 | { | ||
364 | int rv, modem; | ||
365 | struct tty_struct *tty; | ||
366 | func_enter(); | ||
367 | |||
368 | tty = ((struct Port *)ptr)->gs.tty; | ||
369 | |||
370 | modem = rio_ismodem(tty); | ||
371 | |||
372 | rv = RIOParam( (struct Port *) ptr, CONFIG, modem, 1); | ||
373 | |||
374 | func_exit (); | ||
375 | |||
376 | return rv; | ||
377 | } | ||
378 | |||
379 | |||
380 | static void rio_reset_interrupt (struct Host *HostP) | ||
381 | { | ||
382 | func_enter(); | ||
383 | |||
384 | switch( HostP->Type ) { | ||
385 | case RIO_AT: | ||
386 | case RIO_MCA: | ||
387 | case RIO_PCI: | ||
388 | WBYTE(HostP->ResetInt , 0xff); | ||
389 | } | ||
390 | |||
391 | func_exit(); | ||
392 | } | ||
393 | |||
394 | |||
395 | static irqreturn_t rio_interrupt (int irq, void *ptr, struct pt_regs *regs) | ||
396 | { | ||
397 | struct Host *HostP; | ||
398 | func_enter (); | ||
399 | |||
400 | HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */ | ||
401 | rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", | ||
402 | irq, HostP->Ivec); | ||
403 | |||
404 | /* AAargh! The order in which to do these things is essential and | ||
405 | not trivial. | ||
406 | |||
407 | - Rate limit goes before "recursive". Otherwise a series of | ||
408 | recursive calls will hang the machine in the interrupt routine. | ||
409 | |||
410 | - hardware twiddling goes before "recursive". Otherwise when we | ||
411 | poll the card, and a recursive interrupt happens, we won't | ||
412 | ack the card, so it might keep on interrupting us. (especially | ||
413 | level sensitive interrupt systems like PCI). | ||
414 | |||
415 | - Rate limit goes before hardware twiddling. Otherwise we won't | ||
416 | catch a card that has gone bonkers. | ||
417 | |||
418 | - The "initialized" test goes after the hardware twiddling. Otherwise | ||
419 | the card will stick us in the interrupt routine again. | ||
420 | |||
421 | - The initialized test goes before recursive. | ||
422 | */ | ||
423 | |||
424 | |||
425 | |||
426 | #ifdef IRQ_RATE_LIMIT | ||
427 | /* Aaargh! I'm ashamed. This costs more lines-of-code than the | ||
428 | actual interrupt routine!. (Well, used to when I wrote that comment) */ | ||
429 | { | ||
430 | static int lastjif; | ||
431 | static int nintr=0; | ||
432 | |||
433 | if (lastjif == jiffies) { | ||
434 | if (++nintr > IRQ_RATE_LIMIT) { | ||
435 | free_irq (HostP->Ivec, ptr); | ||
436 | printk (KERN_ERR "rio: Too many interrupts. Turning off interrupt %d.\n", | ||
437 | HostP->Ivec); | ||
438 | } | ||
439 | } else { | ||
440 | lastjif = jiffies; | ||
441 | nintr = 0; | ||
442 | } | ||
443 | } | ||
444 | #endif | ||
445 | rio_dprintk (RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n"); | ||
446 | if (HostP->Ivec == irq) { | ||
447 | /* Tell the card we've noticed the interrupt. */ | ||
448 | rio_reset_interrupt (HostP); | ||
449 | } | ||
450 | |||
451 | if ((HostP->Flags & RUN_STATE) != RC_RUNNING) | ||
452 | return IRQ_HANDLED; | ||
453 | |||
454 | if (test_and_set_bit (RIO_BOARD_INTR_LOCK, &HostP->locks)) { | ||
455 | printk (KERN_ERR "Recursive interrupt! (host %d/irq%d)\n", | ||
456 | (int) ptr, HostP->Ivec); | ||
457 | return IRQ_HANDLED; | ||
458 | } | ||
459 | |||
460 | RIOServiceHost(p, HostP, irq); | ||
461 | |||
462 | rio_dprintk ( RIO_DEBUG_IFLOW, "riointr() doing host %d type %d\n", | ||
463 | (int) ptr, HostP->Type); | ||
464 | |||
465 | clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks); | ||
466 | rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", | ||
467 | irq, HostP->Ivec); | ||
468 | func_exit (); | ||
469 | return IRQ_HANDLED; | ||
470 | } | ||
471 | |||
472 | |||
473 | static void rio_pollfunc (unsigned long data) | ||
474 | { | ||
475 | func_enter (); | ||
476 | |||
477 | rio_interrupt (0, &p->RIOHosts[data], NULL); | ||
478 | p->RIOHosts[data].timer.expires = jiffies + rio_poll; | ||
479 | add_timer (&p->RIOHosts[data].timer); | ||
480 | |||
481 | func_exit (); | ||
482 | } | ||
483 | |||
484 | |||
485 | /* ********************************************************************** * | ||
486 | * Here are the routines that actually * | ||
487 | * interface with the generic_serial driver * | ||
488 | * ********************************************************************** */ | ||
489 | |||
490 | /* Ehhm. I don't know how to fiddle with interrupts on the Specialix | ||
491 | cards. .... Hmm. Ok I figured it out. You don't. -- REW */ | ||
492 | |||
493 | static void rio_disable_tx_interrupts (void * ptr) | ||
494 | { | ||
495 | func_enter(); | ||
496 | |||
497 | /* port->gs.flags &= ~GS_TX_INTEN; */ | ||
498 | |||
499 | func_exit(); | ||
500 | } | ||
501 | |||
502 | |||
503 | static void rio_enable_tx_interrupts (void * ptr) | ||
504 | { | ||
505 | struct Port *PortP = ptr; | ||
506 | /* int hn; */ | ||
507 | |||
508 | func_enter(); | ||
509 | |||
510 | /* hn = PortP->HostP - p->RIOHosts; | ||
511 | |||
512 | rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn); | ||
513 | rio_interrupt (-1,(void *) hn, NULL); */ | ||
514 | |||
515 | RIOTxEnable((char *) PortP); | ||
516 | |||
517 | /* | ||
518 | * In general we cannot count on "tx empty" interrupts, although | ||
519 | * the interrupt routine seems to be able to tell the difference. | ||
520 | */ | ||
521 | PortP->gs.flags &= ~GS_TX_INTEN; | ||
522 | |||
523 | func_exit(); | ||
524 | } | ||
525 | |||
526 | |||
527 | static void rio_disable_rx_interrupts (void * ptr) | ||
528 | { | ||
529 | func_enter(); | ||
530 | func_exit(); | ||
531 | } | ||
532 | |||
533 | static void rio_enable_rx_interrupts (void * ptr) | ||
534 | { | ||
535 | /* struct rio_port *port = ptr; */ | ||
536 | func_enter(); | ||
537 | func_exit(); | ||
538 | } | ||
539 | |||
540 | |||
541 | /* Jeez. Isn't this simple? */ | ||
542 | static int rio_get_CD (void * ptr) | ||
543 | { | ||
544 | struct Port *PortP = ptr; | ||
545 | int rv; | ||
546 | |||
547 | func_enter(); | ||
548 | rv = (PortP->ModemState & MSVR1_CD) != 0; | ||
549 | |||
550 | rio_dprintk (RIO_DEBUG_INIT, "Getting CD status: %d\n", rv); | ||
551 | |||
552 | func_exit(); | ||
553 | return rv; | ||
554 | } | ||
555 | |||
556 | |||
557 | /* Jeez. Isn't this simple? Actually, we can sync with the actual port | ||
558 | by just pushing stuff into the queue going to the port... */ | ||
559 | static int rio_chars_in_buffer (void * ptr) | ||
560 | { | ||
561 | func_enter(); | ||
562 | |||
563 | func_exit(); | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | |||
568 | /* Nothing special here... */ | ||
569 | static void rio_shutdown_port (void * ptr) | ||
570 | { | ||
571 | struct Port *PortP; | ||
572 | |||
573 | func_enter(); | ||
574 | |||
575 | PortP = (struct Port *)ptr; | ||
576 | PortP->gs.tty = NULL; | ||
577 | #if 0 | ||
578 | port->gs.flags &= ~ GS_ACTIVE; | ||
579 | if (!port->gs.tty) { | ||
580 | rio_dprintk (RIO_DBUG_TTY, "No tty.\n"); | ||
581 | return; | ||
582 | } | ||
583 | if (!port->gs.tty->termios) { | ||
584 | rio_dprintk (RIO_DEBUG_TTY, "No termios.\n"); | ||
585 | return; | ||
586 | } | ||
587 | if (port->gs.tty->termios->c_cflag & HUPCL) { | ||
588 | rio_setsignals (port, 0, 0); | ||
589 | } | ||
590 | #endif | ||
591 | |||
592 | func_exit(); | ||
593 | } | ||
594 | |||
595 | |||
596 | /* I haven't the foggiest why the decrement use count has to happen | ||
597 | here. The whole linux serial drivers stuff needs to be redesigned. | ||
598 | My guess is that this is a hack to minimize the impact of a bug | ||
599 | elsewhere. Thinking about it some more. (try it sometime) Try | ||
600 | running minicom on a serial port that is driven by a modularized | ||
601 | driver. Have the modem hangup. Then remove the driver module. Then | ||
602 | exit minicom. I expect an "oops". -- REW */ | ||
603 | static void rio_hungup (void *ptr) | ||
604 | { | ||
605 | struct Port *PortP; | ||
606 | |||
607 | func_enter(); | ||
608 | |||
609 | PortP = (struct Port *)ptr; | ||
610 | PortP->gs.tty = NULL; | ||
611 | |||
612 | func_exit (); | ||
613 | } | ||
614 | |||
615 | |||
616 | /* The standard serial_close would become shorter if you'd wrap it like | ||
617 | this. | ||
618 | rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;} | ||
619 | */ | ||
620 | static void rio_close (void *ptr) | ||
621 | { | ||
622 | struct Port *PortP; | ||
623 | |||
624 | func_enter (); | ||
625 | |||
626 | PortP = (struct Port *)ptr; | ||
627 | |||
628 | riotclose (ptr); | ||
629 | |||
630 | if(PortP->gs.count) { | ||
631 | printk (KERN_ERR "WARNING port count:%d\n", PortP->gs.count); | ||
632 | PortP->gs.count = 0; | ||
633 | } | ||
634 | |||
635 | PortP->gs.tty = NULL; | ||
636 | func_exit (); | ||
637 | } | ||
638 | |||
639 | |||
640 | |||
641 | static int rio_fw_ioctl (struct inode *inode, struct file *filp, | ||
642 | unsigned int cmd, unsigned long arg) | ||
643 | { | ||
644 | int rc = 0; | ||
645 | func_enter(); | ||
646 | |||
647 | /* The "dev" argument isn't used. */ | ||
648 | rc = riocontrol (p, 0, cmd, (void *)arg, capable(CAP_SYS_ADMIN)); | ||
649 | |||
650 | func_exit (); | ||
651 | return rc; | ||
652 | } | ||
653 | |||
654 | extern int RIOShortCommand(struct rio_info *p, struct Port *PortP, | ||
655 | int command, int len, int arg); | ||
656 | |||
657 | static int rio_ioctl (struct tty_struct * tty, struct file * filp, | ||
658 | unsigned int cmd, unsigned long arg) | ||
659 | { | ||
660 | int rc; | ||
661 | struct Port *PortP; | ||
662 | int ival; | ||
663 | |||
664 | func_enter(); | ||
665 | |||
666 | PortP = (struct Port *)tty->driver_data; | ||
667 | |||
668 | rc = 0; | ||
669 | switch (cmd) { | ||
670 | #if 0 | ||
671 | case TIOCGSOFTCAR: | ||
672 | rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), | ||
673 | (unsigned int *) arg); | ||
674 | break; | ||
675 | #endif | ||
676 | case TIOCSSOFTCAR: | ||
677 | if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { | ||
678 | tty->termios->c_cflag = | ||
679 | (tty->termios->c_cflag & ~CLOCAL) | | ||
680 | (ival ? CLOCAL : 0); | ||
681 | } | ||
682 | break; | ||
683 | case TIOCGSERIAL: | ||
684 | rc = -EFAULT; | ||
685 | if (access_ok(VERIFY_WRITE, (void *) arg, | ||
686 | sizeof(struct serial_struct))) | ||
687 | rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg); | ||
688 | break; | ||
689 | case TCSBRK: | ||
690 | if ( PortP->State & RIO_DELETED ) { | ||
691 | rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n"); | ||
692 | rc = -EIO; | ||
693 | } else { | ||
694 | if (RIOShortCommand(p, PortP, SBREAK, 2, 250) == RIO_FAIL) { | ||
695 | rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); | ||
696 | rc = -EIO; | ||
697 | } | ||
698 | } | ||
699 | break; | ||
700 | case TCSBRKP: | ||
701 | if ( PortP->State & RIO_DELETED ) { | ||
702 | rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n"); | ||
703 | rc = -EIO; | ||
704 | } else { | ||
705 | int l; | ||
706 | l = arg?arg*100:250; | ||
707 | if (l > 255) l = 255; | ||
708 | if (RIOShortCommand(p, PortP, SBREAK, 2, arg?arg*100:250) == RIO_FAIL) { | ||
709 | rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); | ||
710 | rc = -EIO; | ||
711 | } | ||
712 | } | ||
713 | break; | ||
714 | case TIOCSSERIAL: | ||
715 | rc = -EFAULT; | ||
716 | if (access_ok(VERIFY_READ, (void *) arg, | ||
717 | sizeof(struct serial_struct))) | ||
718 | rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg); | ||
719 | break; | ||
720 | #if 0 | ||
721 | /* | ||
722 | * note: these IOCTLs no longer reach here. Use | ||
723 | * tiocmset/tiocmget driver methods instead. The | ||
724 | * #if 0 disablement predates this comment. | ||
725 | */ | ||
726 | case TIOCMGET: | ||
727 | rc = -EFAULT; | ||
728 | if (access_ok(VERIFY_WRITE, (void *) arg, | ||
729 | sizeof(unsigned int))) { | ||
730 | rc = 0; | ||
731 | ival = rio_getsignals(port); | ||
732 | put_user(ival, (unsigned int *) arg); | ||
733 | } | ||
734 | break; | ||
735 | case TIOCMBIS: | ||
736 | if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { | ||
737 | rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), | ||
738 | ((ival & TIOCM_RTS) ? 1 : -1)); | ||
739 | } | ||
740 | break; | ||
741 | case TIOCMBIC: | ||
742 | if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { | ||
743 | rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), | ||
744 | ((ival & TIOCM_RTS) ? 0 : -1)); | ||
745 | } | ||
746 | break; | ||
747 | case TIOCMSET: | ||
748 | if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { | ||
749 | rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), | ||
750 | ((ival & TIOCM_RTS) ? 1 : 0)); | ||
751 | } | ||
752 | break; | ||
753 | #endif | ||
754 | default: | ||
755 | rc = -ENOIOCTLCMD; | ||
756 | break; | ||
757 | } | ||
758 | func_exit(); | ||
759 | return rc; | ||
760 | } | ||
761 | |||
762 | |||
763 | /* The throttle/unthrottle scheme for the Specialix card is different | ||
764 | * from other drivers and deserves some explanation. | ||
765 | * The Specialix hardware takes care of XON/XOFF | ||
766 | * and CTS/RTS flow control itself. This means that all we have to | ||
767 | * do when signalled by the upper tty layer to throttle/unthrottle is | ||
768 | * to make a note of it here. When we come to read characters from the | ||
769 | * rx buffers on the card (rio_receive_chars()) we look to see if the | ||
770 | * upper layer can accept more (as noted here in rio_rx_throt[]). | ||
771 | * If it can't we simply don't remove chars from the cards buffer. | ||
772 | * When the tty layer can accept chars, we again note that here and when | ||
773 | * rio_receive_chars() is called it will remove them from the cards buffer. | ||
774 | * The card will notice that a ports buffer has drained below some low | ||
775 | * water mark and will unflow control the line itself, using whatever | ||
776 | * flow control scheme is in use for that port. -- Simon Allen | ||
777 | */ | ||
778 | |||
779 | static void rio_throttle (struct tty_struct * tty) | ||
780 | { | ||
781 | struct Port *port = (struct Port *)tty->driver_data; | ||
782 | |||
783 | func_enter(); | ||
784 | /* If the port is using any type of input flow | ||
785 | * control then throttle the port. | ||
786 | */ | ||
787 | |||
788 | if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) { | ||
789 | port->State |= RIO_THROTTLE_RX; | ||
790 | } | ||
791 | |||
792 | func_exit(); | ||
793 | } | ||
794 | |||
795 | |||
796 | static void rio_unthrottle (struct tty_struct * tty) | ||
797 | { | ||
798 | struct Port *port = (struct Port *)tty->driver_data; | ||
799 | |||
800 | func_enter(); | ||
801 | /* Always unthrottle even if flow control is not enabled on | ||
802 | * this port in case we disabled flow control while the port | ||
803 | * was throttled | ||
804 | */ | ||
805 | |||
806 | port->State &= ~RIO_THROTTLE_RX; | ||
807 | |||
808 | func_exit(); | ||
809 | return; | ||
810 | } | ||
811 | |||
812 | |||
813 | |||
814 | |||
815 | |||
816 | /* ********************************************************************** * | ||
817 | * Here are the initialization routines. * | ||
818 | * ********************************************************************** */ | ||
819 | |||
820 | |||
821 | static struct vpd_prom *get_VPD_PROM (struct Host *hp) | ||
822 | { | ||
823 | static struct vpd_prom vpdp; | ||
824 | char *p; | ||
825 | int i; | ||
826 | |||
827 | func_enter(); | ||
828 | rio_dprintk (RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", | ||
829 | hp->Caddr + RIO_VPD_ROM); | ||
830 | |||
831 | p = (char *) &vpdp; | ||
832 | for (i=0;i< sizeof (struct vpd_prom);i++) | ||
833 | *p++ = readb (hp->Caddr+RIO_VPD_ROM + i*2); | ||
834 | /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */ | ||
835 | |||
836 | /* Terminate the identifier string. | ||
837 | *** requires one extra byte in struct vpd_prom *** */ | ||
838 | *p++=0; | ||
839 | |||
840 | if (rio_debug & RIO_DEBUG_PROBE) | ||
841 | my_hd ((char *)&vpdp, 0x20); | ||
842 | |||
843 | func_exit(); | ||
844 | |||
845 | return &vpdp; | ||
846 | } | ||
847 | |||
848 | static struct tty_operations rio_ops = { | ||
849 | .open = riotopen, | ||
850 | .close = gs_close, | ||
851 | .write = gs_write, | ||
852 | .put_char = gs_put_char, | ||
853 | .flush_chars = gs_flush_chars, | ||
854 | .write_room = gs_write_room, | ||
855 | .chars_in_buffer = gs_chars_in_buffer, | ||
856 | .flush_buffer = gs_flush_buffer, | ||
857 | .ioctl = rio_ioctl, | ||
858 | .throttle = rio_throttle, | ||
859 | .unthrottle = rio_unthrottle, | ||
860 | .set_termios = gs_set_termios, | ||
861 | .stop = gs_stop, | ||
862 | .start = gs_start, | ||
863 | .hangup = gs_hangup, | ||
864 | }; | ||
865 | |||
866 | static int rio_init_drivers(void) | ||
867 | { | ||
868 | int error = -ENOMEM; | ||
869 | |||
870 | rio_driver = alloc_tty_driver(256); | ||
871 | if (!rio_driver) | ||
872 | goto out; | ||
873 | rio_driver2 = alloc_tty_driver(256); | ||
874 | if (!rio_driver2) | ||
875 | goto out1; | ||
876 | |||
877 | func_enter(); | ||
878 | |||
879 | rio_driver->owner = THIS_MODULE; | ||
880 | rio_driver->driver_name = "specialix_rio"; | ||
881 | rio_driver->name = "ttySR"; | ||
882 | rio_driver->major = RIO_NORMAL_MAJOR0; | ||
883 | rio_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
884 | rio_driver->subtype = SERIAL_TYPE_NORMAL; | ||
885 | rio_driver->init_termios = tty_std_termios; | ||
886 | rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
887 | rio_driver->flags = TTY_DRIVER_REAL_RAW; | ||
888 | tty_set_operations(rio_driver, &rio_ops); | ||
889 | |||
890 | rio_driver2->owner = THIS_MODULE; | ||
891 | rio_driver2->driver_name = "specialix_rio"; | ||
892 | rio_driver2->name = "ttySR"; | ||
893 | rio_driver2->major = RIO_NORMAL_MAJOR1; | ||
894 | rio_driver2->type = TTY_DRIVER_TYPE_SERIAL; | ||
895 | rio_driver2->subtype = SERIAL_TYPE_NORMAL; | ||
896 | rio_driver2->init_termios = tty_std_termios; | ||
897 | rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
898 | rio_driver2->flags = TTY_DRIVER_REAL_RAW; | ||
899 | tty_set_operations(rio_driver2, &rio_ops); | ||
900 | |||
901 | rio_dprintk (RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios); | ||
902 | |||
903 | if ((error = tty_register_driver(rio_driver))) | ||
904 | goto out2; | ||
905 | if ((error = tty_register_driver(rio_driver2))) | ||
906 | goto out3; | ||
907 | func_exit(); | ||
908 | return 0; | ||
909 | out3: | ||
910 | tty_unregister_driver(rio_driver); | ||
911 | out2: | ||
912 | put_tty_driver(rio_driver2); | ||
913 | out1: | ||
914 | put_tty_driver(rio_driver); | ||
915 | out: | ||
916 | printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n", | ||
917 | error); | ||
918 | return 1; | ||
919 | } | ||
920 | |||
921 | |||
922 | static void * ckmalloc (int size) | ||
923 | { | ||
924 | void *p; | ||
925 | |||
926 | p = kmalloc(size, GFP_KERNEL); | ||
927 | if (p) | ||
928 | memset(p, 0, size); | ||
929 | return p; | ||
930 | } | ||
931 | |||
932 | |||
933 | |||
934 | static int rio_init_datastructures (void) | ||
935 | { | ||
936 | int i; | ||
937 | struct Port *port; | ||
938 | func_enter(); | ||
939 | |||
940 | /* Many drivers statically allocate the maximum number of ports | ||
941 | There is no reason not to allocate them dynamically. Is there? -- REW */ | ||
942 | /* However, the RIO driver allows users to configure their first | ||
943 | RTA as the ports numbered 504-511. We therefore need to allocate | ||
944 | the whole range. :-( -- REW */ | ||
945 | |||
946 | #define RI_SZ sizeof(struct rio_info) | ||
947 | #define HOST_SZ sizeof(struct Host) | ||
948 | #define PORT_SZ sizeof(struct Port *) | ||
949 | #define TMIO_SZ sizeof(struct termios *) | ||
950 | rio_dprintk (RIO_DEBUG_INIT, "getting : %d %d %d %d %d bytes\n", | ||
951 | RI_SZ, | ||
952 | RIO_HOSTS * HOST_SZ, | ||
953 | RIO_PORTS * PORT_SZ, | ||
954 | RIO_PORTS * TMIO_SZ, | ||
955 | RIO_PORTS * TMIO_SZ); | ||
956 | |||
957 | if (!(p = ckmalloc ( RI_SZ))) goto free0; | ||
958 | if (!(p->RIOHosts = ckmalloc (RIO_HOSTS * HOST_SZ))) goto free1; | ||
959 | if (!(p->RIOPortp = ckmalloc (RIO_PORTS * PORT_SZ))) goto free2; | ||
960 | p->RIOConf = RIOConf; | ||
961 | rio_dprintk (RIO_DEBUG_INIT, "Got : %p %p %p\n", | ||
962 | p, p->RIOHosts, p->RIOPortp); | ||
963 | |||
964 | #if 1 | ||
965 | for (i = 0; i < RIO_PORTS; i++) { | ||
966 | port = p->RIOPortp[i] = ckmalloc (sizeof (struct Port)); | ||
967 | if (!port) { | ||
968 | goto free6; | ||
969 | } | ||
970 | rio_dprintk (RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped); | ||
971 | port->PortNum = i; | ||
972 | port->gs.magic = RIO_MAGIC; | ||
973 | port->gs.close_delay = HZ/2; | ||
974 | port->gs.closing_wait = 30 * HZ; | ||
975 | port->gs.rd = &rio_real_driver; | ||
976 | spin_lock_init(&port->portSem); | ||
977 | /* | ||
978 | * Initializing wait queue | ||
979 | */ | ||
980 | init_waitqueue_head(&port->gs.open_wait); | ||
981 | init_waitqueue_head(&port->gs.close_wait); | ||
982 | } | ||
983 | #else | ||
984 | /* We could postpone initializing them to when they are configured. */ | ||
985 | #endif | ||
986 | |||
987 | |||
988 | |||
989 | if (rio_debug & RIO_DEBUG_INIT) { | ||
990 | my_hd (&rio_real_driver, sizeof (rio_real_driver)); | ||
991 | } | ||
992 | |||
993 | |||
994 | func_exit(); | ||
995 | return 0; | ||
996 | |||
997 | free6:for (i--;i>=0;i--) | ||
998 | kfree (p->RIOPortp[i]); | ||
999 | /*free5: | ||
1000 | free4: | ||
1001 | free3:*/kfree (p->RIOPortp); | ||
1002 | free2:kfree (p->RIOHosts); | ||
1003 | free1: | ||
1004 | rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", | ||
1005 | p, p->RIOHosts, p->RIOPortp); | ||
1006 | kfree(p); | ||
1007 | free0: | ||
1008 | return -ENOMEM; | ||
1009 | } | ||
1010 | |||
1011 | static void __exit rio_release_drivers(void) | ||
1012 | { | ||
1013 | func_enter(); | ||
1014 | tty_unregister_driver(rio_driver2); | ||
1015 | tty_unregister_driver(rio_driver); | ||
1016 | put_tty_driver(rio_driver2); | ||
1017 | put_tty_driver(rio_driver); | ||
1018 | func_exit(); | ||
1019 | } | ||
1020 | |||
1021 | |||
1022 | #ifdef CONFIG_PCI | ||
1023 | /* This was written for SX, but applies to RIO too... | ||
1024 | (including bugs....) | ||
1025 | |||
1026 | There is another bit besides Bit 17. Turning that bit off | ||
1027 | (on boards shipped with the fix in the eeprom) results in a | ||
1028 | hang on the next access to the card. | ||
1029 | */ | ||
1030 | |||
1031 | /******************************************************** | ||
1032 | * Setting bit 17 in the CNTRL register of the PLX 9050 * | ||
1033 | * chip forces a retry on writes while a read is pending.* | ||
1034 | * This is to prevent the card locking up on Intel Xeon * | ||
1035 | * multiprocessor systems with the NX chipset. -- NV * | ||
1036 | ********************************************************/ | ||
1037 | |||
1038 | /* Newer cards are produced with this bit set from the configuration | ||
1039 | EEprom. As the bit is read/write for the CPU, we can fix it here, | ||
1040 | if we detect that it isn't set correctly. -- REW */ | ||
1041 | |||
1042 | static void fix_rio_pci (struct pci_dev *pdev) | ||
1043 | { | ||
1044 | unsigned int hwbase; | ||
1045 | unsigned long rebase; | ||
1046 | unsigned int t; | ||
1047 | |||
1048 | #define CNTRL_REG_OFFSET 0x50 | ||
1049 | #define CNTRL_REG_GOODVALUE 0x18260000 | ||
1050 | |||
1051 | pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); | ||
1052 | hwbase &= PCI_BASE_ADDRESS_MEM_MASK; | ||
1053 | rebase = (ulong) ioremap(hwbase, 0x80); | ||
1054 | t = readl (rebase + CNTRL_REG_OFFSET); | ||
1055 | if (t != CNTRL_REG_GOODVALUE) { | ||
1056 | printk (KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", | ||
1057 | t, CNTRL_REG_GOODVALUE); | ||
1058 | writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); | ||
1059 | } | ||
1060 | iounmap((char*) rebase); | ||
1061 | } | ||
1062 | #endif | ||
1063 | |||
1064 | |||
1065 | static int __init rio_init(void) | ||
1066 | { | ||
1067 | int found = 0; | ||
1068 | int i; | ||
1069 | struct Host *hp; | ||
1070 | int retval; | ||
1071 | struct vpd_prom *vpdp; | ||
1072 | int okboard; | ||
1073 | |||
1074 | #ifdef CONFIG_PCI | ||
1075 | struct pci_dev *pdev = NULL; | ||
1076 | unsigned int tint; | ||
1077 | unsigned short tshort; | ||
1078 | #endif | ||
1079 | |||
1080 | func_enter(); | ||
1081 | rio_dprintk (RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", | ||
1082 | rio_debug); | ||
1083 | |||
1084 | if (abs ((long) (&rio_debug) - rio_debug) < 0x10000) { | ||
1085 | printk (KERN_WARNING "rio: rio_debug is an address, instead of a value. " | ||
1086 | "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug); | ||
1087 | rio_debug=-1; | ||
1088 | } | ||
1089 | |||
1090 | if (misc_register(&rio_fw_device) < 0) { | ||
1091 | printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n"); | ||
1092 | return -EIO; | ||
1093 | } | ||
1094 | |||
1095 | retval = rio_init_datastructures (); | ||
1096 | if (retval < 0) { | ||
1097 | misc_deregister(&rio_fw_device); | ||
1098 | return retval; | ||
1099 | } | ||
1100 | |||
1101 | #ifdef CONFIG_PCI | ||
1102 | /* First look for the JET devices: */ | ||
1103 | while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, | ||
1104 | PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, | ||
1105 | pdev))) { | ||
1106 | if (pci_enable_device(pdev)) continue; | ||
1107 | |||
1108 | /* Specialix has a whole bunch of cards with | ||
1109 | 0x2000 as the device ID. They say its because | ||
1110 | the standard requires it. Stupid standard. */ | ||
1111 | /* It seems that reading a word doesn't work reliably on 2.0. | ||
1112 | Also, reading a non-aligned dword doesn't work. So we read the | ||
1113 | whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID) | ||
1114 | ourselves */ | ||
1115 | /* I don't know why the define doesn't work, constant 0x2c does --REW */ | ||
1116 | pci_read_config_dword (pdev, 0x2c, &tint); | ||
1117 | tshort = (tint >> 16) & 0xffff; | ||
1118 | rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); | ||
1119 | if (tshort != 0x0100) { | ||
1120 | rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", | ||
1121 | tshort); | ||
1122 | continue; | ||
1123 | } | ||
1124 | rio_dprintk (RIO_DEBUG_PROBE, "cp1\n"); | ||
1125 | |||
1126 | pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint); | ||
1127 | |||
1128 | hp = &p->RIOHosts[p->RIONumHosts]; | ||
1129 | hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; | ||
1130 | hp->Ivec = pdev->irq; | ||
1131 | if (((1 << hp->Ivec) & rio_irqmask) == 0) | ||
1132 | hp->Ivec = 0; | ||
1133 | hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); | ||
1134 | hp->CardP = (struct DpRam *) hp->Caddr; | ||
1135 | hp->Type = RIO_PCI; | ||
1136 | hp->Copy = rio_pcicopy; | ||
1137 | hp->Mode = RIO_PCI_BOOT_FROM_RAM; | ||
1138 | spin_lock_init(&hp->HostLock); | ||
1139 | rio_reset_interrupt (hp); | ||
1140 | rio_start_card_running (hp); | ||
1141 | |||
1142 | rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", | ||
1143 | (void *)p->RIOHosts[p->RIONumHosts].PaddrP, | ||
1144 | p->RIOHosts[p->RIONumHosts].Caddr); | ||
1145 | if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP, | ||
1146 | p->RIOHosts[p->RIONumHosts].Caddr, | ||
1147 | RIO_PCI, 0 ) == RIO_SUCCESS) { | ||
1148 | rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n"); | ||
1149 | WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); | ||
1150 | p->RIOHosts[p->RIONumHosts].UniqueNum = | ||
1151 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)| | ||
1152 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)| | ||
1153 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)| | ||
1154 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24); | ||
1155 | rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", | ||
1156 | p->RIOHosts[p->RIONumHosts].UniqueNum); | ||
1157 | |||
1158 | fix_rio_pci (pdev); | ||
1159 | p->RIOLastPCISearch = RIO_SUCCESS; | ||
1160 | p->RIONumHosts++; | ||
1161 | found++; | ||
1162 | } else { | ||
1163 | iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr)); | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | /* Then look for the older PCI card.... : */ | ||
1168 | |||
1169 | /* These older PCI cards have problems (only byte-mode access is | ||
1170 | supported), which makes them a bit awkward to support. | ||
1171 | They also have problems sharing interrupts. Be careful. | ||
1172 | (The driver now refuses to share interrupts for these | ||
1173 | cards. This should be sufficient). | ||
1174 | */ | ||
1175 | |||
1176 | /* Then look for the older RIO/PCI devices: */ | ||
1177 | while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, | ||
1178 | PCI_DEVICE_ID_SPECIALIX_RIO, | ||
1179 | pdev))) { | ||
1180 | if (pci_enable_device(pdev)) continue; | ||
1181 | |||
1182 | #ifdef CONFIG_RIO_OLDPCI | ||
1183 | pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint); | ||
1184 | |||
1185 | hp = &p->RIOHosts[p->RIONumHosts]; | ||
1186 | hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; | ||
1187 | hp->Ivec = pdev->irq; | ||
1188 | if (((1 << hp->Ivec) & rio_irqmask) == 0) | ||
1189 | hp->Ivec = 0; | ||
1190 | hp->Ivec |= 0x8000; /* Mark as non-sharable */ | ||
1191 | hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); | ||
1192 | hp->CardP = (struct DpRam *) hp->Caddr; | ||
1193 | hp->Type = RIO_PCI; | ||
1194 | hp->Copy = rio_pcicopy; | ||
1195 | hp->Mode = RIO_PCI_BOOT_FROM_RAM; | ||
1196 | spin_lock_init(&hp->HostLock); | ||
1197 | |||
1198 | rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec); | ||
1199 | rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode); | ||
1200 | |||
1201 | rio_reset_interrupt (hp); | ||
1202 | rio_start_card_running (hp); | ||
1203 | rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", | ||
1204 | (void *)p->RIOHosts[p->RIONumHosts].PaddrP, | ||
1205 | p->RIOHosts[p->RIONumHosts].Caddr); | ||
1206 | if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP, | ||
1207 | p->RIOHosts[p->RIONumHosts].Caddr, | ||
1208 | RIO_PCI, 0 ) == RIO_SUCCESS) { | ||
1209 | WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); | ||
1210 | p->RIOHosts[p->RIONumHosts].UniqueNum = | ||
1211 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)| | ||
1212 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)| | ||
1213 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)| | ||
1214 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24); | ||
1215 | rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", | ||
1216 | p->RIOHosts[p->RIONumHosts].UniqueNum); | ||
1217 | |||
1218 | p->RIOLastPCISearch = RIO_SUCCESS; | ||
1219 | p->RIONumHosts++; | ||
1220 | found++; | ||
1221 | } else { | ||
1222 | iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr)); | ||
1223 | } | ||
1224 | #else | ||
1225 | printk (KERN_ERR "Found an older RIO PCI card, but the driver is not " | ||
1226 | "compiled to support it.\n"); | ||
1227 | #endif | ||
1228 | } | ||
1229 | #endif /* PCI */ | ||
1230 | |||
1231 | /* Now probe for ISA cards... */ | ||
1232 | for (i=0;i<NR_RIO_ADDRS;i++) { | ||
1233 | hp = &p->RIOHosts[p->RIONumHosts]; | ||
1234 | hp->PaddrP = rio_probe_addrs[i]; | ||
1235 | /* There was something about the IRQs of these cards. 'Forget what.--REW */ | ||
1236 | hp->Ivec = 0; | ||
1237 | hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); | ||
1238 | hp->CardP = (struct DpRam *) hp->Caddr; | ||
1239 | hp->Type = RIO_AT; | ||
1240 | hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL | ||
1241 | * -- YES! this is now a normal copy. Only the | ||
1242 | * old PCI card uses the special PCI copy. | ||
1243 | * Moreover, the ISA card will work with the | ||
1244 | * special PCI copy anyway. -- REW */ | ||
1245 | hp->Mode = 0; | ||
1246 | spin_lock_init(&hp->HostLock); | ||
1247 | |||
1248 | vpdp = get_VPD_PROM (hp); | ||
1249 | rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n"); | ||
1250 | okboard = 0; | ||
1251 | if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || | ||
1252 | (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || | ||
1253 | (strncmp (vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) { | ||
1254 | /* Board is present... */ | ||
1255 | if (RIOBoardTest (hp->PaddrP, | ||
1256 | hp->Caddr, RIO_AT, 0) == RIO_SUCCESS) { | ||
1257 | /* ... and feeling fine!!!! */ | ||
1258 | rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", | ||
1259 | p->RIOHosts[p->RIONumHosts].UniqueNum); | ||
1260 | if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) { | ||
1261 | rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", | ||
1262 | p->RIONumHosts, | ||
1263 | p->RIOHosts[p->RIONumHosts-1].UniqueNum); | ||
1264 | okboard++; | ||
1265 | found++; | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | if (!okboard) | ||
1270 | iounmap ((char*) (hp->Caddr)); | ||
1271 | } | ||
1272 | } | ||
1273 | |||
1274 | |||
1275 | for (i=0;i<p->RIONumHosts;i++) { | ||
1276 | hp = &p->RIOHosts[i]; | ||
1277 | if (hp->Ivec) { | ||
1278 | int mode = SA_SHIRQ; | ||
1279 | if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;} | ||
1280 | rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode); | ||
1281 | retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp); | ||
1282 | rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval); | ||
1283 | if (retval) { | ||
1284 | printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec); | ||
1285 | hp->Ivec = 0; | ||
1286 | } | ||
1287 | rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec); | ||
1288 | if (hp->Ivec != 0){ | ||
1289 | rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n"); | ||
1290 | hp->Mode |= RIO_PCI_INT_ENABLE; | ||
1291 | } else | ||
1292 | hp->Mode &= !RIO_PCI_INT_ENABLE; | ||
1293 | rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode); | ||
1294 | rio_start_card_running (hp); | ||
1295 | } | ||
1296 | /* Init the timer "always" to make sure that it can safely be | ||
1297 | deleted when we unload... */ | ||
1298 | |||
1299 | init_timer (&hp->timer); | ||
1300 | if (!hp->Ivec) { | ||
1301 | rio_dprintk (RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", | ||
1302 | rio_poll); | ||
1303 | hp->timer.data = i; | ||
1304 | hp->timer.function = rio_pollfunc; | ||
1305 | hp->timer.expires = jiffies + rio_poll; | ||
1306 | add_timer (&hp->timer); | ||
1307 | } | ||
1308 | } | ||
1309 | |||
1310 | if (found) { | ||
1311 | rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found); | ||
1312 | rio_init_drivers (); | ||
1313 | } else { | ||
1314 | /* deregister the misc device we created earlier */ | ||
1315 | misc_deregister(&rio_fw_device); | ||
1316 | } | ||
1317 | |||
1318 | func_exit(); | ||
1319 | return found?0:-EIO; | ||
1320 | } | ||
1321 | |||
1322 | |||
1323 | static void __exit rio_exit (void) | ||
1324 | { | ||
1325 | int i; | ||
1326 | struct Host *hp; | ||
1327 | |||
1328 | func_enter(); | ||
1329 | |||
1330 | for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) { | ||
1331 | RIOHostReset (hp->Type, hp->CardP, hp->Slot); | ||
1332 | if (hp->Ivec) { | ||
1333 | free_irq (hp->Ivec, hp); | ||
1334 | rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec); | ||
1335 | } | ||
1336 | /* It is safe/allowed to del_timer a non-active timer */ | ||
1337 | del_timer (&hp->timer); | ||
1338 | } | ||
1339 | |||
1340 | if (misc_deregister(&rio_fw_device) < 0) { | ||
1341 | printk (KERN_INFO "rio: couldn't deregister control-device\n"); | ||
1342 | } | ||
1343 | |||
1344 | |||
1345 | rio_dprintk (RIO_DEBUG_CLEANUP, "Cleaning up drivers\n"); | ||
1346 | |||
1347 | rio_release_drivers (); | ||
1348 | |||
1349 | /* Release dynamically allocated memory */ | ||
1350 | kfree (p->RIOPortp); | ||
1351 | kfree (p->RIOHosts); | ||
1352 | kfree (p); | ||
1353 | |||
1354 | func_exit(); | ||
1355 | } | ||
1356 | |||
1357 | module_init(rio_init); | ||
1358 | module_exit(rio_exit); | ||
1359 | |||
1360 | /* | ||
1361 | * Anybody who knows why this doesn't work for me, please tell me -- REW. | ||
1362 | * Snatched from scsi.c (fixed one spelling error): | ||
1363 | * Overrides for Emacs so that we follow Linus' tabbing style. | ||
1364 | * Emacs will notice this stuff at the end of the file and automatically | ||
1365 | * adjust the settings for this buffer only. This must remain at the end | ||
1366 | * of the file. | ||
1367 | * --------------------------------------------------------------------------- | ||
1368 | * Local Variables: | ||
1369 | * c-indent-level: 4 | ||
1370 | * c-brace-imaginary-offset: 0 | ||
1371 | * c-brace-offset: -4 | ||
1372 | * c-argdecl-indent: 4 | ||
1373 | * c-label-offset: -4 | ||
1374 | * c-continued-statement-offset: 4 | ||
1375 | * c-continued-brace-offset: 0 | ||
1376 | * indent-tabs-mode: nil | ||
1377 | * tab-width: 8 | ||
1378 | * End: | ||
1379 | */ | ||
1380 | |||
diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h new file mode 100644 index 000000000000..1fba19d5b66a --- /dev/null +++ b/drivers/char/rio/rio_linux.h | |||
@@ -0,0 +1,187 @@ | |||
1 | |||
2 | /* | ||
3 | * rio_linux.h | ||
4 | * | ||
5 | * Copyright (C) 1998,1999,2000 R.E.Wolff@BitWizard.nl | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | * RIO serial driver. | ||
22 | * | ||
23 | * Version 1.0 -- July, 1999. | ||
24 | * | ||
25 | */ | ||
26 | #include <linux/config.h> | ||
27 | |||
28 | #define RIO_NBOARDS 4 | ||
29 | #define RIO_PORTSPERBOARD 128 | ||
30 | #define RIO_NPORTS (RIO_NBOARDS * RIO_PORTSPERBOARD) | ||
31 | |||
32 | #define MODEM_SUPPORT | ||
33 | |||
34 | #ifdef __KERNEL__ | ||
35 | |||
36 | #define RIO_MAGIC 0x12345678 | ||
37 | |||
38 | |||
39 | struct vpd_prom { | ||
40 | unsigned short id; | ||
41 | char hwrev; | ||
42 | char hwass; | ||
43 | int uniqid; | ||
44 | char myear; | ||
45 | char mweek; | ||
46 | char hw_feature[5]; | ||
47 | char oem_id; | ||
48 | char identifier[16]; | ||
49 | }; | ||
50 | |||
51 | |||
52 | #define RIO_DEBUG_ALL 0xffffffff | ||
53 | |||
54 | #define O_OTHER(tty) \ | ||
55 | ((O_OLCUC(tty)) ||\ | ||
56 | (O_ONLCR(tty)) ||\ | ||
57 | (O_OCRNL(tty)) ||\ | ||
58 | (O_ONOCR(tty)) ||\ | ||
59 | (O_ONLRET(tty)) ||\ | ||
60 | (O_OFILL(tty)) ||\ | ||
61 | (O_OFDEL(tty)) ||\ | ||
62 | (O_NLDLY(tty)) ||\ | ||
63 | (O_CRDLY(tty)) ||\ | ||
64 | (O_TABDLY(tty)) ||\ | ||
65 | (O_BSDLY(tty)) ||\ | ||
66 | (O_VTDLY(tty)) ||\ | ||
67 | (O_FFDLY(tty))) | ||
68 | |||
69 | /* Same for input. */ | ||
70 | #define I_OTHER(tty) \ | ||
71 | ((I_INLCR(tty)) ||\ | ||
72 | (I_IGNCR(tty)) ||\ | ||
73 | (I_ICRNL(tty)) ||\ | ||
74 | (I_IUCLC(tty)) ||\ | ||
75 | (L_ISIG(tty))) | ||
76 | |||
77 | |||
78 | #endif /* __KERNEL__ */ | ||
79 | |||
80 | |||
81 | #define RIO_BOARD_INTR_LOCK 1 | ||
82 | |||
83 | |||
84 | #ifndef RIOCTL_MISC_MINOR | ||
85 | /* Allow others to gather this into "major.h" or something like that */ | ||
86 | #define RIOCTL_MISC_MINOR 169 | ||
87 | #endif | ||
88 | |||
89 | |||
90 | /* Allow us to debug "in the field" without requiring clients to | ||
91 | recompile.... */ | ||
92 | #if 1 | ||
93 | #define rio_spin_lock_irqsave(sem, flags) do { \ | ||
94 | rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \ | ||
95 | sem, __FILE__, __LINE__);\ | ||
96 | spin_lock_irqsave(sem, flags);\ | ||
97 | } while (0) | ||
98 | |||
99 | #define rio_spin_unlock_irqrestore(sem, flags) do { \ | ||
100 | rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\ | ||
101 | sem, __FILE__, __LINE__);\ | ||
102 | spin_unlock_irqrestore(sem, flags);\ | ||
103 | } while (0) | ||
104 | |||
105 | #define rio_spin_lock(sem) do { \ | ||
106 | rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\ | ||
107 | sem, __FILE__, __LINE__);\ | ||
108 | spin_lock(sem);\ | ||
109 | } while (0) | ||
110 | |||
111 | #define rio_spin_unlock(sem) do { \ | ||
112 | rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlock: %p %s:%d\n",\ | ||
113 | sem, __FILE__, __LINE__);\ | ||
114 | spin_unlock(sem);\ | ||
115 | } while (0) | ||
116 | #else | ||
117 | #define rio_spin_lock_irqsave(sem, flags) \ | ||
118 | spin_lock_irqsave(sem, flags) | ||
119 | |||
120 | #define rio_spin_unlock_irqrestore(sem, flags) \ | ||
121 | spin_unlock_irqrestore(sem, flags) | ||
122 | |||
123 | #define rio_spin_lock(sem) \ | ||
124 | spin_lock(sem) | ||
125 | |||
126 | #define rio_spin_unlock(sem) \ | ||
127 | spin_unlock(sem) | ||
128 | |||
129 | #endif | ||
130 | |||
131 | |||
132 | |||
133 | #ifdef CONFIG_RIO_OLDPCI | ||
134 | static inline void *rio_memcpy_toio (void *dummy, void *dest, void *source, int n) | ||
135 | { | ||
136 | char *dst = dest; | ||
137 | char *src = source; | ||
138 | |||
139 | while (n--) { | ||
140 | writeb (*src++, dst++); | ||
141 | (void) readb (dummy); | ||
142 | } | ||
143 | |||
144 | return dest; | ||
145 | } | ||
146 | |||
147 | |||
148 | static inline void *rio_memcpy_fromio (void *dest, void *source, int n) | ||
149 | { | ||
150 | char *dst = dest; | ||
151 | char *src = source; | ||
152 | |||
153 | while (n--) | ||
154 | *dst++ = readb (src++); | ||
155 | |||
156 | return dest; | ||
157 | } | ||
158 | |||
159 | #else | ||
160 | #define rio_memcpy_toio(dummy,dest,source,n) memcpy_toio(dest, source, n) | ||
161 | #define rio_memcpy_fromio memcpy_fromio | ||
162 | #endif | ||
163 | |||
164 | #define DEBUG 1 | ||
165 | |||
166 | |||
167 | /* | ||
168 | This driver can spew a whole lot of debugging output at you. If you | ||
169 | need maximum performance, you should disable the DEBUG define. To | ||
170 | aid in debugging in the field, I'm leaving the compile-time debug | ||
171 | features enabled, and disable them "runtime". That allows me to | ||
172 | instruct people with problems to enable debugging without requiring | ||
173 | them to recompile... | ||
174 | */ | ||
175 | |||
176 | #ifdef DEBUG | ||
177 | #define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0) | ||
178 | #define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __FUNCTION__) | ||
179 | #define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit %s\n", __FUNCTION__) | ||
180 | #define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__FUNCTION__, port->line) | ||
181 | #else | ||
182 | #define rio_dprintk(f, str...) /* nothing */ | ||
183 | #define func_enter() | ||
184 | #define func_exit() | ||
185 | #define func_enter2() | ||
186 | #endif | ||
187 | |||
diff --git a/drivers/char/rio/rioboard.h b/drivers/char/rio/rioboard.h new file mode 100644 index 000000000000..cc6ac6a98f65 --- /dev/null +++ b/drivers/char/rio/rioboard.h | |||
@@ -0,0 +1,281 @@ | |||
1 | /************************************************************************/ | ||
2 | /* */ | ||
3 | /* Title : RIO Host Card Hardware Definitions */ | ||
4 | /* */ | ||
5 | /* Author : N.P.Vassallo */ | ||
6 | /* */ | ||
7 | /* Creation : 26th April 1999 */ | ||
8 | /* */ | ||
9 | /* Version : 1.0.0 */ | ||
10 | /* */ | ||
11 | /* Copyright : (c) Specialix International Ltd. 1999 * | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | * */ | ||
27 | /* Description : Prototypes, structures and definitions */ | ||
28 | /* describing the RIO board hardware */ | ||
29 | /* */ | ||
30 | /************************************************************************/ | ||
31 | |||
32 | /* History... | ||
33 | |||
34 | 1.0.0 26/04/99 NPV Creation. | ||
35 | |||
36 | */ | ||
37 | |||
38 | #ifndef _rioboard_h /* If RIOBOARD.H not already defined */ | ||
39 | #define _rioboard_h 1 | ||
40 | |||
41 | /***************************************************************************** | ||
42 | *********************** *********************** | ||
43 | *********************** Hardware Control Registers *********************** | ||
44 | *********************** *********************** | ||
45 | *****************************************************************************/ | ||
46 | |||
47 | /* Hardware Registers... */ | ||
48 | |||
49 | #define RIO_REG_BASE 0x7C00 /* Base of control registers */ | ||
50 | |||
51 | #define RIO_CONFIG RIO_REG_BASE + 0x0000 /* WRITE: Configuration Register */ | ||
52 | #define RIO_INTSET RIO_REG_BASE + 0x0080 /* WRITE: Interrupt Set */ | ||
53 | #define RIO_RESET RIO_REG_BASE + 0x0100 /* WRITE: Host Reset */ | ||
54 | #define RIO_INTRESET RIO_REG_BASE + 0x0180 /* WRITE: Interrupt Reset */ | ||
55 | |||
56 | #define RIO_VPD_ROM RIO_REG_BASE + 0x0000 /* READ: Vital Product Data ROM */ | ||
57 | #define RIO_INTSTAT RIO_REG_BASE + 0x0080 /* READ: Interrupt Status (Jet boards only) */ | ||
58 | #define RIO_RESETSTAT RIO_REG_BASE + 0x0100 /* READ: Reset Status (Jet boards only) */ | ||
59 | |||
60 | /* RIO_VPD_ROM definitions... */ | ||
61 | #define VPD_SLX_ID1 0x00 /* READ: Specialix Identifier #1 */ | ||
62 | #define VPD_SLX_ID2 0x01 /* READ: Specialix Identifier #2 */ | ||
63 | #define VPD_HW_REV 0x02 /* READ: Hardware Revision */ | ||
64 | #define VPD_HW_ASSEM 0x03 /* READ: Hardware Assembly Level */ | ||
65 | #define VPD_UNIQUEID4 0x04 /* READ: Unique Identifier #4 */ | ||
66 | #define VPD_UNIQUEID3 0x05 /* READ: Unique Identifier #3 */ | ||
67 | #define VPD_UNIQUEID2 0x06 /* READ: Unique Identifier #2 */ | ||
68 | #define VPD_UNIQUEID1 0x07 /* READ: Unique Identifier #1 */ | ||
69 | #define VPD_MANU_YEAR 0x08 /* READ: Year Of Manufacture (0 = 1970) */ | ||
70 | #define VPD_MANU_WEEK 0x09 /* READ: Week Of Manufacture (0 = week 1 Jan) */ | ||
71 | #define VPD_HWFEATURE1 0x0A /* READ: Hardware Feature Byte 1 */ | ||
72 | #define VPD_HWFEATURE2 0x0B /* READ: Hardware Feature Byte 2 */ | ||
73 | #define VPD_HWFEATURE3 0x0C /* READ: Hardware Feature Byte 3 */ | ||
74 | #define VPD_HWFEATURE4 0x0D /* READ: Hardware Feature Byte 4 */ | ||
75 | #define VPD_HWFEATURE5 0x0E /* READ: Hardware Feature Byte 5 */ | ||
76 | #define VPD_OEMID 0x0F /* READ: OEM Identifier */ | ||
77 | #define VPD_IDENT 0x10 /* READ: Identifier string (16 bytes) */ | ||
78 | #define VPD_IDENT_LEN 0x10 | ||
79 | |||
80 | /* VPD ROM Definitions... */ | ||
81 | #define SLX_ID1 0x4D | ||
82 | #define SLX_ID2 0x98 | ||
83 | |||
84 | #define PRODUCT_ID(a) ((a>>4)&0xF) /* Use to obtain Product ID from VPD_UNIQUEID1 */ | ||
85 | |||
86 | #define ID_SX_ISA 0x2 | ||
87 | #define ID_RIO_EISA 0x3 | ||
88 | #define ID_SX_PCI 0x5 | ||
89 | #define ID_SX_EISA 0x7 | ||
90 | #define ID_RIO_RTA16 0x9 | ||
91 | #define ID_RIO_ISA 0xA | ||
92 | #define ID_RIO_MCA 0xB | ||
93 | #define ID_RIO_SBUS 0xC | ||
94 | #define ID_RIO_PCI 0xD | ||
95 | #define ID_RIO_RTA8 0xE | ||
96 | |||
97 | /* Transputer bootstrap definitions... */ | ||
98 | |||
99 | #define BOOTLOADADDR (0x8000 - 6) | ||
100 | #define BOOTINDICATE (0x8000 - 2) | ||
101 | |||
102 | /* Firmware load position... */ | ||
103 | |||
104 | #define FIRMWARELOADADDR 0x7C00 /* Firmware is loaded _before_ this address */ | ||
105 | |||
106 | /***************************************************************************** | ||
107 | ***************************** ***************************** | ||
108 | ***************************** RIO (Rev1) ISA ***************************** | ||
109 | ***************************** ***************************** | ||
110 | *****************************************************************************/ | ||
111 | |||
112 | /* Control Register Definitions... */ | ||
113 | #define RIO_ISA_IDENT "JBJGPGGHINSMJPJR" | ||
114 | |||
115 | #define RIO_ISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ | ||
116 | #define RIO_ISA_CFG_BUSENABLE 0x02 /* Enable processor bus */ | ||
117 | #define RIO_ISA_CFG_IRQMASK 0x30 /* Interrupt mask */ | ||
118 | #define RIO_ISA_CFG_IRQ12 0x10 /* Interrupt Level 12 */ | ||
119 | #define RIO_ISA_CFG_IRQ11 0x20 /* Interrupt Level 11 */ | ||
120 | #define RIO_ISA_CFG_IRQ9 0x30 /* Interrupt Level 9 */ | ||
121 | #define RIO_ISA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ | ||
122 | #define RIO_ISA_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */ | ||
123 | |||
124 | /***************************************************************************** | ||
125 | ***************************** ***************************** | ||
126 | ***************************** RIO (Rev2) ISA ***************************** | ||
127 | ***************************** ***************************** | ||
128 | *****************************************************************************/ | ||
129 | |||
130 | /* Control Register Definitions... */ | ||
131 | #define RIO_ISA2_IDENT "JBJGPGGHINSMJPJR" | ||
132 | |||
133 | #define RIO_ISA2_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ | ||
134 | #define RIO_ISA2_CFG_BUSENABLE 0x02 /* Enable processor bus */ | ||
135 | #define RIO_ISA2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ | ||
136 | #define RIO_ISA2_CFG_16BIT 0x08 /* 16bit mode, else 8bit */ | ||
137 | #define RIO_ISA2_CFG_IRQMASK 0x30 /* Interrupt mask */ | ||
138 | #define RIO_ISA2_CFG_IRQ15 0x00 /* Interrupt Level 15 */ | ||
139 | #define RIO_ISA2_CFG_IRQ12 0x10 /* Interrupt Level 12 */ | ||
140 | #define RIO_ISA2_CFG_IRQ11 0x20 /* Interrupt Level 11 */ | ||
141 | #define RIO_ISA2_CFG_IRQ9 0x30 /* Interrupt Level 9 */ | ||
142 | #define RIO_ISA2_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ | ||
143 | #define RIO_ISA2_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */ | ||
144 | |||
145 | /***************************************************************************** | ||
146 | ***************************** ****************************** | ||
147 | ***************************** RIO (Jet) ISA ****************************** | ||
148 | ***************************** ****************************** | ||
149 | *****************************************************************************/ | ||
150 | |||
151 | /* Control Register Definitions... */ | ||
152 | #define RIO_ISA3_IDENT "JET HOST BY KEV#" | ||
153 | |||
154 | #define RIO_ISA3_CFG_BUSENABLE 0x02 /* Enable processor bus */ | ||
155 | #define RIO_ISA3_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ | ||
156 | #define RIO_ISA32_CFG_IRQMASK 0xF30 /* Interrupt mask */ | ||
157 | #define RIO_ISA3_CFG_IRQ15 0xF0 /* Interrupt Level 15 */ | ||
158 | #define RIO_ISA3_CFG_IRQ12 0xC0 /* Interrupt Level 12 */ | ||
159 | #define RIO_ISA3_CFG_IRQ11 0xB0 /* Interrupt Level 11 */ | ||
160 | #define RIO_ISA3_CFG_IRQ10 0xA0 /* Interrupt Level 10 */ | ||
161 | #define RIO_ISA3_CFG_IRQ9 0x90 /* Interrupt Level 9 */ | ||
162 | |||
163 | /***************************************************************************** | ||
164 | ********************************* ******************************** | ||
165 | ********************************* RIO MCA ******************************** | ||
166 | ********************************* ******************************** | ||
167 | *****************************************************************************/ | ||
168 | |||
169 | /* Control Register Definitions... */ | ||
170 | #define RIO_MCA_IDENT "JBJGPGGHINSMJPJR" | ||
171 | |||
172 | #define RIO_MCA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ | ||
173 | #define RIO_MCA_CFG_BUSENABLE 0x02 /* Enable processor bus */ | ||
174 | #define RIO_MCA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ | ||
175 | |||
176 | /***************************************************************************** | ||
177 | ******************************** ******************************** | ||
178 | ******************************** RIO EISA ******************************** | ||
179 | ******************************** ******************************** | ||
180 | *****************************************************************************/ | ||
181 | |||
182 | /* EISA Configuration Space Definitions... */ | ||
183 | #define EISA_PRODUCT_ID1 0xC80 | ||
184 | #define EISA_PRODUCT_ID2 0xC81 | ||
185 | #define EISA_PRODUCT_NUMBER 0xC82 | ||
186 | #define EISA_REVISION_NUMBER 0xC83 | ||
187 | #define EISA_CARD_ENABLE 0xC84 | ||
188 | #define EISA_VPD_UNIQUEID4 0xC88 /* READ: Unique Identifier #4 */ | ||
189 | #define EISA_VPD_UNIQUEID3 0xC8A /* READ: Unique Identifier #3 */ | ||
190 | #define EISA_VPD_UNIQUEID2 0xC90 /* READ: Unique Identifier #2 */ | ||
191 | #define EISA_VPD_UNIQUEID1 0xC92 /* READ: Unique Identifier #1 */ | ||
192 | #define EISA_VPD_MANU_YEAR 0xC98 /* READ: Year Of Manufacture (0 = 1970) */ | ||
193 | #define EISA_VPD_MANU_WEEK 0xC9A /* READ: Week Of Manufacture (0 = week 1 Jan) */ | ||
194 | #define EISA_MEM_ADDR_23_16 0xC00 | ||
195 | #define EISA_MEM_ADDR_31_24 0xC01 | ||
196 | #define EISA_RIO_CONFIG 0xC02 /* WRITE: Configuration Register */ | ||
197 | #define EISA_RIO_INTSET 0xC03 /* WRITE: Interrupt Set */ | ||
198 | #define EISA_RIO_INTRESET 0xC03 /* READ: Interrupt Reset */ | ||
199 | |||
200 | /* Control Register Definitions... */ | ||
201 | #define RIO_EISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ | ||
202 | #define RIO_EISA_CFG_LINK20 0x02 /* 20Mbps link, else 10Mbps */ | ||
203 | #define RIO_EISA_CFG_BUSENABLE 0x04 /* Enable processor bus */ | ||
204 | #define RIO_EISA_CFG_PROCRUN 0x08 /* Processor running, else reset */ | ||
205 | #define RIO_EISA_CFG_IRQMASK 0xF0 /* Interrupt mask */ | ||
206 | #define RIO_EISA_CFG_IRQ15 0xF0 /* Interrupt Level 15 */ | ||
207 | #define RIO_EISA_CFG_IRQ14 0xE0 /* Interrupt Level 14 */ | ||
208 | #define RIO_EISA_CFG_IRQ12 0xC0 /* Interrupt Level 12 */ | ||
209 | #define RIO_EISA_CFG_IRQ11 0xB0 /* Interrupt Level 11 */ | ||
210 | #define RIO_EISA_CFG_IRQ10 0xA0 /* Interrupt Level 10 */ | ||
211 | #define RIO_EISA_CFG_IRQ9 0x90 /* Interrupt Level 9 */ | ||
212 | #define RIO_EISA_CFG_IRQ7 0x70 /* Interrupt Level 7 */ | ||
213 | #define RIO_EISA_CFG_IRQ6 0x60 /* Interrupt Level 6 */ | ||
214 | #define RIO_EISA_CFG_IRQ5 0x50 /* Interrupt Level 5 */ | ||
215 | #define RIO_EISA_CFG_IRQ4 0x40 /* Interrupt Level 4 */ | ||
216 | #define RIO_EISA_CFG_IRQ3 0x30 /* Interrupt Level 3 */ | ||
217 | |||
218 | /***************************************************************************** | ||
219 | ******************************** ******************************** | ||
220 | ******************************** RIO SBus ******************************** | ||
221 | ******************************** ******************************** | ||
222 | *****************************************************************************/ | ||
223 | |||
224 | /* Control Register Definitions... */ | ||
225 | #define RIO_SBUS_IDENT "JBPGK#\0\0\0\0\0\0\0\0\0\0" | ||
226 | |||
227 | #define RIO_SBUS_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ | ||
228 | #define RIO_SBUS_CFG_BUSENABLE 0x02 /* Enable processor bus */ | ||
229 | #define RIO_SBUS_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ | ||
230 | #define RIO_SBUS_CFG_IRQMASK 0x38 /* Interrupt mask */ | ||
231 | #define RIO_SBUS_CFG_IRQNONE 0x00 /* No Interrupt */ | ||
232 | #define RIO_SBUS_CFG_IRQ7 0x38 /* Interrupt Level 7 */ | ||
233 | #define RIO_SBUS_CFG_IRQ6 0x30 /* Interrupt Level 6 */ | ||
234 | #define RIO_SBUS_CFG_IRQ5 0x28 /* Interrupt Level 5 */ | ||
235 | #define RIO_SBUS_CFG_IRQ4 0x20 /* Interrupt Level 4 */ | ||
236 | #define RIO_SBUS_CFG_IRQ3 0x18 /* Interrupt Level 3 */ | ||
237 | #define RIO_SBUS_CFG_IRQ2 0x10 /* Interrupt Level 2 */ | ||
238 | #define RIO_SBUS_CFG_IRQ1 0x08 /* Interrupt Level 1 */ | ||
239 | #define RIO_SBUS_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ | ||
240 | #define RIO_SBUS_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */ | ||
241 | |||
242 | /***************************************************************************** | ||
243 | ********************************* ******************************** | ||
244 | ********************************* RIO PCI ******************************** | ||
245 | ********************************* ******************************** | ||
246 | *****************************************************************************/ | ||
247 | |||
248 | /* Control Register Definitions... */ | ||
249 | #define RIO_PCI_IDENT "ECDDPGJGJHJRGSK#" | ||
250 | |||
251 | #define RIO_PCI_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */ | ||
252 | #define RIO_PCI_CFG_BUSENABLE 0x02 /* Enable processor bus */ | ||
253 | #define RIO_PCI_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ | ||
254 | #define RIO_PCI_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */ | ||
255 | #define RIO_PCI_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */ | ||
256 | |||
257 | /* PCI Definitions... */ | ||
258 | #define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */ | ||
259 | #define SPX_DEVICE_ID 0x8000 /* RIO bridge boards */ | ||
260 | #define SPX_PLXDEVICE_ID 0x2000 /* PLX bridge boards */ | ||
261 | #define SPX_SUB_VENDOR_ID SPX_VENDOR_ID /* Same as vendor id */ | ||
262 | #define RIO_SUB_SYS_ID 0x0800 /* RIO PCI board */ | ||
263 | |||
264 | /***************************************************************************** | ||
265 | ***************************** ****************************** | ||
266 | ***************************** RIO (Jet) PCI ****************************** | ||
267 | ***************************** ****************************** | ||
268 | *****************************************************************************/ | ||
269 | |||
270 | /* Control Register Definitions... */ | ||
271 | #define RIO_PCI2_IDENT "JET HOST BY KEV#" | ||
272 | |||
273 | #define RIO_PCI2_CFG_BUSENABLE 0x02 /* Enable processor bus */ | ||
274 | #define RIO_PCI2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */ | ||
275 | |||
276 | /* PCI Definitions... */ | ||
277 | #define RIO2_SUB_SYS_ID 0x0100 /* RIO (Jet) PCI board */ | ||
278 | |||
279 | #endif /*_rioboard_h */ | ||
280 | |||
281 | /* End of RIOBOARD.H */ | ||
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c new file mode 100644 index 000000000000..a8be11dfcba3 --- /dev/null +++ b/drivers/char/rio/rioboot.c | |||
@@ -0,0 +1,1360 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : rioboot.c | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 10:33:36 | ||
26 | ** Retrieved : 11/6/98 10:33:48 | ||
27 | ** | ||
28 | ** ident @(#)rioboot.c 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifdef SCCS_LABELS | ||
34 | static char *_rioboot_c_sccs_ = "@(#)rioboot.c 1.3"; | ||
35 | #endif | ||
36 | |||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/errno.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/string.h> | ||
44 | #include <asm/semaphore.h> | ||
45 | |||
46 | |||
47 | #include <linux/termios.h> | ||
48 | #include <linux/serial.h> | ||
49 | |||
50 | #include <linux/generic_serial.h> | ||
51 | |||
52 | |||
53 | |||
54 | #include "linux_compat.h" | ||
55 | #include "rio_linux.h" | ||
56 | #include "typdef.h" | ||
57 | #include "pkt.h" | ||
58 | #include "daemon.h" | ||
59 | #include "rio.h" | ||
60 | #include "riospace.h" | ||
61 | #include "top.h" | ||
62 | #include "cmdpkt.h" | ||
63 | #include "map.h" | ||
64 | #include "riotypes.h" | ||
65 | #include "rup.h" | ||
66 | #include "port.h" | ||
67 | #include "riodrvr.h" | ||
68 | #include "rioinfo.h" | ||
69 | #include "func.h" | ||
70 | #include "errors.h" | ||
71 | #include "pci.h" | ||
72 | |||
73 | #include "parmmap.h" | ||
74 | #include "unixrup.h" | ||
75 | #include "board.h" | ||
76 | #include "host.h" | ||
77 | #include "error.h" | ||
78 | #include "phb.h" | ||
79 | #include "link.h" | ||
80 | #include "cmdblk.h" | ||
81 | #include "route.h" | ||
82 | |||
83 | static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP ); | ||
84 | |||
85 | static uchar | ||
86 | RIOAtVec2Ctrl[] = | ||
87 | { | ||
88 | /* 0 */ INTERRUPT_DISABLE, | ||
89 | /* 1 */ INTERRUPT_DISABLE, | ||
90 | /* 2 */ INTERRUPT_DISABLE, | ||
91 | /* 3 */ INTERRUPT_DISABLE, | ||
92 | /* 4 */ INTERRUPT_DISABLE, | ||
93 | /* 5 */ INTERRUPT_DISABLE, | ||
94 | /* 6 */ INTERRUPT_DISABLE, | ||
95 | /* 7 */ INTERRUPT_DISABLE, | ||
96 | /* 8 */ INTERRUPT_DISABLE, | ||
97 | /* 9 */ IRQ_9|INTERRUPT_ENABLE, | ||
98 | /* 10 */ INTERRUPT_DISABLE, | ||
99 | /* 11 */ IRQ_11|INTERRUPT_ENABLE, | ||
100 | /* 12 */ IRQ_12|INTERRUPT_ENABLE, | ||
101 | /* 13 */ INTERRUPT_DISABLE, | ||
102 | /* 14 */ INTERRUPT_DISABLE, | ||
103 | /* 15 */ IRQ_15|INTERRUPT_ENABLE | ||
104 | }; | ||
105 | |||
106 | /* | ||
107 | ** Load in the RTA boot code. | ||
108 | */ | ||
109 | int | ||
110 | RIOBootCodeRTA(p, rbp) | ||
111 | struct rio_info * p; | ||
112 | struct DownLoad * rbp; | ||
113 | { | ||
114 | int offset; | ||
115 | |||
116 | func_enter (); | ||
117 | |||
118 | /* Linux doesn't allow you to disable interrupts during a | ||
119 | "copyin". (Crash when a pagefault occurs). */ | ||
120 | /* disable(oldspl); */ | ||
121 | |||
122 | rio_dprintk (RIO_DEBUG_BOOT, "Data at user address 0x%x\n",(int)rbp->DataP); | ||
123 | |||
124 | /* | ||
125 | ** Check that we have set asside enough memory for this | ||
126 | */ | ||
127 | if ( rbp->Count > SIXTY_FOUR_K ) { | ||
128 | rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n"); | ||
129 | p->RIOError.Error = HOST_FILE_TOO_LARGE; | ||
130 | /* restore(oldspl); */ | ||
131 | func_exit (); | ||
132 | return -ENOMEM; | ||
133 | } | ||
134 | |||
135 | if ( p->RIOBooting ) { | ||
136 | rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n"); | ||
137 | p->RIOError.Error = BOOT_IN_PROGRESS; | ||
138 | /* restore(oldspl); */ | ||
139 | func_exit (); | ||
140 | return -EBUSY; | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary, | ||
145 | ** so calculate how far we have to move the data up the buffer | ||
146 | ** to achieve this. | ||
147 | */ | ||
148 | offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % | ||
149 | RTA_BOOT_DATA_SIZE; | ||
150 | |||
151 | /* | ||
152 | ** Be clean, and clear the 'unused' portion of the boot buffer, | ||
153 | ** because it will (eventually) be part of the Rta run time environment | ||
154 | ** and so should be zeroed. | ||
155 | */ | ||
156 | bzero( (caddr_t)p->RIOBootPackets, offset ); | ||
157 | |||
158 | /* | ||
159 | ** Copy the data from user space. | ||
160 | */ | ||
161 | |||
162 | if ( copyin((int)rbp->DataP,((caddr_t)(p->RIOBootPackets))+offset, | ||
163 | rbp->Count) ==COPYFAIL ) { | ||
164 | rio_dprintk (RIO_DEBUG_BOOT, "Bad data copy from user space\n"); | ||
165 | p->RIOError.Error = COPYIN_FAILED; | ||
166 | /* restore(oldspl); */ | ||
167 | func_exit (); | ||
168 | return -EFAULT; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | ** Make sure that our copy of the size includes that offset we discussed | ||
173 | ** earlier. | ||
174 | */ | ||
175 | p->RIONumBootPkts = (rbp->Count+offset)/RTA_BOOT_DATA_SIZE; | ||
176 | p->RIOBootCount = rbp->Count; | ||
177 | |||
178 | /* restore(oldspl); */ | ||
179 | func_exit(); | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | void rio_start_card_running (struct Host * HostP) | ||
184 | { | ||
185 | func_enter (); | ||
186 | |||
187 | switch ( HostP->Type ) { | ||
188 | case RIO_AT: | ||
189 | rio_dprintk (RIO_DEBUG_BOOT, "Start ISA card running\n"); | ||
190 | WBYTE(HostP->Control, | ||
191 | BOOT_FROM_RAM | EXTERNAL_BUS_ON | ||
192 | | HostP->Mode | ||
193 | | RIOAtVec2Ctrl[HostP->Ivec & 0xF] ); | ||
194 | break; | ||
195 | |||
196 | #ifdef FUTURE_RELEASE | ||
197 | case RIO_MCA: | ||
198 | /* | ||
199 | ** MCA handles IRQ vectors differently, so we don't write | ||
200 | ** them to this register. | ||
201 | */ | ||
202 | rio_dprintk (RIO_DEBUG_BOOT, "Start MCA card running\n"); | ||
203 | WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode); | ||
204 | break; | ||
205 | |||
206 | case RIO_EISA: | ||
207 | /* | ||
208 | ** EISA is totally different and expects OUTBZs to turn it on. | ||
209 | */ | ||
210 | rio_dprintk (RIO_DEBUG_BOOT, "Start EISA card running\n"); | ||
211 | OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM ); | ||
212 | break; | ||
213 | #endif | ||
214 | |||
215 | case RIO_PCI: | ||
216 | /* | ||
217 | ** PCI is much the same as MCA. Everything is once again memory | ||
218 | ** mapped, so we are writing to memory registers instead of io | ||
219 | ** ports. | ||
220 | */ | ||
221 | rio_dprintk (RIO_DEBUG_BOOT, "Start PCI card running\n"); | ||
222 | WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode); | ||
223 | break; | ||
224 | default: | ||
225 | rio_dprintk (RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type); | ||
226 | break; | ||
227 | } | ||
228 | /* | ||
229 | printk (KERN_INFO "Done with starting the card\n"); | ||
230 | func_exit (); | ||
231 | */ | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | ** Load in the host boot code - load it directly onto all halted hosts | ||
237 | ** of the correct type. | ||
238 | ** | ||
239 | ** Put your rubber pants on before messing with this code - even the magic | ||
240 | ** numbers have trouble understanding what they are doing here. | ||
241 | */ | ||
242 | int | ||
243 | RIOBootCodeHOST(p, rbp) | ||
244 | struct rio_info * p; | ||
245 | register struct DownLoad *rbp; | ||
246 | { | ||
247 | register struct Host *HostP; | ||
248 | register caddr_t Cad; | ||
249 | register PARM_MAP *ParmMapP; | ||
250 | register int RupN; | ||
251 | int PortN; | ||
252 | uint host; | ||
253 | caddr_t StartP; | ||
254 | BYTE *DestP; | ||
255 | int wait_count; | ||
256 | ushort OldParmMap; | ||
257 | ushort offset; /* It is very important that this is a ushort */ | ||
258 | /* uint byte; */ | ||
259 | caddr_t DownCode = NULL; | ||
260 | unsigned long flags; | ||
261 | |||
262 | HostP = NULL; /* Assure the compiler we've initialized it */ | ||
263 | for ( host=0; host<p->RIONumHosts; host++ ) { | ||
264 | rio_dprintk (RIO_DEBUG_BOOT, "Attempt to boot host %d\n",host); | ||
265 | HostP = &p->RIOHosts[host]; | ||
266 | |||
267 | rio_dprintk (RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", | ||
268 | HostP->Type, HostP->Mode, HostP->Ivec); | ||
269 | |||
270 | |||
271 | if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) { | ||
272 | rio_dprintk (RIO_DEBUG_BOOT, "%s %d already running\n","Host",host); | ||
273 | continue; | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | ** Grab a 32 bit pointer to the card. | ||
278 | */ | ||
279 | Cad = HostP->Caddr; | ||
280 | |||
281 | /* | ||
282 | ** We are going to (try) and load in rbp->Count bytes. | ||
283 | ** The last byte will reside at p->RIOConf.HostLoadBase-1; | ||
284 | ** Therefore, we need to start copying at address | ||
285 | ** (caddr+p->RIOConf.HostLoadBase-rbp->Count) | ||
286 | */ | ||
287 | StartP = (caddr_t)&Cad[p->RIOConf.HostLoadBase-rbp->Count]; | ||
288 | |||
289 | rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for host is 0x%x\n", (int)Cad ); | ||
290 | rio_dprintk (RIO_DEBUG_BOOT, "kernel virtual address for download is 0x%x\n", (int)StartP); | ||
291 | rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%x\n",p->RIOConf.HostLoadBase); | ||
292 | rio_dprintk (RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count); | ||
293 | |||
294 | if ( p->RIOConf.HostLoadBase < rbp->Count ) { | ||
295 | rio_dprintk (RIO_DEBUG_BOOT, "Bin too large\n"); | ||
296 | p->RIOError.Error = HOST_FILE_TOO_LARGE; | ||
297 | func_exit (); | ||
298 | return -EFBIG; | ||
299 | } | ||
300 | /* | ||
301 | ** Ensure that the host really is stopped. | ||
302 | ** Disable it's external bus & twang its reset line. | ||
303 | */ | ||
304 | RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot ); | ||
305 | |||
306 | /* | ||
307 | ** Copy the data directly from user space to the SRAM. | ||
308 | ** This ain't going to be none too clever if the download | ||
309 | ** code is bigger than this segment. | ||
310 | */ | ||
311 | rio_dprintk (RIO_DEBUG_BOOT, "Copy in code\n"); | ||
312 | |||
313 | /* | ||
314 | ** PCI hostcard can't cope with 32 bit accesses and so need to copy | ||
315 | ** data to a local buffer, and then dripfeed the card. | ||
316 | */ | ||
317 | if ( HostP->Type == RIO_PCI ) { | ||
318 | /* int offset; */ | ||
319 | |||
320 | DownCode = sysbrk(rbp->Count); | ||
321 | if ( !DownCode ) { | ||
322 | rio_dprintk (RIO_DEBUG_BOOT, "No system memory available\n"); | ||
323 | p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY; | ||
324 | func_exit (); | ||
325 | return -ENOMEM; | ||
326 | } | ||
327 | bzero(DownCode, rbp->Count); | ||
328 | |||
329 | if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) { | ||
330 | rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host data\n"); | ||
331 | sysfree( DownCode, rbp->Count ); | ||
332 | p->RIOError.Error = COPYIN_FAILED; | ||
333 | func_exit (); | ||
334 | return -EFAULT; | ||
335 | } | ||
336 | |||
337 | HostP->Copy( DownCode, StartP, rbp->Count ); | ||
338 | |||
339 | sysfree( DownCode, rbp->Count ); | ||
340 | } | ||
341 | else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) { | ||
342 | rio_dprintk (RIO_DEBUG_BOOT, "Bad copyin of host data\n"); | ||
343 | p->RIOError.Error = COPYIN_FAILED; | ||
344 | func_exit (); | ||
345 | return -EFAULT; | ||
346 | } | ||
347 | |||
348 | rio_dprintk (RIO_DEBUG_BOOT, "Copy completed\n"); | ||
349 | |||
350 | /* | ||
351 | ** S T O P ! | ||
352 | ** | ||
353 | ** Upto this point the code has been fairly rational, and possibly | ||
354 | ** even straight forward. What follows is a pile of crud that will | ||
355 | ** magically turn into six bytes of transputer assembler. Normally | ||
356 | ** you would expect an array or something, but, being me, I have | ||
357 | ** chosen [been told] to use a technique whereby the startup code | ||
358 | ** will be correct if we change the loadbase for the code. Which | ||
359 | ** brings us onto another issue - the loadbase is the *end* of the | ||
360 | ** code, not the start. | ||
361 | ** | ||
362 | ** If I were you I wouldn't start from here. | ||
363 | */ | ||
364 | |||
365 | /* | ||
366 | ** We now need to insert a short boot section into | ||
367 | ** the memory at the end of Sram2. This is normally (de)composed | ||
368 | ** of the last eight bytes of the download code. The | ||
369 | ** download has been assembled/compiled to expect to be | ||
370 | ** loaded from 0x7FFF downwards. We have loaded it | ||
371 | ** at some other address. The startup code goes into the small | ||
372 | ** ram window at Sram2, in the last 8 bytes, which are really | ||
373 | ** at addresses 0x7FF8-0x7FFF. | ||
374 | ** | ||
375 | ** If the loadbase is, say, 0x7C00, then we need to branch to | ||
376 | ** address 0x7BFE to run the host.bin startup code. We assemble | ||
377 | ** this jump manually. | ||
378 | ** | ||
379 | ** The two byte sequence 60 08 is loaded into memory at address | ||
380 | ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0, | ||
381 | ** which adds '0' to the .O register, complements .O, and then shifts | ||
382 | ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will | ||
383 | ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new | ||
384 | ** location. Now, the branch starts from the value of .PC (or .IP or | ||
385 | ** whatever the bloody register is called on this chip), and the .PC | ||
386 | ** will be pointing to the location AFTER the branch, in this case | ||
387 | ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8. | ||
388 | ** | ||
389 | ** A long branch is coded at 0x7FF8. This consists of loading a four | ||
390 | ** byte offset into .O using nfix (as above) and pfix operators. The | ||
391 | ** pfix operates in exactly the same way as the nfix operator, but | ||
392 | ** without the complement operation. The offset, of course, must be | ||
393 | ** relative to the address of the byte AFTER the branch instruction, | ||
394 | ** which will be (urm) 0x7FFC, so, our final destination of the branch | ||
395 | ** (loadbase-2), has to be reached from here. Imagine that the loadbase | ||
396 | ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which | ||
397 | ** is the first byte of the initial two byte short local branch of the | ||
398 | ** download code). | ||
399 | ** | ||
400 | ** To code a jump from 0x7FFC (which is where the branch will start | ||
401 | ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)= | ||
402 | ** 0x7BFE. | ||
403 | ** This will be coded as four bytes: | ||
404 | ** 60 2C 20 02 | ||
405 | ** being nfix .O+0 | ||
406 | ** pfix .O+C | ||
407 | ** pfix .O+0 | ||
408 | ** jump .O+2 | ||
409 | ** | ||
410 | ** The nfix operator is used, so that the startup code will be | ||
411 | ** compatible with the whole Tp family. (lies, damn lies, it'll never | ||
412 | ** work in a month of Sundays). | ||
413 | ** | ||
414 | ** The nfix nyble is the 1s complement of the nyble value you | ||
415 | ** want to load - in this case we wanted 'F' so we nfix loaded '0'. | ||
416 | */ | ||
417 | |||
418 | |||
419 | /* | ||
420 | ** Dest points to the top 8 bytes of Sram2. The Tp jumps | ||
421 | ** to 0x7FFE at reset time, and starts executing. This is | ||
422 | ** a short branch to 0x7FF8, where a long branch is coded. | ||
423 | */ | ||
424 | |||
425 | DestP = (BYTE *)&Cad[0x7FF8]; /* <<<---- READ THE ABOVE COMMENTS */ | ||
426 | |||
427 | #define NFIX(N) (0x60 | (N)) /* .O = (~(.O + N))<<4 */ | ||
428 | #define PFIX(N) (0x20 | (N)) /* .O = (.O + N)<<4 */ | ||
429 | #define JUMP(N) (0x00 | (N)) /* .PC = .PC + .O */ | ||
430 | |||
431 | /* | ||
432 | ** 0x7FFC is the address of the location following the last byte of | ||
433 | ** the four byte jump instruction. | ||
434 | ** READ THE ABOVE COMMENTS | ||
435 | ** | ||
436 | ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about. | ||
437 | ** Memsize is 64K for this range of Tp, so offset is a short (unsigned, | ||
438 | ** cos I don't understand 2's complement). | ||
439 | */ | ||
440 | offset = (p->RIOConf.HostLoadBase-2)-0x7FFC; | ||
441 | WBYTE( DestP[0] , NFIX(((ushort)(~offset) >> (ushort)12) & 0xF) ); | ||
442 | WBYTE( DestP[1] , PFIX(( offset >> 8) & 0xF) ); | ||
443 | WBYTE( DestP[2] , PFIX(( offset >> 4) & 0xF) ); | ||
444 | WBYTE( DestP[3] , JUMP( offset & 0xF) ); | ||
445 | |||
446 | WBYTE( DestP[6] , NFIX(0) ); | ||
447 | WBYTE( DestP[7] , JUMP(8) ); | ||
448 | |||
449 | rio_dprintk (RIO_DEBUG_BOOT, "host loadbase is 0x%x\n",p->RIOConf.HostLoadBase); | ||
450 | rio_dprintk (RIO_DEBUG_BOOT, "startup offset is 0x%x\n",offset); | ||
451 | |||
452 | /* | ||
453 | ** Flag what is going on | ||
454 | */ | ||
455 | HostP->Flags &= ~RUN_STATE; | ||
456 | HostP->Flags |= RC_STARTUP; | ||
457 | |||
458 | /* | ||
459 | ** Grab a copy of the current ParmMap pointer, so we | ||
460 | ** can tell when it has changed. | ||
461 | */ | ||
462 | OldParmMap = RWORD(HostP->__ParmMapR); | ||
463 | |||
464 | rio_dprintk (RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n",OldParmMap); | ||
465 | |||
466 | /* | ||
467 | ** And start it running (I hope). | ||
468 | ** As there is nothing dodgy or obscure about the | ||
469 | ** above code, this is guaranteed to work every time. | ||
470 | */ | ||
471 | rio_dprintk (RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", | ||
472 | HostP->Type, HostP->Mode, HostP->Ivec); | ||
473 | |||
474 | rio_start_card_running(HostP); | ||
475 | |||
476 | rio_dprintk (RIO_DEBUG_BOOT, "Set control port\n"); | ||
477 | |||
478 | /* | ||
479 | ** Now, wait for upto five seconds for the Tp to setup the parmmap | ||
480 | ** pointer: | ||
481 | */ | ||
482 | for ( wait_count=0; (wait_count<p->RIOConf.StartupTime)&& | ||
483 | (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) { | ||
484 | rio_dprintk (RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR)); | ||
485 | delay(HostP, HUNDRED_MS); | ||
486 | |||
487 | } | ||
488 | |||
489 | /* | ||
490 | ** If the parmmap pointer is unchanged, then the host code | ||
491 | ** has crashed & burned in a really spectacular way | ||
492 | */ | ||
493 | if ( RWORD(HostP->__ParmMapR) == OldParmMap ) { | ||
494 | rio_dprintk (RIO_DEBUG_BOOT, "parmmap 0x%x\n", RWORD(HostP->__ParmMapR)); | ||
495 | rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n"); | ||
496 | |||
497 | #define HOST_DISABLE \ | ||
498 | HostP->Flags &= ~RUN_STATE; \ | ||
499 | HostP->Flags |= RC_STUFFED; \ | ||
500 | RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );\ | ||
501 | continue | ||
502 | |||
503 | HOST_DISABLE; | ||
504 | } | ||
505 | |||
506 | rio_dprintk (RIO_DEBUG_BOOT, "Running 0x%x\n", RWORD(HostP->__ParmMapR)); | ||
507 | |||
508 | /* | ||
509 | ** Well, the board thought it was OK, and setup its parmmap | ||
510 | ** pointer. For the time being, we will pretend that this | ||
511 | ** board is running, and check out what the error flag says. | ||
512 | */ | ||
513 | |||
514 | /* | ||
515 | ** Grab a 32 bit pointer to the parmmap structure | ||
516 | */ | ||
517 | ParmMapP = (PARM_MAP *)RIO_PTR(Cad,RWORD(HostP->__ParmMapR)); | ||
518 | rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int)ParmMapP); | ||
519 | ParmMapP = (PARM_MAP *)((unsigned long)Cad + | ||
520 | (unsigned long)((RWORD((HostP->__ParmMapR))) & 0xFFFF)); | ||
521 | rio_dprintk (RIO_DEBUG_BOOT, "ParmMapP : %x\n", (int)ParmMapP); | ||
522 | |||
523 | /* | ||
524 | ** The links entry should be 0xFFFF; we set it up | ||
525 | ** with a mask to say how many PHBs to use, and | ||
526 | ** which links to use. | ||
527 | */ | ||
528 | if ( (RWORD(ParmMapP->links) & 0xFFFF) != 0xFFFF ) { | ||
529 | rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); | ||
530 | rio_dprintk (RIO_DEBUG_BOOT, "Links = 0x%x\n",RWORD(ParmMapP->links)); | ||
531 | HOST_DISABLE; | ||
532 | } | ||
533 | |||
534 | WWORD(ParmMapP->links , RIO_LINK_ENABLE); | ||
535 | |||
536 | /* | ||
537 | ** now wait for the card to set all the parmmap->XXX stuff | ||
538 | ** this is a wait of upto two seconds.... | ||
539 | */ | ||
540 | rio_dprintk (RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n",p->RIOConf.StartupTime); | ||
541 | HostP->timeout_id = 0; | ||
542 | for ( wait_count=0; (wait_count<p->RIOConf.StartupTime) && | ||
543 | !RWORD(ParmMapP->init_done); wait_count++ ) { | ||
544 | rio_dprintk (RIO_DEBUG_BOOT, "Waiting for init_done\n"); | ||
545 | delay(HostP, HUNDRED_MS); | ||
546 | } | ||
547 | rio_dprintk (RIO_DEBUG_BOOT, "OK! init_done!\n"); | ||
548 | |||
549 | if (RWORD(ParmMapP->error) != E_NO_ERROR || | ||
550 | !RWORD(ParmMapP->init_done) ) { | ||
551 | rio_dprintk (RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name); | ||
552 | rio_dprintk (RIO_DEBUG_BOOT, "Timedout waiting for init_done\n"); | ||
553 | HOST_DISABLE; | ||
554 | } | ||
555 | |||
556 | rio_dprintk (RIO_DEBUG_BOOT, "Got init_done\n"); | ||
557 | |||
558 | /* | ||
559 | ** It runs! It runs! | ||
560 | */ | ||
561 | rio_dprintk (RIO_DEBUG_BOOT, "Host ID %x Running\n",HostP->UniqueNum); | ||
562 | |||
563 | /* | ||
564 | ** set the time period between interrupts. | ||
565 | */ | ||
566 | WWORD(ParmMapP->timer, (short)p->RIOConf.Timer ); | ||
567 | |||
568 | /* | ||
569 | ** Translate all the 16 bit pointers in the __ParmMapR into | ||
570 | ** 32 bit pointers for the driver. | ||
571 | */ | ||
572 | HostP->ParmMapP = ParmMapP; | ||
573 | HostP->PhbP = (PHB*)RIO_PTR(Cad,RWORD(ParmMapP->phb_ptr)); | ||
574 | HostP->RupP = (RUP*)RIO_PTR(Cad,RWORD(ParmMapP->rups)); | ||
575 | HostP->PhbNumP = (ushort*)RIO_PTR(Cad,RWORD(ParmMapP->phb_num_ptr)); | ||
576 | HostP->LinkStrP = (LPB*)RIO_PTR(Cad,RWORD(ParmMapP->link_str_ptr)); | ||
577 | |||
578 | /* | ||
579 | ** point the UnixRups at the real Rups | ||
580 | */ | ||
581 | for ( RupN = 0; RupN<MAX_RUP; RupN++ ) { | ||
582 | HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN]; | ||
583 | HostP->UnixRups[RupN].Id = RupN+1; | ||
584 | HostP->UnixRups[RupN].BaseSysPort = NO_PORT; | ||
585 | spin_lock_init(&HostP->UnixRups[RupN].RupLock); | ||
586 | } | ||
587 | |||
588 | for ( RupN = 0; RupN<LINKS_PER_UNIT; RupN++ ) { | ||
589 | HostP->UnixRups[RupN+MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup; | ||
590 | HostP->UnixRups[RupN+MAX_RUP].Id = 0; | ||
591 | HostP->UnixRups[RupN+MAX_RUP].BaseSysPort = NO_PORT; | ||
592 | spin_lock_init(&HostP->UnixRups[RupN+MAX_RUP].RupLock); | ||
593 | } | ||
594 | |||
595 | /* | ||
596 | ** point the PortP->Phbs at the real Phbs | ||
597 | */ | ||
598 | for ( PortN=p->RIOFirstPortsMapped; | ||
599 | PortN<p->RIOLastPortsMapped+PORTS_PER_RTA; PortN++ ) { | ||
600 | if ( p->RIOPortp[PortN]->HostP == HostP ) { | ||
601 | struct Port *PortP = p->RIOPortp[PortN]; | ||
602 | struct PHB *PhbP; | ||
603 | /* int oldspl; */ | ||
604 | |||
605 | if ( !PortP->Mapped ) | ||
606 | continue; | ||
607 | |||
608 | PhbP = &HostP->PhbP[PortP->HostPort]; | ||
609 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
610 | |||
611 | PortP->PhbP = PhbP; | ||
612 | |||
613 | PortP->TxAdd = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_add)); | ||
614 | PortP->TxStart = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_start)); | ||
615 | PortP->TxEnd = (WORD *)RIO_PTR(Cad,RWORD(PhbP->tx_end)); | ||
616 | PortP->RxRemove = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_remove)); | ||
617 | PortP->RxStart = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_start)); | ||
618 | PortP->RxEnd = (WORD *)RIO_PTR(Cad,RWORD(PhbP->rx_end)); | ||
619 | |||
620 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
621 | /* | ||
622 | ** point the UnixRup at the base SysPort | ||
623 | */ | ||
624 | if ( !(PortN % PORTS_PER_RTA) ) | ||
625 | HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN; | ||
626 | } | ||
627 | } | ||
628 | |||
629 | rio_dprintk (RIO_DEBUG_BOOT, "Set the card running... \n"); | ||
630 | /* | ||
631 | ** last thing - show the world that everything is in place | ||
632 | */ | ||
633 | HostP->Flags &= ~RUN_STATE; | ||
634 | HostP->Flags |= RC_RUNNING; | ||
635 | } | ||
636 | /* | ||
637 | ** MPX always uses a poller. This is actually patched into the system | ||
638 | ** configuration and called directly from each clock tick. | ||
639 | ** | ||
640 | */ | ||
641 | p->RIOPolling = 1; | ||
642 | |||
643 | p->RIOSystemUp++; | ||
644 | |||
645 | rio_dprintk (RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec); | ||
646 | func_exit (); | ||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | |||
651 | |||
652 | /* | ||
653 | ** Boot an RTA. If we have successfully processed this boot, then | ||
654 | ** return 1. If we havent, then return 0. | ||
655 | */ | ||
656 | int | ||
657 | RIOBootRup( p, Rup, HostP, PacketP) | ||
658 | struct rio_info * p; | ||
659 | uint Rup; | ||
660 | struct Host *HostP; | ||
661 | struct PKT *PacketP; | ||
662 | { | ||
663 | struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data; | ||
664 | struct PktCmd_M *PktReplyP; | ||
665 | struct CmdBlk *CmdBlkP; | ||
666 | uint sequence; | ||
667 | |||
668 | #ifdef CHECK | ||
669 | CheckHost(Host); | ||
670 | CheckRup(Rup); | ||
671 | CheckHostP(HostP); | ||
672 | CheckPacketP(PacketP); | ||
673 | #endif | ||
674 | |||
675 | /* | ||
676 | ** If we haven't been told what to boot, we can't boot it. | ||
677 | */ | ||
678 | if ( p->RIONumBootPkts == 0 ) { | ||
679 | rio_dprintk (RIO_DEBUG_BOOT, "No RTA code to download yet\n"); | ||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | /* rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_BOOT,"Incoming command packet\n"); */ | ||
684 | /* ShowPacket( DBG_BOOT, PacketP ); */ | ||
685 | |||
686 | /* | ||
687 | ** Special case of boot completed - if we get one of these then we | ||
688 | ** don't need a command block. For all other cases we do, so handle | ||
689 | ** this first and then get a command block, then handle every other | ||
690 | ** case, relinquishing the command block if disaster strikes! | ||
691 | */ | ||
692 | if ( (RBYTE(PacketP->len) & PKT_CMD_BIT) && | ||
693 | (RBYTE(PktCmdP->Command)==BOOT_COMPLETED) ) | ||
694 | return RIOBootComplete(p, HostP, Rup, PktCmdP ); | ||
695 | |||
696 | /* | ||
697 | ** try to unhook a command block from the command free list. | ||
698 | */ | ||
699 | if ( !(CmdBlkP = RIOGetCmdBlk()) ) { | ||
700 | rio_dprintk (RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n"); | ||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | /* | ||
705 | ** Fill in the default info on the command block | ||
706 | */ | ||
707 | CmdBlkP->Packet.dest_unit = Rup < (ushort)MAX_RUP ? Rup : 0; | ||
708 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
709 | CmdBlkP->Packet.src_unit = 0; | ||
710 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
711 | |||
712 | CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL; | ||
713 | PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data; | ||
714 | |||
715 | /* | ||
716 | ** process COMMANDS on the boot rup! | ||
717 | */ | ||
718 | if ( RBYTE(PacketP->len) & PKT_CMD_BIT ) { | ||
719 | /* | ||
720 | ** We only expect one type of command - a BOOT_REQUEST! | ||
721 | */ | ||
722 | if ( RBYTE(PktCmdP->Command) != BOOT_REQUEST ) { | ||
723 | rio_dprintk (RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %d\n", | ||
724 | PktCmdP->Command,Rup,HostP-p->RIOHosts); | ||
725 | ShowPacket( DBG_BOOT, PacketP ); | ||
726 | RIOFreeCmdBlk( CmdBlkP ); | ||
727 | return 1; | ||
728 | } | ||
729 | |||
730 | /* | ||
731 | ** Build a Boot Sequence command block | ||
732 | ** | ||
733 | ** 02.03.1999 ARG - ESIL 0820 fix | ||
734 | ** We no longer need to use "Boot Mode", we'll always allow | ||
735 | ** boot requests - the boot will not complete if the device | ||
736 | ** appears in the bindings table. | ||
737 | ** So, this conditional is not required ... | ||
738 | ** | ||
739 | if (p->RIOBootMode == RC_BOOT_NONE) | ||
740 | ** | ||
741 | ** If the system is in slave mode, and a boot request is | ||
742 | ** received, set command to BOOT_ABORT so that the boot | ||
743 | ** will not complete. | ||
744 | ** | ||
745 | PktReplyP->Command = BOOT_ABORT; | ||
746 | else | ||
747 | ** | ||
748 | ** We'll just (always) set the command field in packet reply | ||
749 | ** to allow an attempted boot sequence : | ||
750 | */ | ||
751 | PktReplyP->Command = BOOT_SEQUENCE; | ||
752 | |||
753 | PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts; | ||
754 | PktReplyP->BootSequence.LoadBase = p->RIOConf.RtaLoadBase; | ||
755 | PktReplyP->BootSequence.CodeSize = p->RIOBootCount; | ||
756 | |||
757 | CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT; | ||
758 | |||
759 | bcopy("BOOT",(void *)&CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN],4); | ||
760 | |||
761 | rio_dprintk (RIO_DEBUG_BOOT, "Boot RTA on Host %d Rup %d - %d (0x%x) packets to 0x%x\n", | ||
762 | HostP-p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, | ||
763 | p->RIOConf.RtaLoadBase); | ||
764 | |||
765 | /* | ||
766 | ** If this host is in slave mode, send the RTA an invalid boot | ||
767 | ** sequence command block to force it to kill the boot. We wait | ||
768 | ** for half a second before sending this packet to prevent the RTA | ||
769 | ** attempting to boot too often. The master host should then grab | ||
770 | ** the RTA and make it its own. | ||
771 | */ | ||
772 | p->RIOBooting++; | ||
773 | RIOQueueCmdBlk( HostP, Rup, CmdBlkP ); | ||
774 | return 1; | ||
775 | } | ||
776 | |||
777 | /* | ||
778 | ** It is a request for boot data. | ||
779 | */ | ||
780 | sequence = RWORD(PktCmdP->Sequence); | ||
781 | |||
782 | rio_dprintk (RIO_DEBUG_BOOT, "Boot block %d on Host %d Rup%d\n",sequence,HostP-p->RIOHosts,Rup); | ||
783 | |||
784 | if ( sequence >= p->RIONumBootPkts ) { | ||
785 | rio_dprintk (RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, | ||
786 | p->RIONumBootPkts); | ||
787 | ShowPacket( DBG_BOOT, PacketP ); | ||
788 | } | ||
789 | |||
790 | PktReplyP->Sequence = sequence; | ||
791 | |||
792 | bcopy( p->RIOBootPackets[ p->RIONumBootPkts - sequence - 1 ], | ||
793 | PktReplyP->BootData, RTA_BOOT_DATA_SIZE ); | ||
794 | |||
795 | CmdBlkP->Packet.len = PKT_MAX_DATA_LEN; | ||
796 | ShowPacket( DBG_BOOT, &CmdBlkP->Packet ); | ||
797 | RIOQueueCmdBlk( HostP, Rup, CmdBlkP ); | ||
798 | return 1; | ||
799 | } | ||
800 | |||
801 | /* | ||
802 | ** This function is called when an RTA been booted. | ||
803 | ** If booted by a host, HostP->HostUniqueNum is the booting host. | ||
804 | ** If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA. | ||
805 | ** RtaUniq is the booted RTA. | ||
806 | */ | ||
807 | static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, struct PktCmd *PktCmdP ) | ||
808 | { | ||
809 | struct Map *MapP = NULL; | ||
810 | struct Map *MapP2 = NULL; | ||
811 | int Flag; | ||
812 | int found; | ||
813 | int host, rta; | ||
814 | int EmptySlot = -1; | ||
815 | int entry, entry2; | ||
816 | char *MyType, *MyName; | ||
817 | uint MyLink; | ||
818 | ushort RtaType; | ||
819 | uint RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) + | ||
820 | (RBYTE(PktCmdP->UniqNum[1]) << 8) + | ||
821 | (RBYTE(PktCmdP->UniqNum[2]) << 16) + | ||
822 | (RBYTE(PktCmdP->UniqNum[3]) << 24); | ||
823 | |||
824 | /* Was RIOBooting-- . That's bad. If an RTA sends two of them, the | ||
825 | driver will never think that the RTA has booted... -- REW */ | ||
826 | p->RIOBooting = 0; | ||
827 | |||
828 | rio_dprintk (RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting); | ||
829 | |||
830 | /* | ||
831 | ** Determine type of unit (16/8 port RTA). | ||
832 | */ | ||
833 | RtaType = GetUnitType(RtaUniq); | ||
834 | if ( Rup >= (ushort)MAX_RUP ) { | ||
835 | rio_dprintk (RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", | ||
836 | HostP->Name, 8 * RtaType, RBYTE(PktCmdP->LinkNum)+'A'); | ||
837 | } else { | ||
838 | rio_dprintk (RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", | ||
839 | HostP->Mapping[Rup].Name, 8 * RtaType, | ||
840 | RBYTE(PktCmdP->LinkNum)+'A'); | ||
841 | } | ||
842 | |||
843 | rio_dprintk (RIO_DEBUG_BOOT, "UniqNum is 0x%x\n",RtaUniq); | ||
844 | |||
845 | if ( ( RtaUniq == 0x00000000 ) || ( RtaUniq == 0xffffffff ) ) | ||
846 | { | ||
847 | rio_dprintk (RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n"); | ||
848 | return TRUE; | ||
849 | } | ||
850 | |||
851 | /* | ||
852 | ** If this RTA has just booted an RTA which doesn't belong to this | ||
853 | ** system, or the system is in slave mode, do not attempt to create | ||
854 | ** a new table entry for it. | ||
855 | */ | ||
856 | if (!RIOBootOk(p, HostP, RtaUniq)) | ||
857 | { | ||
858 | MyLink = RBYTE(PktCmdP->LinkNum); | ||
859 | if (Rup < (ushort) MAX_RUP) | ||
860 | { | ||
861 | /* | ||
862 | ** RtaUniq was clone booted (by this RTA). Instruct this RTA | ||
863 | ** to hold off further attempts to boot on this link for 30 | ||
864 | ** seconds. | ||
865 | */ | ||
866 | if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) | ||
867 | { | ||
868 | rio_dprintk (RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", | ||
869 | 'A' + MyLink); | ||
870 | } | ||
871 | } | ||
872 | else | ||
873 | { | ||
874 | /* | ||
875 | ** RtaUniq was booted by this host. Set the booting link | ||
876 | ** to hold off for 30 seconds to give another unit a | ||
877 | ** chance to boot it. | ||
878 | */ | ||
879 | WWORD(HostP->LinkStrP[MyLink].WaitNoBoot, 30); | ||
880 | } | ||
881 | rio_dprintk (RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", | ||
882 | RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum); | ||
883 | return TRUE; | ||
884 | } | ||
885 | |||
886 | /* | ||
887 | ** Check for a SLOT_IN_USE entry for this RTA attached to the | ||
888 | ** current host card in the driver table. | ||
889 | ** | ||
890 | ** If it exists, make a note that we have booted it. Other parts of | ||
891 | ** the driver are interested in this information at a later date, | ||
892 | ** in particular when the booting RTA asks for an ID for this unit, | ||
893 | ** we must have set the BOOTED flag, and the NEWBOOT flag is used | ||
894 | ** to force an open on any ports that where previously open on this | ||
895 | ** unit. | ||
896 | */ | ||
897 | for ( entry=0; entry<MAX_RUP; entry++ ) | ||
898 | { | ||
899 | uint sysport; | ||
900 | |||
901 | if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && | ||
902 | (HostP->Mapping[entry].RtaUniqueNum==RtaUniq)) | ||
903 | { | ||
904 | HostP->Mapping[entry].Flags |= RTA_BOOTED|RTA_NEWBOOT; | ||
905 | #if NEED_TO_FIX | ||
906 | RIO_SV_BROADCAST(HostP->svFlags[entry]); | ||
907 | #endif | ||
908 | if ( (sysport=HostP->Mapping[entry].SysPort) != NO_PORT ) | ||
909 | { | ||
910 | if ( sysport < p->RIOFirstPortsBooted ) | ||
911 | p->RIOFirstPortsBooted = sysport; | ||
912 | if ( sysport > p->RIOLastPortsBooted ) | ||
913 | p->RIOLastPortsBooted = sysport; | ||
914 | /* | ||
915 | ** For a 16 port RTA, check the second bank of 8 ports | ||
916 | */ | ||
917 | if (RtaType == TYPE_RTA16) | ||
918 | { | ||
919 | entry2 = HostP->Mapping[entry].ID2 - 1; | ||
920 | HostP->Mapping[entry2].Flags |= RTA_BOOTED|RTA_NEWBOOT; | ||
921 | #if NEED_TO_FIX | ||
922 | RIO_SV_BROADCAST(HostP->svFlags[entry2]); | ||
923 | #endif | ||
924 | sysport = HostP->Mapping[entry2].SysPort; | ||
925 | if ( sysport < p->RIOFirstPortsBooted ) | ||
926 | p->RIOFirstPortsBooted = sysport; | ||
927 | if ( sysport > p->RIOLastPortsBooted ) | ||
928 | p->RIOLastPortsBooted = sysport; | ||
929 | } | ||
930 | } | ||
931 | if (RtaType == TYPE_RTA16) { | ||
932 | rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", | ||
933 | entry+1, entry2+1); | ||
934 | } else { | ||
935 | rio_dprintk (RIO_DEBUG_BOOT, "RTA will be given ID %d\n",entry+1); | ||
936 | } | ||
937 | return TRUE; | ||
938 | } | ||
939 | } | ||
940 | |||
941 | rio_dprintk (RIO_DEBUG_BOOT, "RTA not configured for this host\n"); | ||
942 | |||
943 | if ( Rup >= (ushort)MAX_RUP ) | ||
944 | { | ||
945 | /* | ||
946 | ** It was a host that did the booting | ||
947 | */ | ||
948 | MyType = "Host"; | ||
949 | MyName = HostP->Name; | ||
950 | } | ||
951 | else | ||
952 | { | ||
953 | /* | ||
954 | ** It was an RTA that did the booting | ||
955 | */ | ||
956 | MyType = "RTA"; | ||
957 | MyName = HostP->Mapping[Rup].Name; | ||
958 | } | ||
959 | #ifdef CHECK | ||
960 | CheckString(MyType); | ||
961 | CheckString(MyName); | ||
962 | #endif | ||
963 | |||
964 | MyLink = RBYTE(PktCmdP->LinkNum); | ||
965 | |||
966 | /* | ||
967 | ** There is no SLOT_IN_USE entry for this RTA attached to the current | ||
968 | ** host card in the driver table. | ||
969 | ** | ||
970 | ** Check for a SLOT_TENTATIVE entry for this RTA attached to the | ||
971 | ** current host card in the driver table. | ||
972 | ** | ||
973 | ** If we find one, then we re-use that slot. | ||
974 | */ | ||
975 | for ( entry=0; entry<MAX_RUP; entry++ ) | ||
976 | { | ||
977 | if ( (HostP->Mapping[entry].Flags & SLOT_TENTATIVE) && | ||
978 | (HostP->Mapping[entry].RtaUniqueNum == RtaUniq) ) | ||
979 | { | ||
980 | if (RtaType == TYPE_RTA16) | ||
981 | { | ||
982 | entry2 = HostP->Mapping[entry].ID2 - 1; | ||
983 | if ( (HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && | ||
984 | (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq) ) | ||
985 | rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", | ||
986 | entry, entry2); | ||
987 | else | ||
988 | continue; | ||
989 | } | ||
990 | else | ||
991 | rio_dprintk (RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n",entry); | ||
992 | if (! p->RIONoMessage) | ||
993 | cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType,MyName,MyLink+'A'); | ||
994 | return TRUE; | ||
995 | } | ||
996 | } | ||
997 | |||
998 | /* | ||
999 | ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA | ||
1000 | ** attached to the current host card in the driver table. | ||
1001 | ** | ||
1002 | ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another | ||
1003 | ** host for this RTA in the driver table. | ||
1004 | ** | ||
1005 | ** For a SLOT_IN_USE entry on another host, we need to delete the RTA | ||
1006 | ** entry from the other host and add it to this host (using some of | ||
1007 | ** the functions from table.c which do this). | ||
1008 | ** For a SLOT_TENTATIVE entry on another host, we must cope with the | ||
1009 | ** following scenario: | ||
1010 | ** | ||
1011 | ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry | ||
1012 | ** in table) | ||
1013 | ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE | ||
1014 | ** entries) | ||
1015 | ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE) | ||
1016 | ** + Unplug RTA and plug back into host A. | ||
1017 | ** + Configure RTA on host A. We now have the same RTA configured | ||
1018 | ** with different ports on two different hosts. | ||
1019 | */ | ||
1020 | rio_dprintk (RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq ); | ||
1021 | found = 0; | ||
1022 | Flag = 0; /* Convince the compiler this variable is initialized */ | ||
1023 | for ( host = 0; !found && (host < p->RIONumHosts); host++ ) | ||
1024 | { | ||
1025 | for ( rta=0; rta<MAX_RUP; rta++ ) | ||
1026 | { | ||
1027 | if ((p->RIOHosts[host].Mapping[rta].Flags & | ||
1028 | (SLOT_IN_USE | SLOT_TENTATIVE)) && | ||
1029 | (p->RIOHosts[host].Mapping[rta].RtaUniqueNum==RtaUniq)) | ||
1030 | { | ||
1031 | Flag = p->RIOHosts[host].Mapping[rta].Flags; | ||
1032 | MapP = &p->RIOHosts[host].Mapping[rta]; | ||
1033 | if (RtaType == TYPE_RTA16) | ||
1034 | { | ||
1035 | MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1]; | ||
1036 | rio_dprintk (RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", | ||
1037 | rta+1, MapP->ID2, p->RIOHosts[host].Name); | ||
1038 | } | ||
1039 | else | ||
1040 | rio_dprintk (RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", | ||
1041 | rta+1, p->RIOHosts[host].Name); | ||
1042 | found = 1; | ||
1043 | break; | ||
1044 | } | ||
1045 | } | ||
1046 | } | ||
1047 | |||
1048 | /* | ||
1049 | ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA | ||
1050 | ** attached to the current host card in the driver table. | ||
1051 | ** | ||
1052 | ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on | ||
1053 | ** another host for this RTA in the driver table... | ||
1054 | ** | ||
1055 | ** Check for a SLOT_IN_USE entry for this RTA in the config table. | ||
1056 | */ | ||
1057 | if ( !MapP ) | ||
1058 | { | ||
1059 | rio_dprintk (RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n",RtaUniq); | ||
1060 | for ( rta=0; rta < TOTAL_MAP_ENTRIES; rta++ ) | ||
1061 | { | ||
1062 | rio_dprintk (RIO_DEBUG_BOOT, "Check table entry %d (%x)", | ||
1063 | rta, | ||
1064 | p->RIOSavedTable[rta].RtaUniqueNum); | ||
1065 | |||
1066 | if ( (p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && | ||
1067 | (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq) ) | ||
1068 | { | ||
1069 | MapP = &p->RIOSavedTable[rta]; | ||
1070 | Flag = p->RIOSavedTable[rta].Flags; | ||
1071 | if (RtaType == TYPE_RTA16) | ||
1072 | { | ||
1073 | for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES; | ||
1074 | entry2++) | ||
1075 | { | ||
1076 | if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq) | ||
1077 | break; | ||
1078 | } | ||
1079 | MapP2 = &p->RIOSavedTable[entry2]; | ||
1080 | rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", | ||
1081 | rta, entry2); | ||
1082 | } | ||
1083 | else | ||
1084 | rio_dprintk (RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta); | ||
1085 | break; | ||
1086 | } | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | /* | ||
1091 | ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA | ||
1092 | ** attached to the current host card in the driver table. | ||
1093 | ** | ||
1094 | ** We may have found a SLOT_IN_USE entry on another host for this | ||
1095 | ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry | ||
1096 | ** on another host for this RTA in the driver table. | ||
1097 | ** | ||
1098 | ** Check the driver table for room to fit this newly discovered RTA. | ||
1099 | ** RIOFindFreeID() first looks for free slots and if it does not | ||
1100 | ** find any free slots it will then attempt to oust any | ||
1101 | ** tentative entry in the table. | ||
1102 | */ | ||
1103 | EmptySlot = 1; | ||
1104 | if (RtaType == TYPE_RTA16) | ||
1105 | { | ||
1106 | if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) | ||
1107 | { | ||
1108 | RIODefaultName(p, HostP, entry); | ||
1109 | FillSlot(entry, entry2, RtaUniq, HostP); | ||
1110 | EmptySlot = 0; | ||
1111 | } | ||
1112 | } | ||
1113 | else | ||
1114 | { | ||
1115 | if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) | ||
1116 | { | ||
1117 | RIODefaultName(p, HostP, entry); | ||
1118 | FillSlot(entry, 0, RtaUniq, HostP); | ||
1119 | EmptySlot = 0; | ||
1120 | } | ||
1121 | } | ||
1122 | |||
1123 | /* | ||
1124 | ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA | ||
1125 | ** attached to the current host card in the driver table. | ||
1126 | ** | ||
1127 | ** If we found a SLOT_IN_USE entry on another host for this | ||
1128 | ** RTA in the config or driver table, and there are enough free | ||
1129 | ** slots in the driver table, then we need to move it over and | ||
1130 | ** delete it from the other host. | ||
1131 | ** If we found a SLOT_TENTATIVE entry on another host for this | ||
1132 | ** RTA in the driver table, just delete the other host entry. | ||
1133 | */ | ||
1134 | if (EmptySlot == 0) | ||
1135 | { | ||
1136 | if ( MapP ) | ||
1137 | { | ||
1138 | if (Flag & SLOT_IN_USE) | ||
1139 | { | ||
1140 | rio_dprintk (RIO_DEBUG_BOOT, | ||
1141 | "This RTA configured on another host - move entry to current host (1)\n"); | ||
1142 | HostP->Mapping[entry].SysPort = MapP->SysPort; | ||
1143 | CCOPY( MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN ); | ||
1144 | HostP->Mapping[entry].Flags = | ||
1145 | SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT; | ||
1146 | #if NEED_TO_FIX | ||
1147 | RIO_SV_BROADCAST(HostP->svFlags[entry]); | ||
1148 | #endif | ||
1149 | RIOReMapPorts( p, HostP, &HostP->Mapping[entry] ); | ||
1150 | if ( HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted ) | ||
1151 | p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort; | ||
1152 | if ( HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted ) | ||
1153 | p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort; | ||
1154 | rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %s\n",(int)MapP->SysPort,MapP->Name); | ||
1155 | } | ||
1156 | else | ||
1157 | { | ||
1158 | rio_dprintk (RIO_DEBUG_BOOT, | ||
1159 | "This RTA has a tentative entry on another host - delete that entry (1)\n"); | ||
1160 | HostP->Mapping[entry].Flags = | ||
1161 | SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT; | ||
1162 | #if NEED_TO_FIX | ||
1163 | RIO_SV_BROADCAST(HostP->svFlags[entry]); | ||
1164 | #endif | ||
1165 | } | ||
1166 | if (RtaType == TYPE_RTA16) | ||
1167 | { | ||
1168 | if (Flag & SLOT_IN_USE) | ||
1169 | { | ||
1170 | HostP->Mapping[entry2].Flags = SLOT_IN_USE | | ||
1171 | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; | ||
1172 | #if NEED_TO_FIX | ||
1173 | RIO_SV_BROADCAST(HostP->svFlags[entry2]); | ||
1174 | #endif | ||
1175 | HostP->Mapping[entry2].SysPort = MapP2->SysPort; | ||
1176 | /* | ||
1177 | ** Map second block of ttys for 16 port RTA | ||
1178 | */ | ||
1179 | RIOReMapPorts( p, HostP, &HostP->Mapping[entry2] ); | ||
1180 | if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted) | ||
1181 | p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort; | ||
1182 | if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted) | ||
1183 | p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort; | ||
1184 | rio_dprintk (RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", | ||
1185 | (int)HostP->Mapping[entry2].SysPort, | ||
1186 | HostP->Mapping[entry].Name); | ||
1187 | } | ||
1188 | else | ||
1189 | HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | | ||
1190 | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; | ||
1191 | #if NEED_TO_FIX | ||
1192 | RIO_SV_BROADCAST(HostP->svFlags[entry2]); | ||
1193 | #endif | ||
1194 | bzero( (caddr_t)MapP2, sizeof(struct Map) ); | ||
1195 | } | ||
1196 | bzero( (caddr_t)MapP, sizeof(struct Map) ); | ||
1197 | if (! p->RIONoMessage) | ||
1198 | cprintf("An orphaned RTA has been adopted by %s '%s' (%c).\n",MyType,MyName,MyLink+'A'); | ||
1199 | } | ||
1200 | else if (! p->RIONoMessage) | ||
1201 | cprintf("RTA connected to %s '%s' (%c) not configured.\n",MyType,MyName,MyLink+'A'); | ||
1202 | RIOSetChange(p); | ||
1203 | return TRUE; | ||
1204 | } | ||
1205 | |||
1206 | /* | ||
1207 | ** There is no room in the driver table to make an entry for the | ||
1208 | ** booted RTA. Keep a note of its Uniq Num in the overflow table, | ||
1209 | ** so we can ignore it's ID requests. | ||
1210 | */ | ||
1211 | if (! p->RIONoMessage) | ||
1212 | cprintf("The RTA connected to %s '%s' (%c) cannot be configured. You cannot configure more than 128 ports to one host card.\n",MyType,MyName,MyLink+'A'); | ||
1213 | for ( entry=0; entry<HostP->NumExtraBooted; entry++ ) | ||
1214 | { | ||
1215 | if ( HostP->ExtraUnits[entry] == RtaUniq ) | ||
1216 | { | ||
1217 | /* | ||
1218 | ** already got it! | ||
1219 | */ | ||
1220 | return TRUE; | ||
1221 | } | ||
1222 | } | ||
1223 | /* | ||
1224 | ** If there is room, add the unit to the list of extras | ||
1225 | */ | ||
1226 | if ( HostP->NumExtraBooted < MAX_EXTRA_UNITS ) | ||
1227 | HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq; | ||
1228 | return TRUE; | ||
1229 | } | ||
1230 | |||
1231 | |||
1232 | /* | ||
1233 | ** If the RTA or its host appears in the RIOBindTab[] structure then | ||
1234 | ** we mustn't boot the RTA and should return FALSE. | ||
1235 | ** This operation is slightly different from the other drivers for RIO | ||
1236 | ** in that this is designed to work with the new utilities | ||
1237 | ** not config.rio and is FAR SIMPLER. | ||
1238 | ** We no longer support the RIOBootMode variable. It is all done from the | ||
1239 | ** "boot/noboot" field in the rio.cf file. | ||
1240 | */ | ||
1241 | int | ||
1242 | RIOBootOk(p, HostP, RtaUniq) | ||
1243 | struct rio_info * p; | ||
1244 | struct Host * HostP; | ||
1245 | ulong RtaUniq; | ||
1246 | { | ||
1247 | int Entry; | ||
1248 | uint HostUniq = HostP->UniqueNum; | ||
1249 | |||
1250 | /* | ||
1251 | ** Search bindings table for RTA or its parent. | ||
1252 | ** If it exists, return 0, else 1. | ||
1253 | */ | ||
1254 | for (Entry = 0; | ||
1255 | ( Entry < MAX_RTA_BINDINGS ) && ( p->RIOBindTab[Entry] != 0 ); | ||
1256 | Entry++) | ||
1257 | { | ||
1258 | if ( (p->RIOBindTab[Entry] == HostUniq) || | ||
1259 | (p->RIOBindTab[Entry] == RtaUniq) ) | ||
1260 | return 0; | ||
1261 | } | ||
1262 | return 1; | ||
1263 | } | ||
1264 | |||
1265 | /* | ||
1266 | ** Make an empty slot tentative. If this is a 16 port RTA, make both | ||
1267 | ** slots tentative, and the second one RTA_SECOND_SLOT as well. | ||
1268 | */ | ||
1269 | |||
1270 | void | ||
1271 | FillSlot(entry, entry2, RtaUniq, HostP) | ||
1272 | int entry; | ||
1273 | int entry2; | ||
1274 | uint RtaUniq; | ||
1275 | struct Host *HostP; | ||
1276 | { | ||
1277 | int link; | ||
1278 | |||
1279 | rio_dprintk (RIO_DEBUG_BOOT, "FillSlot(%d, %d, 0x%x...)\n", entry, entry2, RtaUniq); | ||
1280 | |||
1281 | HostP->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE); | ||
1282 | HostP->Mapping[entry].SysPort = NO_PORT; | ||
1283 | HostP->Mapping[entry].RtaUniqueNum = RtaUniq; | ||
1284 | HostP->Mapping[entry].HostUniqueNum = HostP->UniqueNum; | ||
1285 | HostP->Mapping[entry].ID = entry + 1; | ||
1286 | HostP->Mapping[entry].ID2 = 0; | ||
1287 | if (entry2) { | ||
1288 | HostP->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | | ||
1289 | SLOT_TENTATIVE | RTA16_SECOND_SLOT); | ||
1290 | HostP->Mapping[entry2].SysPort = NO_PORT; | ||
1291 | HostP->Mapping[entry2].RtaUniqueNum = RtaUniq; | ||
1292 | HostP->Mapping[entry2].HostUniqueNum = HostP->UniqueNum; | ||
1293 | HostP->Mapping[entry2].Name[0] = '\0'; | ||
1294 | HostP->Mapping[entry2].ID = entry2 + 1; | ||
1295 | HostP->Mapping[entry2].ID2 = entry + 1; | ||
1296 | HostP->Mapping[entry].ID2 = entry2 + 1; | ||
1297 | } | ||
1298 | /* | ||
1299 | ** Must set these up, so that utilities show | ||
1300 | ** topology of 16 port RTAs correctly | ||
1301 | */ | ||
1302 | for ( link=0; link<LINKS_PER_UNIT; link++ ) { | ||
1303 | HostP->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT; | ||
1304 | HostP->Mapping[entry].Topology[link].Link = NO_LINK; | ||
1305 | if (entry2) { | ||
1306 | HostP->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT; | ||
1307 | HostP->Mapping[entry2].Topology[link].Link = NO_LINK; | ||
1308 | } | ||
1309 | } | ||
1310 | } | ||
1311 | |||
1312 | #if 0 | ||
1313 | /* | ||
1314 | Function: This function is to disable the disk interrupt | ||
1315 | Returns : Nothing | ||
1316 | */ | ||
1317 | void | ||
1318 | disable_interrupt(vector) | ||
1319 | int vector; | ||
1320 | { | ||
1321 | int ps; | ||
1322 | int val; | ||
1323 | |||
1324 | disable(ps); | ||
1325 | if (vector > 40) { | ||
1326 | val = 1 << (vector - 40); | ||
1327 | __outb(S8259+1, __inb(S8259+1) | val); | ||
1328 | } | ||
1329 | else { | ||
1330 | val = 1 << (vector - 32); | ||
1331 | __outb(M8259+1, __inb(M8259+1) | val); | ||
1332 | } | ||
1333 | restore(ps); | ||
1334 | } | ||
1335 | |||
1336 | /* | ||
1337 | Function: This function is to enable the disk interrupt | ||
1338 | Returns : Nothing | ||
1339 | */ | ||
1340 | void | ||
1341 | enable_interrupt(vector) | ||
1342 | int vector; | ||
1343 | { | ||
1344 | int ps; | ||
1345 | int val; | ||
1346 | |||
1347 | disable(ps); | ||
1348 | if (vector > 40) { | ||
1349 | val = 1 << (vector - 40); | ||
1350 | val = ~val; | ||
1351 | __outb(S8259+1, __inb(S8259+1) & val); | ||
1352 | } | ||
1353 | else { | ||
1354 | val = 1 << (vector - 32); | ||
1355 | val = ~val; | ||
1356 | __outb(M8259+1, __inb(M8259+1) & val); | ||
1357 | } | ||
1358 | restore(ps); | ||
1359 | } | ||
1360 | #endif | ||
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c new file mode 100644 index 000000000000..533085ec6f1b --- /dev/null +++ b/drivers/char/rio/riocmd.c | |||
@@ -0,0 +1,1041 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** ported from the existing SCO driver source | ||
6 | ** | ||
7 | * | ||
8 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | ** | ||
24 | ** Module : riocmd.c | ||
25 | ** SID : 1.2 | ||
26 | ** Last Modified : 11/6/98 10:33:41 | ||
27 | ** Retrieved : 11/6/98 10:33:49 | ||
28 | ** | ||
29 | ** ident @(#)riocmd.c 1.2 | ||
30 | ** | ||
31 | ** ----------------------------------------------------------------------------- | ||
32 | */ | ||
33 | #ifdef SCCS_LABELS | ||
34 | static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; | ||
35 | #endif | ||
36 | |||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/errno.h> | ||
40 | #include <linux/tty.h> | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/string.h> | ||
44 | #include <asm/semaphore.h> | ||
45 | |||
46 | #include <linux/termios.h> | ||
47 | #include <linux/serial.h> | ||
48 | |||
49 | #include <linux/generic_serial.h> | ||
50 | |||
51 | #include "linux_compat.h" | ||
52 | #include "rio_linux.h" | ||
53 | #include "typdef.h" | ||
54 | #include "pkt.h" | ||
55 | #include "daemon.h" | ||
56 | #include "rio.h" | ||
57 | #include "riospace.h" | ||
58 | #include "top.h" | ||
59 | #include "cmdpkt.h" | ||
60 | #include "map.h" | ||
61 | #include "riotypes.h" | ||
62 | #include "rup.h" | ||
63 | #include "port.h" | ||
64 | #include "riodrvr.h" | ||
65 | #include "rioinfo.h" | ||
66 | #include "func.h" | ||
67 | #include "errors.h" | ||
68 | #include "pci.h" | ||
69 | |||
70 | #include "parmmap.h" | ||
71 | #include "unixrup.h" | ||
72 | #include "board.h" | ||
73 | #include "host.h" | ||
74 | #include "error.h" | ||
75 | #include "phb.h" | ||
76 | #include "link.h" | ||
77 | #include "cmdblk.h" | ||
78 | #include "route.h" | ||
79 | #include "control.h" | ||
80 | #include "cirrus.h" | ||
81 | |||
82 | |||
83 | static struct IdentifyRta IdRta; | ||
84 | static struct KillNeighbour KillUnit; | ||
85 | |||
86 | int | ||
87 | RIOFoadRta(struct Host *HostP, struct Map *MapP) | ||
88 | { | ||
89 | struct CmdBlk *CmdBlkP; | ||
90 | |||
91 | rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA\n"); | ||
92 | |||
93 | CmdBlkP = RIOGetCmdBlk(); | ||
94 | |||
95 | if ( !CmdBlkP ) { | ||
96 | rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n"); | ||
97 | return -ENXIO; | ||
98 | } | ||
99 | |||
100 | CmdBlkP->Packet.dest_unit = MapP->ID; | ||
101 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
102 | CmdBlkP->Packet.src_unit = 0; | ||
103 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
104 | CmdBlkP->Packet.len = 0x84; | ||
105 | CmdBlkP->Packet.data[0] = IFOAD; | ||
106 | CmdBlkP->Packet.data[1] = 0; | ||
107 | CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF; | ||
108 | CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF; | ||
109 | |||
110 | if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) { | ||
111 | rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n"); | ||
112 | return -EIO; | ||
113 | } | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | int | ||
118 | RIOZombieRta(struct Host *HostP, struct Map *MapP) | ||
119 | { | ||
120 | struct CmdBlk *CmdBlkP; | ||
121 | |||
122 | rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA\n"); | ||
123 | |||
124 | CmdBlkP = RIOGetCmdBlk(); | ||
125 | |||
126 | if ( !CmdBlkP ) { | ||
127 | rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n"); | ||
128 | return -ENXIO; | ||
129 | } | ||
130 | |||
131 | CmdBlkP->Packet.dest_unit = MapP->ID; | ||
132 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
133 | CmdBlkP->Packet.src_unit = 0; | ||
134 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
135 | CmdBlkP->Packet.len = 0x84; | ||
136 | CmdBlkP->Packet.data[0] = ZOMBIE; | ||
137 | CmdBlkP->Packet.data[1] = 0; | ||
138 | CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF; | ||
139 | CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF; | ||
140 | |||
141 | if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) { | ||
142 | rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n"); | ||
143 | return -EIO; | ||
144 | } | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | int | ||
149 | RIOCommandRta(struct rio_info *p, uint RtaUnique, | ||
150 | int (* func)(struct Host *HostP, struct Map *MapP)) | ||
151 | { | ||
152 | uint Host; | ||
153 | |||
154 | rio_dprintk (RIO_DEBUG_CMD, "Command RTA 0x%x func 0x%x\n", RtaUnique, (int)func); | ||
155 | |||
156 | if ( !RtaUnique ) | ||
157 | return(0); | ||
158 | |||
159 | for ( Host = 0; Host < p->RIONumHosts; Host++ ) { | ||
160 | uint Rta; | ||
161 | struct Host *HostP = &p->RIOHosts[Host]; | ||
162 | |||
163 | for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) { | ||
164 | struct Map *MapP = &HostP->Mapping[Rta]; | ||
165 | |||
166 | if ( MapP->RtaUniqueNum == RtaUnique ) { | ||
167 | uint Link; | ||
168 | |||
169 | /* | ||
170 | ** now, lets just check we have a route to it... | ||
171 | ** IF the routing stuff is working, then one of the | ||
172 | ** topology entries for this unit will have a legit | ||
173 | ** route *somewhere*. We care not where - if its got | ||
174 | ** any connections, we can get to it. | ||
175 | */ | ||
176 | for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) { | ||
177 | if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) { | ||
178 | /* | ||
179 | ** Its worth trying the operation... | ||
180 | */ | ||
181 | return (*func)( HostP, MapP ); | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | return -ENXIO; | ||
188 | } | ||
189 | |||
190 | |||
191 | int | ||
192 | RIOIdentifyRta(struct rio_info *p, caddr_t arg) | ||
193 | { | ||
194 | uint Host; | ||
195 | |||
196 | if ( copyin( (int)arg, (caddr_t)&IdRta, sizeof(IdRta) ) == COPYFAIL ) { | ||
197 | rio_dprintk (RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n"); | ||
198 | p->RIOError.Error = COPYIN_FAILED; | ||
199 | return -EFAULT; | ||
200 | } | ||
201 | |||
202 | for ( Host = 0 ; Host < p->RIONumHosts; Host++ ) { | ||
203 | uint Rta; | ||
204 | struct Host *HostP = &p->RIOHosts[Host]; | ||
205 | |||
206 | for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) { | ||
207 | struct Map *MapP = &HostP->Mapping[Rta]; | ||
208 | |||
209 | if ( MapP->RtaUniqueNum == IdRta.RtaUnique ) { | ||
210 | uint Link; | ||
211 | /* | ||
212 | ** now, lets just check we have a route to it... | ||
213 | ** IF the routing stuff is working, then one of the | ||
214 | ** topology entries for this unit will have a legit | ||
215 | ** route *somewhere*. We care not where - if its got | ||
216 | ** any connections, we can get to it. | ||
217 | */ | ||
218 | for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) { | ||
219 | if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) { | ||
220 | /* | ||
221 | ** Its worth trying the operation... | ||
222 | */ | ||
223 | struct CmdBlk *CmdBlkP; | ||
224 | |||
225 | rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA\n"); | ||
226 | |||
227 | CmdBlkP = RIOGetCmdBlk(); | ||
228 | |||
229 | if ( !CmdBlkP ) { | ||
230 | rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n"); | ||
231 | return -ENXIO; | ||
232 | } | ||
233 | |||
234 | CmdBlkP->Packet.dest_unit = MapP->ID; | ||
235 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
236 | CmdBlkP->Packet.src_unit = 0; | ||
237 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
238 | CmdBlkP->Packet.len = 0x84; | ||
239 | CmdBlkP->Packet.data[0] = IDENTIFY; | ||
240 | CmdBlkP->Packet.data[1] = 0; | ||
241 | CmdBlkP->Packet.data[2] = IdRta.ID; | ||
242 | |||
243 | if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) { | ||
244 | rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n"); | ||
245 | return -EIO; | ||
246 | } | ||
247 | return 0; | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | return -ENOENT; | ||
254 | } | ||
255 | |||
256 | |||
257 | int | ||
258 | RIOKillNeighbour(struct rio_info *p, caddr_t arg) | ||
259 | { | ||
260 | uint Host; | ||
261 | uint ID; | ||
262 | struct Host *HostP; | ||
263 | struct CmdBlk *CmdBlkP; | ||
264 | |||
265 | rio_dprintk (RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n"); | ||
266 | |||
267 | if ( copyin( (int)arg, (caddr_t)&KillUnit, sizeof(KillUnit) ) == COPYFAIL ) { | ||
268 | rio_dprintk (RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n"); | ||
269 | p->RIOError.Error = COPYIN_FAILED; | ||
270 | return -EFAULT; | ||
271 | } | ||
272 | |||
273 | if ( KillUnit.Link > 3 ) | ||
274 | return -ENXIO; | ||
275 | |||
276 | CmdBlkP = RIOGetCmdBlk(); | ||
277 | |||
278 | if ( !CmdBlkP ) { | ||
279 | rio_dprintk (RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n"); | ||
280 | return -ENXIO; | ||
281 | } | ||
282 | |||
283 | CmdBlkP->Packet.dest_unit = 0; | ||
284 | CmdBlkP->Packet.src_unit = 0; | ||
285 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
286 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
287 | CmdBlkP->Packet.len = 0x84; | ||
288 | CmdBlkP->Packet.data[0] = UFOAD; | ||
289 | CmdBlkP->Packet.data[1] = KillUnit.Link; | ||
290 | CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF; | ||
291 | CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF; | ||
292 | |||
293 | for ( Host = 0; Host < p->RIONumHosts; Host++ ) { | ||
294 | ID = 0; | ||
295 | HostP = &p->RIOHosts[Host]; | ||
296 | |||
297 | if ( HostP->UniqueNum == KillUnit.UniqueNum ) { | ||
298 | if ( RIOQueueCmdBlk( HostP, RTAS_PER_HOST+KillUnit.Link, | ||
299 | CmdBlkP) == RIO_FAIL ) { | ||
300 | rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); | ||
301 | return -EIO; | ||
302 | } | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | for ( ID=0; ID < RTAS_PER_HOST; ID++ ) { | ||
307 | if ( HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum ) { | ||
308 | CmdBlkP->Packet.dest_unit = ID+1; | ||
309 | if ( RIOQueueCmdBlk( HostP, ID, CmdBlkP) == RIO_FAIL ) { | ||
310 | rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n"); | ||
311 | return -EIO; | ||
312 | } | ||
313 | return 0; | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | RIOFreeCmdBlk( CmdBlkP ); | ||
318 | return -ENXIO; | ||
319 | } | ||
320 | |||
321 | int | ||
322 | RIOSuspendBootRta(struct Host *HostP, int ID, int Link) | ||
323 | { | ||
324 | struct CmdBlk *CmdBlkP; | ||
325 | |||
326 | rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link); | ||
327 | |||
328 | CmdBlkP = RIOGetCmdBlk(); | ||
329 | |||
330 | if ( !CmdBlkP ) { | ||
331 | rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n"); | ||
332 | return -ENXIO; | ||
333 | } | ||
334 | |||
335 | CmdBlkP->Packet.dest_unit = ID; | ||
336 | CmdBlkP->Packet.dest_port = BOOT_RUP; | ||
337 | CmdBlkP->Packet.src_unit = 0; | ||
338 | CmdBlkP->Packet.src_port = BOOT_RUP; | ||
339 | CmdBlkP->Packet.len = 0x84; | ||
340 | CmdBlkP->Packet.data[0] = IWAIT; | ||
341 | CmdBlkP->Packet.data[1] = Link; | ||
342 | CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF; | ||
343 | CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF; | ||
344 | |||
345 | if ( RIOQueueCmdBlk( HostP, ID - 1, CmdBlkP) == RIO_FAIL ) { | ||
346 | rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n"); | ||
347 | return -EIO; | ||
348 | } | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | int | ||
353 | RIOFoadWakeup(struct rio_info *p) | ||
354 | { | ||
355 | int port; | ||
356 | register struct Port *PortP; | ||
357 | unsigned long flags; | ||
358 | |||
359 | for ( port=0; port<RIO_PORTS; port++) { | ||
360 | PortP = p->RIOPortp[port]; | ||
361 | |||
362 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
363 | PortP->Config = 0; | ||
364 | PortP->State = 0; | ||
365 | PortP->InUse = NOT_INUSE; | ||
366 | PortP->PortState = 0; | ||
367 | PortP->FlushCmdBodge = 0; | ||
368 | PortP->ModemLines = 0; | ||
369 | PortP->ModemState = 0; | ||
370 | PortP->CookMode = 0; | ||
371 | PortP->ParamSem = 0; | ||
372 | PortP->Mapped = 0; | ||
373 | PortP->WflushFlag = 0; | ||
374 | PortP->MagicFlags = 0; | ||
375 | PortP->RxDataStart = 0; | ||
376 | PortP->TxBufferIn = 0; | ||
377 | PortP->TxBufferOut = 0; | ||
378 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
379 | } | ||
380 | return(0); | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | ** Incoming command on the COMMAND_RUP to be processed. | ||
385 | */ | ||
386 | static int | ||
387 | RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP) | ||
388 | { | ||
389 | struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data; | ||
390 | struct Port *PortP; | ||
391 | struct UnixRup *UnixRupP; | ||
392 | ushort SysPort; | ||
393 | ushort ReportedModemStatus; | ||
394 | ushort rup; | ||
395 | ushort subCommand; | ||
396 | unsigned long flags; | ||
397 | |||
398 | func_enter (); | ||
399 | |||
400 | #ifdef CHECK | ||
401 | CheckHost( Host ); | ||
402 | CheckHostP( HostP ); | ||
403 | CheckPacketP( PacketP ); | ||
404 | #endif | ||
405 | |||
406 | /* | ||
407 | ** 16 port RTA note: | ||
408 | ** Command rup packets coming from the RTA will have pkt->data[1] (which | ||
409 | ** translates to PktCmdP->PhbNum) set to the host port number for the | ||
410 | ** particular unit. To access the correct BaseSysPort for a 16 port RTA, | ||
411 | ** we can use PhbNum to get the rup number for the appropriate 8 port | ||
412 | ** block (for the first block, this should be equal to 'Rup'). | ||
413 | */ | ||
414 | rup = RBYTE(PktCmdP->PhbNum) / (ushort)PORTS_PER_RTA; | ||
415 | UnixRupP = &HostP->UnixRups[rup]; | ||
416 | SysPort = UnixRupP->BaseSysPort + | ||
417 | (RBYTE(PktCmdP->PhbNum) % (ushort)PORTS_PER_RTA); | ||
418 | rio_dprintk (RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort); | ||
419 | |||
420 | #ifdef CHECK | ||
421 | CheckRup( rup ); | ||
422 | CheckUnixRupP( UnixRupP ); | ||
423 | #endif | ||
424 | if ( UnixRupP->BaseSysPort == NO_PORT ) { | ||
425 | rio_dprintk (RIO_DEBUG_CMD, "OBSCURE ERROR!\n"); | ||
426 | rio_dprintk (RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n"); | ||
427 | rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n", | ||
428 | HostP-p->RIOHosts, HostP->Name ); | ||
429 | rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup); | ||
430 | |||
431 | if ( Rup >= (ushort)MAX_RUP ) { | ||
432 | rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", | ||
433 | HostP->Mapping[Rup].Name); | ||
434 | } else | ||
435 | rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", | ||
436 | ('A' + Rup - MAX_RUP), HostP->Name); | ||
437 | |||
438 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", | ||
439 | PacketP->dest_unit, PacketP->dest_port ); | ||
440 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n", | ||
441 | PacketP->src_unit, PacketP->src_port ); | ||
442 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", PacketP->len,PacketP->len ); | ||
443 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control); | ||
444 | rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum ); | ||
445 | rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " | ||
446 | "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command ); | ||
447 | return TRUE; | ||
448 | } | ||
449 | |||
450 | #ifdef CHECK | ||
451 | CheckSysPort( SysPort ); | ||
452 | #endif | ||
453 | PortP = p->RIOPortp[ SysPort ]; | ||
454 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
455 | switch( RBYTE(PktCmdP->Command) ) { | ||
456 | case BREAK_RECEIVED: | ||
457 | rio_dprintk (RIO_DEBUG_CMD, "Received a break!\n"); | ||
458 | /* If the current line disc. is not multi-threading and | ||
459 | the current processor is not the default, reset rup_intr | ||
460 | and return FALSE to ensure that the command packet is | ||
461 | not freed. */ | ||
462 | /* Call tmgr HANGUP HERE */ | ||
463 | /* Fix this later when every thing works !!!! RAMRAJ */ | ||
464 | gs_got_break (&PortP->gs); | ||
465 | break; | ||
466 | |||
467 | case COMPLETE: | ||
468 | rio_dprintk (RIO_DEBUG_CMD, "Command complete on phb %d host %d\n", | ||
469 | RBYTE(PktCmdP->PhbNum), HostP-p->RIOHosts); | ||
470 | subCommand = 1; | ||
471 | switch (RBYTE(PktCmdP->SubCommand)) { | ||
472 | case MEMDUMP : | ||
473 | rio_dprintk (RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", | ||
474 | RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr)); | ||
475 | break; | ||
476 | case READ_REGISTER : | ||
477 | rio_dprintk (RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr)); | ||
478 | p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST); | ||
479 | break; | ||
480 | default : | ||
481 | subCommand = 0; | ||
482 | break; | ||
483 | } | ||
484 | if (subCommand) | ||
485 | break; | ||
486 | rio_dprintk (RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", | ||
487 | RBYTE(PktCmdP->PortStatus),PortP->PortState); | ||
488 | if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) { | ||
489 | rio_dprintk (RIO_DEBUG_CMD, "Mark status & wakeup\n"); | ||
490 | PortP->PortState = RBYTE(PktCmdP->PortStatus); | ||
491 | /* What should we do here ... | ||
492 | wakeup( &PortP->PortState ); | ||
493 | */ | ||
494 | } else | ||
495 | rio_dprintk (RIO_DEBUG_CMD, "No change\n"); | ||
496 | |||
497 | /* FALLTHROUGH */ | ||
498 | case MODEM_STATUS: | ||
499 | /* | ||
500 | ** Knock out the tbusy and tstop bits, as these are not relevant | ||
501 | ** to the check for modem status change (they're just there because | ||
502 | ** it's a convenient place to put them!). | ||
503 | */ | ||
504 | ReportedModemStatus = RBYTE(PktCmdP->ModemStatus); | ||
505 | if ((PortP->ModemState & MSVR1_HOST) == | ||
506 | (ReportedModemStatus & MSVR1_HOST)) { | ||
507 | rio_dprintk (RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState); | ||
508 | /* | ||
509 | ** Update ModemState just in case tbusy or tstop states have | ||
510 | ** changed. | ||
511 | */ | ||
512 | PortP->ModemState = ReportedModemStatus; | ||
513 | } | ||
514 | else { | ||
515 | rio_dprintk (RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", | ||
516 | PortP->ModemState, ReportedModemStatus); | ||
517 | PortP->ModemState = ReportedModemStatus; | ||
518 | #ifdef MODEM_SUPPORT | ||
519 | if ( PortP->Mapped ) { | ||
520 | /***********************************************************\ | ||
521 | ************************************************************* | ||
522 | *** *** | ||
523 | *** M O D E M S T A T E C H A N G E *** | ||
524 | *** *** | ||
525 | ************************************************************* | ||
526 | \***********************************************************/ | ||
527 | /* | ||
528 | ** If the device is a modem, then check the modem | ||
529 | ** carrier. | ||
530 | */ | ||
531 | if (PortP->gs.tty == NULL) | ||
532 | break; | ||
533 | if (PortP->gs.tty->termios == NULL) | ||
534 | break; | ||
535 | |||
536 | if (!(PortP->gs.tty->termios->c_cflag & CLOCAL) && | ||
537 | ((PortP->State & (RIO_MOPEN|RIO_WOPEN)))) { | ||
538 | |||
539 | rio_dprintk (RIO_DEBUG_CMD, "Is there a Carrier?\n"); | ||
540 | /* | ||
541 | ** Is there a carrier? | ||
542 | */ | ||
543 | if ( PortP->ModemState & MSVR1_CD ) { | ||
544 | /* | ||
545 | ** Has carrier just appeared? | ||
546 | */ | ||
547 | if (!(PortP->State & RIO_CARR_ON)) { | ||
548 | rio_dprintk (RIO_DEBUG_CMD, "Carrier just came up.\n"); | ||
549 | PortP->State |= RIO_CARR_ON; | ||
550 | /* | ||
551 | ** wakeup anyone in WOPEN | ||
552 | */ | ||
553 | if (PortP->State & (PORT_ISOPEN | RIO_WOPEN) ) | ||
554 | wake_up_interruptible (&PortP->gs.open_wait); | ||
555 | #ifdef STATS | ||
556 | PortP->Stat.ModemOnCnt++; | ||
557 | #endif | ||
558 | } | ||
559 | } else { | ||
560 | /* | ||
561 | ** Has carrier just dropped? | ||
562 | */ | ||
563 | if (PortP->State & RIO_CARR_ON) { | ||
564 | if (PortP->State & (PORT_ISOPEN|RIO_WOPEN|RIO_MOPEN)) | ||
565 | tty_hangup (PortP->gs.tty); | ||
566 | PortP->State &= ~RIO_CARR_ON; | ||
567 | rio_dprintk (RIO_DEBUG_CMD, "Carrirer just went down\n"); | ||
568 | #ifdef STATS | ||
569 | PortP->Stat.ModemOffCnt++; | ||
570 | #endif | ||
571 | } | ||
572 | } | ||
573 | } | ||
574 | } | ||
575 | #endif | ||
576 | } | ||
577 | break; | ||
578 | |||
579 | default: | ||
580 | rio_dprintk (RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n", | ||
581 | RBYTE(PktCmdP->Command),HostP-p->RIOHosts); | ||
582 | break; | ||
583 | } | ||
584 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
585 | |||
586 | func_exit (); | ||
587 | |||
588 | return TRUE; | ||
589 | } | ||
590 | /* | ||
591 | ** The command mechanism: | ||
592 | ** Each rup has a chain of commands associated with it. | ||
593 | ** This chain is maintained by routines in this file. | ||
594 | ** Periodically we are called and we run a quick check of all the | ||
595 | ** active chains to determine if there is a command to be executed, | ||
596 | ** and if the rup is ready to accept it. | ||
597 | ** | ||
598 | */ | ||
599 | |||
600 | /* | ||
601 | ** Allocate an empty command block. | ||
602 | */ | ||
603 | struct CmdBlk * | ||
604 | RIOGetCmdBlk(void) | ||
605 | { | ||
606 | struct CmdBlk *CmdBlkP; | ||
607 | |||
608 | CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk)); | ||
609 | if (CmdBlkP) | ||
610 | bzero(CmdBlkP, sizeof(struct CmdBlk)); | ||
611 | |||
612 | return CmdBlkP; | ||
613 | } | ||
614 | |||
615 | /* | ||
616 | ** Return a block to the head of the free list. | ||
617 | */ | ||
618 | void | ||
619 | RIOFreeCmdBlk(struct CmdBlk *CmdBlkP) | ||
620 | { | ||
621 | sysfree((void *)CmdBlkP, sizeof(struct CmdBlk)); | ||
622 | } | ||
623 | |||
624 | /* | ||
625 | ** attach a command block to the list of commands to be performed for | ||
626 | ** a given rup. | ||
627 | */ | ||
628 | int | ||
629 | RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP) | ||
630 | { | ||
631 | struct CmdBlk **Base; | ||
632 | struct UnixRup *UnixRupP; | ||
633 | unsigned long flags; | ||
634 | |||
635 | #ifdef CHECK | ||
636 | CheckHostP( HostP ); | ||
637 | CheckRup( Rup ); | ||
638 | CheckCmdBlkP( CmdBlkP ); | ||
639 | #endif | ||
640 | if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) { | ||
641 | rio_dprintk (RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n",Rup); | ||
642 | RIOFreeCmdBlk( CmdBlkP ); | ||
643 | return RIO_FAIL; | ||
644 | } | ||
645 | |||
646 | UnixRupP = &HostP->UnixRups[Rup]; | ||
647 | |||
648 | rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
649 | |||
650 | /* | ||
651 | ** If the RUP is currently inactive, then put the request | ||
652 | ** straight on the RUP.... | ||
653 | */ | ||
654 | if ( (UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && | ||
655 | (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE ) && | ||
656 | (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg,CmdBlkP) | ||
657 | :TRUE)) { | ||
658 | rio_dprintk (RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", | ||
659 | CmdBlkP->Packet.data[0]); | ||
660 | |||
661 | /* | ||
662 | ** Whammy! blat that pack! | ||
663 | */ | ||
664 | HostP->Copy( (caddr_t)&CmdBlkP->Packet, | ||
665 | RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt ), sizeof(PKT) ); | ||
666 | |||
667 | /* | ||
668 | ** place command packet on the pending position. | ||
669 | */ | ||
670 | UnixRupP->CmdPendingP = CmdBlkP; | ||
671 | |||
672 | /* | ||
673 | ** set the command register | ||
674 | */ | ||
675 | WWORD(UnixRupP->RupP->txcontrol , TX_PACKET_READY); | ||
676 | |||
677 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
678 | |||
679 | return RIO_SUCCESS; | ||
680 | } | ||
681 | rio_dprintk (RIO_DEBUG_CMD, "RUP active - en-queing\n"); | ||
682 | |||
683 | if ( UnixRupP->CmdsWaitingP != NULL) | ||
684 | rio_dprintk (RIO_DEBUG_CMD, "Rup active - command waiting\n"); | ||
685 | if ( UnixRupP->CmdPendingP != NULL ) | ||
686 | rio_dprintk (RIO_DEBUG_CMD, "Rup active - command pending\n"); | ||
687 | if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE ) | ||
688 | rio_dprintk (RIO_DEBUG_CMD, "Rup active - command rup not ready\n"); | ||
689 | |||
690 | Base = &UnixRupP->CmdsWaitingP; | ||
691 | |||
692 | rio_dprintk (RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int)CmdBlkP,(int)Base); | ||
693 | |||
694 | while ( *Base ) { | ||
695 | rio_dprintk (RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int)(*Base)); | ||
696 | Base = &((*Base)->NextP); | ||
697 | rio_dprintk (RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%x at 0x%x\n", | ||
698 | (int)CmdBlkP,(int)Base); | ||
699 | } | ||
700 | |||
701 | rio_dprintk (RIO_DEBUG_CMD, "Will queue cmdblk 0x%x at 0x%x\n",(int)CmdBlkP,(int)Base); | ||
702 | |||
703 | *Base = CmdBlkP; | ||
704 | |||
705 | CmdBlkP->NextP = NULL; | ||
706 | |||
707 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
708 | |||
709 | return RIO_SUCCESS; | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | ** Here we go - if there is an empty rup, fill it! | ||
714 | ** must be called at splrio() or higher. | ||
715 | */ | ||
716 | void | ||
717 | RIOPollHostCommands(struct rio_info *p, struct Host *HostP) | ||
718 | { | ||
719 | register struct CmdBlk *CmdBlkP; | ||
720 | register struct UnixRup *UnixRupP; | ||
721 | struct PKT *PacketP; | ||
722 | ushort Rup; | ||
723 | unsigned long flags; | ||
724 | |||
725 | |||
726 | Rup = MAX_RUP+LINKS_PER_UNIT; | ||
727 | |||
728 | do { /* do this loop for each RUP */ | ||
729 | /* | ||
730 | ** locate the rup we are processing & lock it | ||
731 | */ | ||
732 | UnixRupP = &HostP->UnixRups[--Rup]; | ||
733 | |||
734 | spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
735 | |||
736 | /* | ||
737 | ** First check for incoming commands: | ||
738 | */ | ||
739 | if ( RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE ) { | ||
740 | int FreeMe; | ||
741 | |||
742 | PacketP =(PKT *)RIO_PTR(HostP->Caddr,RWORD(UnixRupP->RupP->rxpkt)); | ||
743 | |||
744 | ShowPacket( DBG_CMD, PacketP ); | ||
745 | |||
746 | switch ( RBYTE(PacketP->dest_port) ) { | ||
747 | case BOOT_RUP: | ||
748 | rio_dprintk (RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", | ||
749 | RBYTE(PacketP->len) & 0x80 ? "Command":"Data", | ||
750 | RBYTE(PacketP->data[0])); | ||
751 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
752 | FreeMe= RIOBootRup(p, Rup,HostP,PacketP); | ||
753 | rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
754 | break; | ||
755 | |||
756 | case COMMAND_RUP: | ||
757 | /* | ||
758 | ** Free the RUP lock as loss of carrier causes a | ||
759 | ** ttyflush which will (eventually) call another | ||
760 | ** routine that uses the RUP lock. | ||
761 | */ | ||
762 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
763 | FreeMe= RIOCommandRup(p, Rup,HostP,PacketP); | ||
764 | if (PacketP->data[5] == MEMDUMP) { | ||
765 | rio_dprintk (RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", | ||
766 | *(ushort *) &(PacketP->data[6])); | ||
767 | HostP->Copy( (caddr_t)&(PacketP->data[8]), | ||
768 | (caddr_t)p->RIOMemDump, 32 ); | ||
769 | } | ||
770 | rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
771 | break; | ||
772 | |||
773 | case ROUTE_RUP: | ||
774 | rio_spin_unlock_irqrestore( &UnixRupP->RupLock, flags); | ||
775 | FreeMe = RIORouteRup(p, Rup, HostP, PacketP ); | ||
776 | rio_spin_lock_irqsave( &UnixRupP->RupLock, flags ); | ||
777 | break; | ||
778 | |||
779 | default: | ||
780 | rio_dprintk (RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port)); | ||
781 | FreeMe = 1; | ||
782 | break; | ||
783 | } | ||
784 | |||
785 | if ( FreeMe ) { | ||
786 | rio_dprintk (RIO_DEBUG_CMD, "Free processed incoming command packet\n"); | ||
787 | put_free_end(HostP,PacketP); | ||
788 | |||
789 | WWORD(UnixRupP->RupP->rxcontrol , RX_RUP_INACTIVE); | ||
790 | |||
791 | if ( RWORD(UnixRupP->RupP->handshake)==PHB_HANDSHAKE_SET ) { | ||
792 | rio_dprintk (RIO_DEBUG_CMD, "Handshake rup %d\n",Rup); | ||
793 | WWORD(UnixRupP->RupP->handshake, | ||
794 | PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET); | ||
795 | } | ||
796 | } | ||
797 | } | ||
798 | |||
799 | /* | ||
800 | ** IF a command was running on the port, | ||
801 | ** and it has completed, then tidy it up. | ||
802 | */ | ||
803 | if ( (CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */ | ||
804 | (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { | ||
805 | /* | ||
806 | ** we are idle. | ||
807 | ** there is a command in pending. | ||
808 | ** Therefore, this command has finished. | ||
809 | ** So, wakeup whoever is waiting for it (and tell them | ||
810 | ** what happened). | ||
811 | */ | ||
812 | if ( CmdBlkP->Packet.dest_port == BOOT_RUP ) | ||
813 | rio_dprintk (RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", | ||
814 | CmdBlkP->Packet.len & 0x80 ? "Command":"Data", | ||
815 | CmdBlkP->Packet.data[0]); | ||
816 | |||
817 | rio_dprintk (RIO_DEBUG_CMD, "Command 0x%x completed\n",(int)CmdBlkP); | ||
818 | |||
819 | /* | ||
820 | ** Clear the Rup lock to prevent mutual exclusion. | ||
821 | */ | ||
822 | if ( CmdBlkP->PostFuncP ) { | ||
823 | rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
824 | (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg,CmdBlkP); | ||
825 | rio_spin_lock_irqsave(&UnixRupP->RupLock, flags); | ||
826 | } | ||
827 | |||
828 | /* | ||
829 | ** ....clear the pending flag.... | ||
830 | */ | ||
831 | UnixRupP->CmdPendingP = NULL; | ||
832 | |||
833 | /* | ||
834 | ** ....and return the command block to the freelist. | ||
835 | */ | ||
836 | RIOFreeCmdBlk( CmdBlkP ); | ||
837 | } | ||
838 | |||
839 | /* | ||
840 | ** If there is a command for this rup, and the rup | ||
841 | ** is idle, then process the command | ||
842 | */ | ||
843 | if ( (CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */ | ||
844 | (UnixRupP->CmdPendingP == NULL) && | ||
845 | (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) { | ||
846 | /* | ||
847 | ** if the pre-function is non-zero, call it. | ||
848 | ** If it returns RIO_FAIL then don't | ||
849 | ** send this command yet! | ||
850 | */ | ||
851 | #ifdef CHECK | ||
852 | CheckCmdBlkP (CmdBlkP); | ||
853 | #endif | ||
854 | if ( !(CmdBlkP->PreFuncP ? | ||
855 | (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg, CmdBlkP) : TRUE)) { | ||
856 | rio_dprintk (RIO_DEBUG_CMD, "Not ready to start command 0x%x\n",(int)CmdBlkP); | ||
857 | } | ||
858 | else { | ||
859 | rio_dprintk (RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n", | ||
860 | (int)CmdBlkP, CmdBlkP->Packet.data[0]); | ||
861 | /* | ||
862 | ** Whammy! blat that pack! | ||
863 | */ | ||
864 | #ifdef CHECK | ||
865 | CheckPacketP ((PKT *)RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt)); | ||
866 | #endif | ||
867 | HostP->Copy( (caddr_t)&CmdBlkP->Packet, | ||
868 | RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT)); | ||
869 | |||
870 | /* | ||
871 | ** remove the command from the rup command queue... | ||
872 | */ | ||
873 | UnixRupP->CmdsWaitingP = CmdBlkP->NextP; | ||
874 | |||
875 | /* | ||
876 | ** ...and place it on the pending position. | ||
877 | */ | ||
878 | UnixRupP->CmdPendingP = CmdBlkP; | ||
879 | |||
880 | /* | ||
881 | ** set the command register | ||
882 | */ | ||
883 | WWORD(UnixRupP->RupP->txcontrol,TX_PACKET_READY); | ||
884 | |||
885 | /* | ||
886 | ** the command block will be freed | ||
887 | ** when the command has been processed. | ||
888 | */ | ||
889 | } | ||
890 | } | ||
891 | spin_unlock_irqrestore(&UnixRupP->RupLock, flags); | ||
892 | } while ( Rup ); | ||
893 | } | ||
894 | |||
895 | int | ||
896 | RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP) | ||
897 | { | ||
898 | struct Port * PortP = (struct Port *)iPortP; | ||
899 | unsigned long flags; | ||
900 | |||
901 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
902 | #ifdef CHECK | ||
903 | CheckPortP( PortP ); | ||
904 | #endif | ||
905 | PortP->WflushFlag++; | ||
906 | PortP->MagicFlags |= MAGIC_FLUSH; | ||
907 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
908 | return RIOUnUse( iPortP, CmdBlkP ); | ||
909 | } | ||
910 | |||
911 | int | ||
912 | RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP) | ||
913 | { | ||
914 | struct Port * PortP = (struct Port *)iPortP; | ||
915 | PKT *PacketP; | ||
916 | unsigned long flags; | ||
917 | |||
918 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
919 | |||
920 | while ( can_remove_receive(&PacketP, PortP) ) { | ||
921 | remove_receive(PortP); | ||
922 | ShowPacket(DBG_PROC, PacketP ); | ||
923 | put_free_end( PortP->HostP, PacketP ); | ||
924 | } | ||
925 | |||
926 | if ( RWORD(PortP->PhbP->handshake)==PHB_HANDSHAKE_SET ) { | ||
927 | /* | ||
928 | ** MAGIC! (Basically, handshake the RX buffer, so that | ||
929 | ** the RTAs upstream can be re-enabled.) | ||
930 | */ | ||
931 | rio_dprintk (RIO_DEBUG_CMD, "Util: Set RX handshake bit\n"); | ||
932 | WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET); | ||
933 | } | ||
934 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
935 | return RIOUnUse( iPortP, CmdBlkP ); | ||
936 | } | ||
937 | |||
938 | int | ||
939 | RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP) | ||
940 | { | ||
941 | struct Port * PortP = (struct Port *)iPortP; | ||
942 | unsigned long flags; | ||
943 | |||
944 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
945 | |||
946 | #ifdef CHECK | ||
947 | CheckPortP( PortP ); | ||
948 | #endif | ||
949 | rio_dprintk (RIO_DEBUG_CMD, "Decrement in use count for port\n"); | ||
950 | |||
951 | if (PortP->InUse) { | ||
952 | if ( --PortP->InUse != NOT_INUSE ) { | ||
953 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
954 | return 0; | ||
955 | } | ||
956 | } | ||
957 | /* | ||
958 | ** While PortP->InUse is set (i.e. a preemptive command has been sent to | ||
959 | ** the RTA and is awaiting completion), any transmit data is prevented from | ||
960 | ** being transferred from the write queue into the transmit packets | ||
961 | ** (add_transmit) and no furthur transmit interrupt will be sent for that | ||
962 | ** data. The next interrupt will occur up to 500ms later (RIOIntr is called | ||
963 | ** twice a second as a saftey measure). This was the case when kermit was | ||
964 | ** used to send data into a RIO port. After each packet was sent, TCFLSH | ||
965 | ** was called to flush the read queue preemptively. PortP->InUse was | ||
966 | ** incremented, thereby blocking the 6 byte acknowledgement packet | ||
967 | ** transmitted back. This acknowledgment hung around for 500ms before | ||
968 | ** being sent, thus reducing input performance substantially!. | ||
969 | ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data | ||
970 | ** hanging around in the transmit buffer is sent immediately. | ||
971 | */ | ||
972 | WWORD(PortP->HostP->ParmMapP->tx_intr, 1); | ||
973 | /* What to do here .. | ||
974 | wakeup( (caddr_t)&(PortP->InUse) ); | ||
975 | */ | ||
976 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | void | ||
981 | ShowPacket(uint Flags, struct PKT *PacketP) | ||
982 | { | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | ** | ||
987 | ** How to use this file: | ||
988 | ** | ||
989 | ** To send a command down a rup, you need to allocate a command block, fill | ||
990 | ** in the packet information, fill in the command number, fill in the pre- | ||
991 | ** and post- functions and arguments, and then add the command block to the | ||
992 | ** queue of command blocks for the port in question. When the port is idle, | ||
993 | ** then the pre-function will be called. If this returns RIO_FAIL then the | ||
994 | ** command will be re-queued and tried again at a later date (probably in one | ||
995 | ** clock tick). If the pre-function returns NOT RIO_FAIL, then the command | ||
996 | ** packet will be queued on the RUP, and the txcontrol field set to the | ||
997 | ** command number. When the txcontrol field has changed from being the | ||
998 | ** command number, then the post-function will be called, with the argument | ||
999 | ** specified earlier, a pointer to the command block, and the value of | ||
1000 | ** txcontrol. | ||
1001 | ** | ||
1002 | ** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer | ||
1003 | ** to the command block structure allocated, or NULL if there aren't any. | ||
1004 | ** The block will have been zeroed for you. | ||
1005 | ** | ||
1006 | ** The structure has the following fields: | ||
1007 | ** | ||
1008 | ** struct CmdBlk | ||
1009 | ** { | ||
1010 | ** struct CmdBlk *NextP; ** Pointer to next command block ** | ||
1011 | ** struct PKT Packet; ** A packet, to copy to the rup ** | ||
1012 | ** int (*PreFuncP)(); ** The func to call to check if OK ** | ||
1013 | ** int PreArg; ** The arg for the func ** | ||
1014 | ** int (*PostFuncP)(); ** The func to call when completed ** | ||
1015 | ** int PostArg; ** The arg for the func ** | ||
1016 | ** }; | ||
1017 | ** | ||
1018 | ** You need to fill in ALL fields EXCEPT NextP, which is used to link the | ||
1019 | ** blocks together either on the free list or on the Rup list. | ||
1020 | ** | ||
1021 | ** Packet is an actual packet structure to be filled in with the packet | ||
1022 | ** information associated with the command. You need to fill in everything, | ||
1023 | ** as the command processore doesn't process the command packet in any way. | ||
1024 | ** | ||
1025 | ** The PreFuncP is called before the packet is enqueued on the host rup. | ||
1026 | ** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must | ||
1027 | ** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL | ||
1028 | ** if the packet is NOT to be queued. | ||
1029 | ** | ||
1030 | ** The PostFuncP is called when the command has completed. It is called | ||
1031 | ** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected | ||
1032 | ** to return a value. PostFuncP does NOT need to free the command block, | ||
1033 | ** as this happens automatically after PostFuncP returns. | ||
1034 | ** | ||
1035 | ** Once the command block has been filled in, it is attached to the correct | ||
1036 | ** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is | ||
1037 | ** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer | ||
1038 | ** to it!), and CmdBlkP is the pointer to the command block allocated using | ||
1039 | ** RIOGetCmdBlk(). | ||
1040 | ** | ||
1041 | */ | ||
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c new file mode 100644 index 000000000000..b4d1a23e27e4 --- /dev/null +++ b/drivers/char/rio/rioctrl.c | |||
@@ -0,0 +1,1869 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : rioctrl.c | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 10:33:42 | ||
26 | ** Retrieved : 11/6/98 10:33:49 | ||
27 | ** | ||
28 | ** ident @(#)rioctrl.c 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | #ifdef SCCS_LABELS | ||
33 | static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3"; | ||
34 | #endif | ||
35 | |||
36 | |||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/errno.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <asm/system.h> | ||
42 | #include <asm/string.h> | ||
43 | #include <asm/semaphore.h> | ||
44 | #include <asm/uaccess.h> | ||
45 | |||
46 | #include <linux/termios.h> | ||
47 | #include <linux/serial.h> | ||
48 | |||
49 | #include <linux/generic_serial.h> | ||
50 | |||
51 | |||
52 | #include "linux_compat.h" | ||
53 | #include "rio_linux.h" | ||
54 | #include "typdef.h" | ||
55 | #include "pkt.h" | ||
56 | #include "daemon.h" | ||
57 | #include "rio.h" | ||
58 | #include "riospace.h" | ||
59 | #include "top.h" | ||
60 | #include "cmdpkt.h" | ||
61 | #include "map.h" | ||
62 | #include "riotypes.h" | ||
63 | #include "rup.h" | ||
64 | #include "port.h" | ||
65 | #include "riodrvr.h" | ||
66 | #include "rioinfo.h" | ||
67 | #include "func.h" | ||
68 | #include "errors.h" | ||
69 | #include "pci.h" | ||
70 | |||
71 | #include "parmmap.h" | ||
72 | #include "unixrup.h" | ||
73 | #include "board.h" | ||
74 | #include "host.h" | ||
75 | #include "error.h" | ||
76 | #include "phb.h" | ||
77 | #include "link.h" | ||
78 | #include "cmdblk.h" | ||
79 | #include "route.h" | ||
80 | #include "control.h" | ||
81 | #include "cirrus.h" | ||
82 | #include "rioioctl.h" | ||
83 | |||
84 | |||
85 | static struct LpbReq LpbReq; | ||
86 | static struct RupReq RupReq; | ||
87 | static struct PortReq PortReq; | ||
88 | static struct HostReq HostReq; | ||
89 | static struct HostDpRam HostDpRam; | ||
90 | static struct DebugCtrl DebugCtrl; | ||
91 | static struct Map MapEnt; | ||
92 | static struct PortSetup PortSetup; | ||
93 | static struct DownLoad DownLoad; | ||
94 | static struct SendPack SendPack; | ||
95 | /* static struct StreamInfo StreamInfo; */ | ||
96 | /* static char modemtable[RIO_PORTS]; */ | ||
97 | static struct SpecialRupCmd SpecialRupCmd; | ||
98 | static struct PortParams PortParams; | ||
99 | static struct portStats portStats; | ||
100 | |||
101 | static struct SubCmdStruct { | ||
102 | ushort Host; | ||
103 | ushort Rup; | ||
104 | ushort Port; | ||
105 | ushort Addr; | ||
106 | } SubCmd; | ||
107 | |||
108 | struct PortTty { | ||
109 | uint port; | ||
110 | struct ttystatics Tty; | ||
111 | }; | ||
112 | |||
113 | static struct PortTty PortTty; | ||
114 | typedef struct ttystatics TERMIO; | ||
115 | |||
116 | /* | ||
117 | ** This table is used when the config.rio downloads bin code to the | ||
118 | ** driver. We index the table using the product code, 0-F, and call | ||
119 | ** the function pointed to by the entry, passing the information | ||
120 | ** about the boot. | ||
121 | ** The RIOBootCodeUNKNOWN entry is there to politely tell the calling | ||
122 | ** process to bog off. | ||
123 | */ | ||
124 | static int | ||
125 | (*RIOBootTable[MAX_PRODUCT])(struct rio_info *, struct DownLoad *) = | ||
126 | { | ||
127 | /* 0 */ RIOBootCodeHOST, /* Host Card */ | ||
128 | /* 1 */ RIOBootCodeRTA, /* RTA */ | ||
129 | }; | ||
130 | |||
131 | #define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff)) | ||
132 | |||
133 | int copyin (int arg, caddr_t dp, int siz) | ||
134 | { | ||
135 | int rv; | ||
136 | |||
137 | rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes from user %p to %p.\n", siz, (void *)arg, dp); | ||
138 | rv = copy_from_user (dp, (void *)arg, siz); | ||
139 | if (rv) return COPYFAIL; | ||
140 | else return rv; | ||
141 | } | ||
142 | |||
143 | static int copyout (caddr_t dp, int arg, int siz) | ||
144 | { | ||
145 | int rv; | ||
146 | |||
147 | rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes to user %p from %p.\n", siz, (void *)arg, dp); | ||
148 | rv = copy_to_user ((void *)arg, dp, siz); | ||
149 | if (rv) return COPYFAIL; | ||
150 | else return rv; | ||
151 | } | ||
152 | |||
153 | int | ||
154 | riocontrol(p, dev, cmd, arg, su) | ||
155 | struct rio_info * p; | ||
156 | dev_t dev; | ||
157 | int cmd; | ||
158 | caddr_t arg; | ||
159 | int su; | ||
160 | { | ||
161 | uint Host; /* leave me unsigned! */ | ||
162 | uint port; /* and me! */ | ||
163 | struct Host *HostP; | ||
164 | ushort loop; | ||
165 | int Entry; | ||
166 | struct Port *PortP; | ||
167 | PKT *PacketP; | ||
168 | int retval = 0; | ||
169 | unsigned long flags; | ||
170 | |||
171 | func_enter (); | ||
172 | |||
173 | /* Confuse the compiler to think that we've initialized these */ | ||
174 | Host=0; | ||
175 | PortP = NULL; | ||
176 | |||
177 | rio_dprintk (RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%x\n", cmd, (int)arg); | ||
178 | |||
179 | switch (cmd) { | ||
180 | /* | ||
181 | ** RIO_SET_TIMER | ||
182 | ** | ||
183 | ** Change the value of the host card interrupt timer. | ||
184 | ** If the host card number is -1 then all host cards are changed | ||
185 | ** otherwise just the specified host card will be changed. | ||
186 | */ | ||
187 | case RIO_SET_TIMER: | ||
188 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_TIMER to %dms\n", (uint)arg); | ||
189 | { | ||
190 | int host, value; | ||
191 | host = (uint)arg >> 16; | ||
192 | value = (uint)arg & 0x0000ffff; | ||
193 | if (host == -1) { | ||
194 | for (host = 0; host < p->RIONumHosts; host++) { | ||
195 | if (p->RIOHosts[host].Flags == RC_RUNNING) { | ||
196 | WWORD(p->RIOHosts[host].ParmMapP->timer , value); | ||
197 | } | ||
198 | } | ||
199 | } else if (host >= p->RIONumHosts) { | ||
200 | return -EINVAL; | ||
201 | } else { | ||
202 | if ( p->RIOHosts[host].Flags == RC_RUNNING ) { | ||
203 | WWORD(p->RIOHosts[host].ParmMapP->timer , value); | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | return 0; | ||
208 | |||
209 | case RIO_IDENTIFY_DRIVER: | ||
210 | /* | ||
211 | ** 15.10.1998 ARG - ESIL 0760 part fix | ||
212 | ** Added driver ident string output. | ||
213 | ** | ||
214 | #ifndef __THIS_RELEASE__ | ||
215 | #warning Driver Version string not defined ! | ||
216 | #endif | ||
217 | cprintf("%s %s %s %s\n", | ||
218 | RIO_DRV_STR, | ||
219 | __THIS_RELEASE__, | ||
220 | __DATE__, __TIME__ ); | ||
221 | |||
222 | return 0; | ||
223 | |||
224 | case RIO_DISPLAY_HOST_CFG: | ||
225 | ** | ||
226 | ** 15.10.1998 ARG - ESIL 0760 part fix | ||
227 | ** Added driver host card ident string output. | ||
228 | ** | ||
229 | ** Note that the only types currently supported | ||
230 | ** are ISA and PCI. Also this driver does not | ||
231 | ** (yet) distinguish between the Old PCI card | ||
232 | ** and the Jet PCI card. In fact I think this | ||
233 | ** driver only supports JET PCI ! | ||
234 | ** | ||
235 | |||
236 | for (Host = 0; Host < p->RIONumHosts; Host++) | ||
237 | { | ||
238 | HostP = &(p->RIOHosts[Host]); | ||
239 | |||
240 | switch ( HostP->Type ) | ||
241 | { | ||
242 | case RIO_AT : | ||
243 | strcpy( host_type, RIO_AT_HOST_STR ); | ||
244 | break; | ||
245 | |||
246 | case RIO_PCI : | ||
247 | strcpy( host_type, RIO_PCI_HOST_STR ); | ||
248 | break; | ||
249 | |||
250 | default : | ||
251 | strcpy( host_type, "Unknown" ); | ||
252 | break; | ||
253 | } | ||
254 | |||
255 | cprintf( | ||
256 | "RIO Host %d - Type:%s Addr:%X IRQ:%d\n", | ||
257 | Host, host_type, | ||
258 | (uint)HostP->PaddrP, | ||
259 | (int)HostP->Ivec - 32 ); | ||
260 | } | ||
261 | return 0; | ||
262 | ** | ||
263 | */ | ||
264 | |||
265 | case RIO_FOAD_RTA: | ||
266 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n"); | ||
267 | return RIOCommandRta(p, (uint)arg, RIOFoadRta); | ||
268 | |||
269 | case RIO_ZOMBIE_RTA: | ||
270 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n"); | ||
271 | return RIOCommandRta(p, (uint)arg, RIOZombieRta); | ||
272 | |||
273 | case RIO_IDENTIFY_RTA: | ||
274 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n"); | ||
275 | return RIOIdentifyRta(p, arg); | ||
276 | |||
277 | case RIO_KILL_NEIGHBOUR: | ||
278 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n"); | ||
279 | return RIOKillNeighbour(p, arg); | ||
280 | |||
281 | case SPECIAL_RUP_CMD: | ||
282 | { | ||
283 | struct CmdBlk *CmdBlkP; | ||
284 | |||
285 | rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n"); | ||
286 | if (copyin((int)arg, (caddr_t)&SpecialRupCmd, | ||
287 | sizeof(SpecialRupCmd)) == COPYFAIL ) { | ||
288 | rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n"); | ||
289 | p->RIOError.Error = COPYIN_FAILED; | ||
290 | return -EFAULT; | ||
291 | } | ||
292 | CmdBlkP = RIOGetCmdBlk(); | ||
293 | if ( !CmdBlkP ) { | ||
294 | rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n"); | ||
295 | return -ENXIO; | ||
296 | } | ||
297 | CmdBlkP->Packet = SpecialRupCmd.Packet; | ||
298 | if ( SpecialRupCmd.Host >= p->RIONumHosts ) | ||
299 | SpecialRupCmd.Host = 0; | ||
300 | rio_dprintk (RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", | ||
301 | SpecialRupCmd.Host, SpecialRupCmd.RupNum); | ||
302 | if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], | ||
303 | SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) { | ||
304 | cprintf("FAILED TO QUEUE SPECIAL RUP COMMAND\n"); | ||
305 | } | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | case RIO_DEBUG_MEM: | ||
310 | #ifdef DEBUG_MEM_SUPPORT | ||
311 | RIO_DEBUG_CTRL, if (su) | ||
312 | return rio_RIODebugMemory(RIO_DEBUG_CTRL, arg); | ||
313 | else | ||
314 | #endif | ||
315 | return -EPERM; | ||
316 | |||
317 | case RIO_ALL_MODEM: | ||
318 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n"); | ||
319 | p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; | ||
320 | return -EINVAL; | ||
321 | |||
322 | case RIO_GET_TABLE: | ||
323 | /* | ||
324 | ** Read the routing table from the device driver to user space | ||
325 | */ | ||
326 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE\n"); | ||
327 | |||
328 | if ((retval = RIOApel(p)) != 0) | ||
329 | return retval; | ||
330 | |||
331 | if (copyout((caddr_t)p->RIOConnectTable, (int)arg, | ||
332 | TOTAL_MAP_ENTRIES*sizeof(struct Map)) == COPYFAIL) { | ||
333 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n"); | ||
334 | p->RIOError.Error = COPYOUT_FAILED; | ||
335 | return -EFAULT; | ||
336 | } | ||
337 | |||
338 | { | ||
339 | int entry; | ||
340 | rio_dprintk (RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n"); | ||
341 | for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ ) | ||
342 | { | ||
343 | if ((p->RIOConnectTable[entry].ID == 0) && | ||
344 | (p->RIOConnectTable[entry].HostUniqueNum == 0) && | ||
345 | (p->RIOConnectTable[entry].RtaUniqueNum == 0)) continue; | ||
346 | |||
347 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ); | ||
348 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ); | ||
349 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ); | ||
350 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ); | ||
351 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int)p->RIOConnectTable[entry].Flags ); | ||
352 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int)p->RIOConnectTable[entry].SysPort ); | ||
353 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ); | ||
354 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link ); | ||
355 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ); | ||
356 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link ); | ||
357 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ); | ||
358 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link ); | ||
359 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ); | ||
360 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link ); | ||
361 | rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ); | ||
362 | } | ||
363 | rio_dprintk (RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n"); | ||
364 | } | ||
365 | p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */ | ||
366 | return 0; | ||
367 | |||
368 | case RIO_PUT_TABLE: | ||
369 | /* | ||
370 | ** Write the routing table to the device driver from user space | ||
371 | */ | ||
372 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n"); | ||
373 | |||
374 | if ( !su ) { | ||
375 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n"); | ||
376 | p->RIOError.Error = NOT_SUPER_USER; | ||
377 | return -EPERM; | ||
378 | } | ||
379 | if ( copyin((int)arg, (caddr_t)&p->RIOConnectTable[0], | ||
380 | TOTAL_MAP_ENTRIES*sizeof(struct Map) ) == COPYFAIL ) { | ||
381 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n"); | ||
382 | p->RIOError.Error = COPYIN_FAILED; | ||
383 | return -EFAULT; | ||
384 | } | ||
385 | /* | ||
386 | *********************************** | ||
387 | { | ||
388 | int entry; | ||
389 | rio_dprint(RIO_DEBUG_CTRL, ("*****\nMAP ENTRIES\n") ); | ||
390 | for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ ) | ||
391 | { | ||
392 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) ); | ||
393 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) ); | ||
394 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) ); | ||
395 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) ); | ||
396 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) ); | ||
397 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) ); | ||
398 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) ); | ||
399 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) ); | ||
400 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) ); | ||
401 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) ); | ||
402 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) ); | ||
403 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) ); | ||
404 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) ); | ||
405 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) ); | ||
406 | rio_dprint(RIO_DEBUG_CTRL, ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) ); | ||
407 | } | ||
408 | rio_dprint(RIO_DEBUG_CTRL, ("*****\nEND MAP ENTRIES\n") ); | ||
409 | } | ||
410 | *********************************** | ||
411 | */ | ||
412 | return RIONewTable(p); | ||
413 | |||
414 | case RIO_GET_BINDINGS : | ||
415 | /* | ||
416 | ** Send bindings table, containing unique numbers of RTAs owned | ||
417 | ** by this system to user space | ||
418 | */ | ||
419 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n"); | ||
420 | |||
421 | if ( !su ) | ||
422 | { | ||
423 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n"); | ||
424 | p->RIOError.Error = NOT_SUPER_USER; | ||
425 | return -EPERM; | ||
426 | } | ||
427 | if (copyout((caddr_t) p->RIOBindTab, (int)arg, | ||
428 | (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL ) { | ||
429 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n"); | ||
430 | p->RIOError.Error = COPYOUT_FAILED; | ||
431 | return -EFAULT; | ||
432 | } | ||
433 | return 0; | ||
434 | |||
435 | case RIO_PUT_BINDINGS : | ||
436 | /* | ||
437 | ** Receive a bindings table, containing unique numbers of RTAs owned | ||
438 | ** by this system | ||
439 | */ | ||
440 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n"); | ||
441 | |||
442 | if ( !su ) | ||
443 | { | ||
444 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n"); | ||
445 | p->RIOError.Error = NOT_SUPER_USER; | ||
446 | return -EPERM; | ||
447 | } | ||
448 | if (copyin((int)arg, (caddr_t)&p->RIOBindTab[0], | ||
449 | (sizeof(ulong) * MAX_RTA_BINDINGS))==COPYFAIL ) { | ||
450 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n"); | ||
451 | p->RIOError.Error = COPYIN_FAILED; | ||
452 | return -EFAULT; | ||
453 | } | ||
454 | return 0; | ||
455 | |||
456 | case RIO_BIND_RTA : | ||
457 | { | ||
458 | int EmptySlot = -1; | ||
459 | /* | ||
460 | ** Bind this RTA to host, so that it will be booted by | ||
461 | ** host in 'boot owned RTAs' mode. | ||
462 | */ | ||
463 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA\n"); | ||
464 | |||
465 | if ( !su ) { | ||
466 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n"); | ||
467 | p->RIOError.Error = NOT_SUPER_USER; | ||
468 | return -EPERM; | ||
469 | } | ||
470 | for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) { | ||
471 | if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L)) | ||
472 | EmptySlot = Entry; | ||
473 | else if (p->RIOBindTab[Entry] == (int) arg) { | ||
474 | /* | ||
475 | ** Already exists - delete | ||
476 | */ | ||
477 | p->RIOBindTab[Entry] = 0L; | ||
478 | rio_dprintk (RIO_DEBUG_CTRL, "Removing Rta %x from p->RIOBindTab\n", | ||
479 | (int) arg); | ||
480 | return 0; | ||
481 | } | ||
482 | } | ||
483 | /* | ||
484 | ** Dosen't exist - add | ||
485 | */ | ||
486 | if (EmptySlot != -1) { | ||
487 | p->RIOBindTab[EmptySlot] = (int) arg; | ||
488 | rio_dprintk (RIO_DEBUG_CTRL, "Adding Rta %x to p->RIOBindTab\n", | ||
489 | (int) arg); | ||
490 | } | ||
491 | else { | ||
492 | rio_dprintk (RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n", | ||
493 | (int) arg); | ||
494 | return -ENOMEM; | ||
495 | } | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | case RIO_RESUME : | ||
500 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME\n"); | ||
501 | port = (uint) arg; | ||
502 | if ((port < 0) || (port > 511)) { | ||
503 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port); | ||
504 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
505 | return -EINVAL; | ||
506 | } | ||
507 | PortP = p->RIOPortp[port]; | ||
508 | if (!PortP->Mapped) { | ||
509 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port); | ||
510 | p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM; | ||
511 | return -EINVAL; | ||
512 | } | ||
513 | if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) { | ||
514 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port); | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | |||
518 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
519 | if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) == | ||
520 | RIO_FAIL) { | ||
521 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME failed\n"); | ||
522 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
523 | return -EBUSY; | ||
524 | } | ||
525 | else { | ||
526 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port); | ||
527 | PortP->State |= RIO_BUSY; | ||
528 | } | ||
529 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
530 | return retval; | ||
531 | |||
532 | case RIO_ASSIGN_RTA: | ||
533 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n"); | ||
534 | if ( !su ) { | ||
535 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n"); | ||
536 | p->RIOError.Error = NOT_SUPER_USER; | ||
537 | return -EPERM; | ||
538 | } | ||
539 | if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt)) | ||
540 | == COPYFAIL) { | ||
541 | rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n"); | ||
542 | p->RIOError.Error = COPYIN_FAILED; | ||
543 | return -EFAULT; | ||
544 | } | ||
545 | return RIOAssignRta(p, &MapEnt); | ||
546 | |||
547 | case RIO_CHANGE_NAME: | ||
548 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n"); | ||
549 | if ( !su ) { | ||
550 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n"); | ||
551 | p->RIOError.Error = NOT_SUPER_USER; | ||
552 | return -EPERM; | ||
553 | } | ||
554 | if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt)) | ||
555 | == COPYFAIL) { | ||
556 | rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n"); | ||
557 | p->RIOError.Error = COPYIN_FAILED; | ||
558 | return -EFAULT; | ||
559 | } | ||
560 | return RIOChangeName(p, &MapEnt); | ||
561 | |||
562 | case RIO_DELETE_RTA: | ||
563 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n"); | ||
564 | if ( !su ) { | ||
565 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n"); | ||
566 | p->RIOError.Error = NOT_SUPER_USER; | ||
567 | return -EPERM; | ||
568 | } | ||
569 | if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt)) | ||
570 | == COPYFAIL ) { | ||
571 | rio_dprintk (RIO_DEBUG_CTRL, "Copy from data space failed\n"); | ||
572 | p->RIOError.Error = COPYIN_FAILED; | ||
573 | return -EFAULT; | ||
574 | } | ||
575 | return RIODeleteRta(p, &MapEnt); | ||
576 | |||
577 | case RIO_QUICK_CHECK: | ||
578 | /* | ||
579 | ** 09.12.1998 ARG - ESIL 0776 part fix | ||
580 | ** A customer was using this to get the RTAs | ||
581 | ** connect/disconnect status. | ||
582 | ** RIOConCon() had been botched use RIOHalted | ||
583 | ** to keep track of RTA connections and | ||
584 | ** disconnections. That has been changed and | ||
585 | ** RIORtaDisCons in the rio_info struct now | ||
586 | ** does the job. So we need to return the value | ||
587 | ** of RIORtaCons instead of RIOHalted. | ||
588 | ** | ||
589 | if (copyout((caddr_t)&p->RIOHalted,(int)arg, | ||
590 | sizeof(uint))==COPYFAIL) { | ||
591 | ** | ||
592 | */ | ||
593 | |||
594 | if (copyout((caddr_t)&p->RIORtaDisCons,(int)arg, | ||
595 | sizeof(uint))==COPYFAIL) { | ||
596 | p->RIOError.Error = COPYOUT_FAILED; | ||
597 | return -EFAULT; | ||
598 | } | ||
599 | return 0; | ||
600 | |||
601 | case RIO_LAST_ERROR: | ||
602 | if (copyout((caddr_t)&p->RIOError, (int)arg, | ||
603 | sizeof(struct Error)) ==COPYFAIL ) | ||
604 | return -EFAULT; | ||
605 | return 0; | ||
606 | |||
607 | case RIO_GET_LOG: | ||
608 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_LOG\n"); | ||
609 | #ifdef LOGGING | ||
610 | RIOGetLog(arg); | ||
611 | return 0; | ||
612 | #else | ||
613 | return -EINVAL; | ||
614 | #endif | ||
615 | |||
616 | case RIO_GET_MODTYPE: | ||
617 | if ( copyin( (int)arg, (caddr_t)&port, | ||
618 | sizeof(uint)) == COPYFAIL ) | ||
619 | { | ||
620 | p->RIOError.Error = COPYIN_FAILED; | ||
621 | return -EFAULT; | ||
622 | } | ||
623 | rio_dprintk (RIO_DEBUG_CTRL, "Get module type for port %d\n", port); | ||
624 | if ( port < 0 || port > 511 ) | ||
625 | { | ||
626 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port); | ||
627 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
628 | return -EINVAL; | ||
629 | } | ||
630 | PortP = (p->RIOPortp[port]); | ||
631 | if (!PortP->Mapped) | ||
632 | { | ||
633 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port); | ||
634 | p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM; | ||
635 | return -EINVAL; | ||
636 | } | ||
637 | /* | ||
638 | ** Return module type of port | ||
639 | */ | ||
640 | port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes; | ||
641 | if (copyout((caddr_t)&port, (int)arg, | ||
642 | sizeof(uint)) == COPYFAIL) { | ||
643 | p->RIOError.Error = COPYOUT_FAILED; | ||
644 | return -EFAULT; | ||
645 | } | ||
646 | return(0); | ||
647 | /* | ||
648 | ** 02.03.1999 ARG - ESIL 0820 fix | ||
649 | ** We are no longer using "Boot Mode", so these ioctls | ||
650 | ** are not required : | ||
651 | ** | ||
652 | case RIO_GET_BOOT_MODE : | ||
653 | rio_dprint(RIO_DEBUG_CTRL, ("Get boot mode - %x\n", p->RIOBootMode)); | ||
654 | ** | ||
655 | ** Return boot state of system - BOOT_ALL, BOOT_OWN or BOOT_NONE | ||
656 | ** | ||
657 | if (copyout((caddr_t)&p->RIOBootMode, (int)arg, | ||
658 | sizeof(p->RIOBootMode)) == COPYFAIL) { | ||
659 | p->RIOError.Error = COPYOUT_FAILED; | ||
660 | return -EFAULT; | ||
661 | } | ||
662 | return(0); | ||
663 | |||
664 | case RIO_SET_BOOT_MODE : | ||
665 | p->RIOBootMode = (uint) arg; | ||
666 | rio_dprint(RIO_DEBUG_CTRL, ("Set boot mode to 0x%x\n", p->RIOBootMode)); | ||
667 | return(0); | ||
668 | ** | ||
669 | ** End ESIL 0820 fix | ||
670 | */ | ||
671 | |||
672 | case RIO_BLOCK_OPENS: | ||
673 | rio_dprintk (RIO_DEBUG_CTRL, "Opens block until booted\n"); | ||
674 | for ( Entry=0; Entry < RIO_PORTS; Entry++ ) { | ||
675 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
676 | p->RIOPortp[Entry]->WaitUntilBooted = 1; | ||
677 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
678 | } | ||
679 | return 0; | ||
680 | |||
681 | case RIO_SETUP_PORTS: | ||
682 | rio_dprintk (RIO_DEBUG_CTRL, "Setup ports\n"); | ||
683 | if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) | ||
684 | == COPYFAIL ) { | ||
685 | p->RIOError.Error = COPYIN_FAILED; | ||
686 | rio_dprintk (RIO_DEBUG_CTRL, "EFAULT"); | ||
687 | return -EFAULT; | ||
688 | } | ||
689 | if ( PortSetup.From > PortSetup.To || | ||
690 | PortSetup.To >= RIO_PORTS ) { | ||
691 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
692 | rio_dprintk (RIO_DEBUG_CTRL, "ENXIO"); | ||
693 | return -ENXIO; | ||
694 | } | ||
695 | if ( PortSetup.XpCps > p->RIOConf.MaxXpCps || | ||
696 | PortSetup.XpCps < p->RIOConf.MinXpCps ) { | ||
697 | p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE; | ||
698 | rio_dprintk (RIO_DEBUG_CTRL, "EINVAL"); | ||
699 | return -EINVAL; | ||
700 | } | ||
701 | if ( !p->RIOPortp ) { | ||
702 | cprintf("No p->RIOPortp array!\n"); | ||
703 | rio_dprintk (RIO_DEBUG_CTRL, "No p->RIOPortp array!\n"); | ||
704 | return -EIO; | ||
705 | } | ||
706 | rio_dprintk (RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To); | ||
707 | for (loop=PortSetup.From; loop<=PortSetup.To; loop++) { | ||
708 | rio_dprintk (RIO_DEBUG_CTRL, "in loop (%d)!\n", loop); | ||
709 | #if 0 | ||
710 | PortP = p->RIOPortp[loop]; | ||
711 | if ( !PortP->TtyP ) | ||
712 | PortP->TtyP = &p->channel[loop]; | ||
713 | |||
714 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
715 | if ( PortSetup.IxAny ) | ||
716 | PortP->Config |= RIO_IXANY; | ||
717 | else | ||
718 | PortP->Config &= ~RIO_IXANY; | ||
719 | if ( PortSetup.IxOn ) | ||
720 | PortP->Config |= RIO_IXON; | ||
721 | else | ||
722 | PortP->Config &= ~RIO_IXON; | ||
723 | |||
724 | /* | ||
725 | ** If the port needs to wait for all a processes output | ||
726 | ** to drain before closing then this flag will be set. | ||
727 | */ | ||
728 | if (PortSetup.Drain) { | ||
729 | PortP->Config |= RIO_WAITDRAIN; | ||
730 | } else { | ||
731 | PortP->Config &= ~RIO_WAITDRAIN; | ||
732 | } | ||
733 | /* | ||
734 | ** Store settings if locking or unlocking port or if the | ||
735 | ** port is not locked, when setting the store option. | ||
736 | */ | ||
737 | if (PortP->Mapped && | ||
738 | ((PortSetup.Lock && !PortP->Lock) || | ||
739 | (!PortP->Lock && | ||
740 | (PortSetup.Store && !PortP->Store)))) { | ||
741 | PortP->StoredTty.iflag = PortP->TtyP->tm.c_iflag; | ||
742 | PortP->StoredTty.oflag = PortP->TtyP->tm.c_oflag; | ||
743 | PortP->StoredTty.cflag = PortP->TtyP->tm.c_cflag; | ||
744 | PortP->StoredTty.lflag = PortP->TtyP->tm.c_lflag; | ||
745 | PortP->StoredTty.line = PortP->TtyP->tm.c_line; | ||
746 | bcopy(PortP->TtyP->tm.c_cc, PortP->StoredTty.cc, | ||
747 | NCC + 5); | ||
748 | } | ||
749 | PortP->Lock = PortSetup.Lock; | ||
750 | PortP->Store = PortSetup.Store; | ||
751 | PortP->Xprint.XpCps = PortSetup.XpCps; | ||
752 | bcopy(PortSetup.XpOn,PortP->Xprint.XpOn,MAX_XP_CTRL_LEN); | ||
753 | bcopy(PortSetup.XpOff,PortP->Xprint.XpOff,MAX_XP_CTRL_LEN); | ||
754 | PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0'; | ||
755 | PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0'; | ||
756 | PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+ | ||
757 | RIOStrlen(PortP->Xprint.XpOff); | ||
758 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
759 | #endif | ||
760 | } | ||
761 | rio_dprintk (RIO_DEBUG_CTRL, "after loop (%d)!\n", loop); | ||
762 | rio_dprintk (RIO_DEBUG_CTRL, "Retval:%x\n", retval); | ||
763 | return retval; | ||
764 | |||
765 | case RIO_GET_PORT_SETUP : | ||
766 | rio_dprintk (RIO_DEBUG_CTRL, "Get port setup\n"); | ||
767 | if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup)) | ||
768 | == COPYFAIL ) { | ||
769 | p->RIOError.Error = COPYIN_FAILED; | ||
770 | return -EFAULT; | ||
771 | } | ||
772 | if ( PortSetup.From >= RIO_PORTS ) { | ||
773 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
774 | return -ENXIO; | ||
775 | } | ||
776 | |||
777 | port = PortSetup.To = PortSetup.From; | ||
778 | PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? | ||
779 | 1 : 0; | ||
780 | PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? | ||
781 | 1 : 0; | ||
782 | PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? | ||
783 | 1 : 0; | ||
784 | PortSetup.Store = p->RIOPortp[port]->Store; | ||
785 | PortSetup.Lock = p->RIOPortp[port]->Lock; | ||
786 | PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps; | ||
787 | bcopy(p->RIOPortp[port]->Xprint.XpOn, PortSetup.XpOn, | ||
788 | MAX_XP_CTRL_LEN); | ||
789 | bcopy(p->RIOPortp[port]->Xprint.XpOff, PortSetup.XpOff, | ||
790 | MAX_XP_CTRL_LEN); | ||
791 | PortSetup.XpOn[MAX_XP_CTRL_LEN-1] = '\0'; | ||
792 | PortSetup.XpOff[MAX_XP_CTRL_LEN-1] = '\0'; | ||
793 | |||
794 | if ( copyout((caddr_t)&PortSetup,(int)arg,sizeof(PortSetup)) | ||
795 | ==COPYFAIL ) { | ||
796 | p->RIOError.Error = COPYOUT_FAILED; | ||
797 | return -EFAULT; | ||
798 | } | ||
799 | return retval; | ||
800 | |||
801 | case RIO_GET_PORT_PARAMS : | ||
802 | rio_dprintk (RIO_DEBUG_CTRL, "Get port params\n"); | ||
803 | if (copyin( (int)arg, (caddr_t)&PortParams, | ||
804 | sizeof(struct PortParams)) == COPYFAIL) { | ||
805 | p->RIOError.Error = COPYIN_FAILED; | ||
806 | return -EFAULT; | ||
807 | } | ||
808 | if (PortParams.Port >= RIO_PORTS) { | ||
809 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
810 | return -ENXIO; | ||
811 | } | ||
812 | PortP = (p->RIOPortp[PortParams.Port]); | ||
813 | PortParams.Config = PortP->Config; | ||
814 | PortParams.State = PortP->State; | ||
815 | rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port); | ||
816 | |||
817 | if (copyout((caddr_t)&PortParams, (int)arg, | ||
818 | sizeof(struct PortParams)) == COPYFAIL ) { | ||
819 | p->RIOError.Error = COPYOUT_FAILED; | ||
820 | return -EFAULT; | ||
821 | } | ||
822 | return retval; | ||
823 | |||
824 | case RIO_GET_PORT_TTY : | ||
825 | rio_dprintk (RIO_DEBUG_CTRL, "Get port tty\n"); | ||
826 | if (copyin((int)arg, (caddr_t)&PortTty, sizeof(struct PortTty)) | ||
827 | == COPYFAIL) { | ||
828 | p->RIOError.Error = COPYIN_FAILED; | ||
829 | return -EFAULT; | ||
830 | } | ||
831 | if ( PortTty.port >= RIO_PORTS ) { | ||
832 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
833 | return -ENXIO; | ||
834 | } | ||
835 | |||
836 | rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortTty.port); | ||
837 | PortP = (p->RIOPortp[PortTty.port]); | ||
838 | #if 0 | ||
839 | PortTty.Tty.tm.c_iflag = PortP->TtyP->tm.c_iflag; | ||
840 | PortTty.Tty.tm.c_oflag = PortP->TtyP->tm.c_oflag; | ||
841 | PortTty.Tty.tm.c_cflag = PortP->TtyP->tm.c_cflag; | ||
842 | PortTty.Tty.tm.c_lflag = PortP->TtyP->tm.c_lflag; | ||
843 | #endif | ||
844 | if (copyout((caddr_t)&PortTty, (int)arg, | ||
845 | sizeof(struct PortTty)) == COPYFAIL) { | ||
846 | p->RIOError.Error = COPYOUT_FAILED; | ||
847 | return -EFAULT; | ||
848 | } | ||
849 | return retval; | ||
850 | |||
851 | case RIO_SET_PORT_TTY : | ||
852 | if (copyin((int)arg, (caddr_t)&PortTty, | ||
853 | sizeof(struct PortTty)) == COPYFAIL) { | ||
854 | p->RIOError.Error = COPYIN_FAILED; | ||
855 | return -EFAULT; | ||
856 | } | ||
857 | rio_dprintk (RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port); | ||
858 | if (PortTty.port >= (ushort) RIO_PORTS) { | ||
859 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
860 | return -ENXIO; | ||
861 | } | ||
862 | PortP = (p->RIOPortp[PortTty.port]); | ||
863 | #if 0 | ||
864 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
865 | PortP->TtyP->tm.c_iflag = PortTty.Tty.tm.c_iflag; | ||
866 | PortP->TtyP->tm.c_oflag = PortTty.Tty.tm.c_oflag; | ||
867 | PortP->TtyP->tm.c_cflag = PortTty.Tty.tm.c_cflag; | ||
868 | PortP->TtyP->tm.c_lflag = PortTty.Tty.tm.c_lflag; | ||
869 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
870 | #endif | ||
871 | |||
872 | RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP); | ||
873 | return retval; | ||
874 | |||
875 | case RIO_SET_PORT_PARAMS : | ||
876 | rio_dprintk (RIO_DEBUG_CTRL, "Set port params\n"); | ||
877 | if ( copyin((int)arg, (caddr_t)&PortParams, sizeof(PortParams)) | ||
878 | == COPYFAIL ) { | ||
879 | p->RIOError.Error = COPYIN_FAILED; | ||
880 | return -EFAULT; | ||
881 | } | ||
882 | if (PortParams.Port >= (ushort) RIO_PORTS) { | ||
883 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
884 | return -ENXIO; | ||
885 | } | ||
886 | PortP = (p->RIOPortp[PortParams.Port]); | ||
887 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
888 | PortP->Config = PortParams.Config; | ||
889 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
890 | return retval; | ||
891 | |||
892 | case RIO_GET_PORT_STATS : | ||
893 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n"); | ||
894 | if ( copyin((int)arg, (caddr_t)&portStats, | ||
895 | sizeof(struct portStats)) == COPYFAIL ) { | ||
896 | p->RIOError.Error = COPYIN_FAILED; | ||
897 | return -EFAULT; | ||
898 | } | ||
899 | if ( portStats.port >= RIO_PORTS ) { | ||
900 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
901 | return -ENXIO; | ||
902 | } | ||
903 | PortP = (p->RIOPortp[portStats.port]); | ||
904 | portStats.gather = PortP->statsGather; | ||
905 | portStats.txchars = PortP->txchars; | ||
906 | portStats.rxchars = PortP->rxchars; | ||
907 | portStats.opens = PortP->opens; | ||
908 | portStats.closes = PortP->closes; | ||
909 | portStats.ioctls = PortP->ioctls; | ||
910 | if ( copyout((caddr_t)&portStats, (int)arg, | ||
911 | sizeof(struct portStats)) == COPYFAIL ) { | ||
912 | p->RIOError.Error = COPYOUT_FAILED; | ||
913 | return -EFAULT; | ||
914 | } | ||
915 | return retval; | ||
916 | |||
917 | case RIO_RESET_PORT_STATS : | ||
918 | port = (uint) arg; | ||
919 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n"); | ||
920 | if ( port >= RIO_PORTS ) { | ||
921 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
922 | return -ENXIO; | ||
923 | } | ||
924 | PortP = (p->RIOPortp[port]); | ||
925 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
926 | PortP->txchars = 0; | ||
927 | PortP->rxchars = 0; | ||
928 | PortP->opens = 0; | ||
929 | PortP->closes = 0; | ||
930 | PortP->ioctls = 0; | ||
931 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
932 | return retval; | ||
933 | |||
934 | case RIO_GATHER_PORT_STATS : | ||
935 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n"); | ||
936 | if ( copyin( (int)arg, (caddr_t)&portStats, | ||
937 | sizeof(struct portStats)) == COPYFAIL ) { | ||
938 | p->RIOError.Error = COPYIN_FAILED; | ||
939 | return -EFAULT; | ||
940 | } | ||
941 | if ( portStats.port >= RIO_PORTS ) { | ||
942 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
943 | return -ENXIO; | ||
944 | } | ||
945 | PortP = (p->RIOPortp[portStats.port]); | ||
946 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
947 | PortP->statsGather = portStats.gather; | ||
948 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
949 | return retval; | ||
950 | |||
951 | #ifdef DEBUG_SUPPORTED | ||
952 | case RIO_READ_LEVELS: | ||
953 | { | ||
954 | int num; | ||
955 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_LEVELS\n"); | ||
956 | for ( num=0; RIODbInf[num].Flag; num++ ) ; | ||
957 | rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copy\n",num); | ||
958 | if (copyout((caddr_t)RIODbInf,(int)arg, | ||
959 | sizeof(struct DbInf)*(num+1))==COPYFAIL) { | ||
960 | rio_dprintk (RIO_DEBUG_CTRL, "ReadLevels Copy failed\n"); | ||
961 | p->RIOError.Error = COPYOUT_FAILED; | ||
962 | return -EFAULT; | ||
963 | } | ||
964 | rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copied\n",num); | ||
965 | return retval; | ||
966 | } | ||
967 | #endif | ||
968 | |||
969 | case RIO_READ_CONFIG: | ||
970 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n"); | ||
971 | if (copyout((caddr_t)&p->RIOConf, (int)arg, | ||
972 | sizeof(struct Conf)) ==COPYFAIL ) { | ||
973 | p->RIOError.Error = COPYOUT_FAILED; | ||
974 | return -EFAULT; | ||
975 | } | ||
976 | return retval; | ||
977 | |||
978 | case RIO_SET_CONFIG: | ||
979 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n"); | ||
980 | if ( !su ) { | ||
981 | p->RIOError.Error = NOT_SUPER_USER; | ||
982 | return -EPERM; | ||
983 | } | ||
984 | if ( copyin((int)arg, (caddr_t)&p->RIOConf, sizeof(struct Conf) ) | ||
985 | ==COPYFAIL ) { | ||
986 | p->RIOError.Error = COPYIN_FAILED; | ||
987 | return -EFAULT; | ||
988 | } | ||
989 | /* | ||
990 | ** move a few value around | ||
991 | */ | ||
992 | for (Host=0; Host < p->RIONumHosts; Host++) | ||
993 | if ( (p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING ) | ||
994 | WWORD(p->RIOHosts[Host].ParmMapP->timer , | ||
995 | p->RIOConf.Timer); | ||
996 | return retval; | ||
997 | |||
998 | case RIO_START_POLLER: | ||
999 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_START_POLLER\n"); | ||
1000 | return -EINVAL; | ||
1001 | |||
1002 | case RIO_STOP_POLLER: | ||
1003 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n"); | ||
1004 | if ( !su ) { | ||
1005 | p->RIOError.Error = NOT_SUPER_USER; | ||
1006 | return -EPERM; | ||
1007 | } | ||
1008 | p->RIOPolling = NOT_POLLING; | ||
1009 | return retval; | ||
1010 | |||
1011 | case RIO_SETDEBUG: | ||
1012 | case RIO_GETDEBUG: | ||
1013 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n"); | ||
1014 | if ( copyin( (int)arg, (caddr_t)&DebugCtrl, sizeof(DebugCtrl) ) | ||
1015 | ==COPYFAIL ) { | ||
1016 | p->RIOError.Error = COPYIN_FAILED; | ||
1017 | return -EFAULT; | ||
1018 | } | ||
1019 | if ( DebugCtrl.SysPort == NO_PORT ) { | ||
1020 | if ( cmd == RIO_SETDEBUG ) { | ||
1021 | if ( !su ) { | ||
1022 | p->RIOError.Error = NOT_SUPER_USER; | ||
1023 | return -EPERM; | ||
1024 | } | ||
1025 | p->rio_debug = DebugCtrl.Debug; | ||
1026 | p->RIODebugWait = DebugCtrl.Wait; | ||
1027 | rio_dprintk (RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", | ||
1028 | p->rio_debug,p->RIODebugWait); | ||
1029 | } | ||
1030 | else { | ||
1031 | rio_dprintk (RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", | ||
1032 | p->rio_debug,p->RIODebugWait); | ||
1033 | DebugCtrl.Debug = p->rio_debug; | ||
1034 | DebugCtrl.Wait = p->RIODebugWait; | ||
1035 | if ( copyout((caddr_t)&DebugCtrl,(int)arg, | ||
1036 | sizeof(DebugCtrl)) == COPYFAIL ) { | ||
1037 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", | ||
1038 | DebugCtrl.SysPort); | ||
1039 | p->RIOError.Error = COPYOUT_FAILED; | ||
1040 | return -EFAULT; | ||
1041 | } | ||
1042 | } | ||
1043 | } | ||
1044 | else if ( DebugCtrl.SysPort >= RIO_PORTS && | ||
1045 | DebugCtrl.SysPort != NO_PORT ) { | ||
1046 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", | ||
1047 | DebugCtrl.SysPort); | ||
1048 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1049 | return -ENXIO; | ||
1050 | } | ||
1051 | else if ( cmd == RIO_SETDEBUG ) { | ||
1052 | if ( !su ) { | ||
1053 | p->RIOError.Error = NOT_SUPER_USER; | ||
1054 | return -EPERM; | ||
1055 | } | ||
1056 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1057 | p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug; | ||
1058 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1059 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", | ||
1060 | p->RIOPortp[DebugCtrl.SysPort]->Debug); | ||
1061 | } | ||
1062 | else { | ||
1063 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", | ||
1064 | p->RIOPortp[DebugCtrl.SysPort]->Debug); | ||
1065 | DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug; | ||
1066 | if ( copyout((caddr_t)&DebugCtrl,(int)arg, | ||
1067 | sizeof(DebugCtrl))==COPYFAIL ) { | ||
1068 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n"); | ||
1069 | p->RIOError.Error = COPYOUT_FAILED; | ||
1070 | return -EFAULT; | ||
1071 | } | ||
1072 | } | ||
1073 | return retval; | ||
1074 | |||
1075 | case RIO_VERSID: | ||
1076 | /* | ||
1077 | ** Enquire about the release and version. | ||
1078 | ** We return MAX_VERSION_LEN bytes, being a | ||
1079 | ** textual null terminated string. | ||
1080 | */ | ||
1081 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID\n"); | ||
1082 | if ( copyout( (caddr_t)RIOVersid(), | ||
1083 | (int)arg, | ||
1084 | sizeof(struct rioVersion) ) == COPYFAIL ) | ||
1085 | { | ||
1086 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host); | ||
1087 | p->RIOError.Error = COPYOUT_FAILED; | ||
1088 | return -EFAULT; | ||
1089 | } | ||
1090 | return retval; | ||
1091 | |||
1092 | /* | ||
1093 | ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
1094 | ** !! commented out previous 'RIO_VERSID' functionality !! | ||
1095 | ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
1096 | ** | ||
1097 | case RIO_VERSID: | ||
1098 | ** | ||
1099 | ** Enquire about the release and version. | ||
1100 | ** We return MAX_VERSION_LEN bytes, being a textual null | ||
1101 | ** terminated string. | ||
1102 | ** | ||
1103 | rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n")); | ||
1104 | if (copyout((caddr_t)RIOVersid(), | ||
1105 | (int)arg, MAX_VERSION_LEN ) == COPYFAIL ) { | ||
1106 | rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space\n",Host)); | ||
1107 | p->RIOError.Error = COPYOUT_FAILED; | ||
1108 | return -EFAULT; | ||
1109 | } | ||
1110 | return retval; | ||
1111 | ** | ||
1112 | ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
1113 | */ | ||
1114 | |||
1115 | case RIO_NUM_HOSTS: | ||
1116 | /* | ||
1117 | ** Enquire as to the number of hosts located | ||
1118 | ** at init time. | ||
1119 | */ | ||
1120 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n"); | ||
1121 | if (copyout((caddr_t)&p->RIONumHosts, (int)arg, | ||
1122 | sizeof(p->RIONumHosts) )==COPYFAIL ) { | ||
1123 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n"); | ||
1124 | p->RIOError.Error = COPYOUT_FAILED; | ||
1125 | return -EFAULT; | ||
1126 | } | ||
1127 | return retval; | ||
1128 | |||
1129 | case RIO_HOST_FOAD: | ||
1130 | /* | ||
1131 | ** Kill host. This may not be in the final version... | ||
1132 | */ | ||
1133 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD %d\n", (int)arg); | ||
1134 | if ( !su ) { | ||
1135 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n"); | ||
1136 | p->RIOError.Error = NOT_SUPER_USER; | ||
1137 | return -EPERM; | ||
1138 | } | ||
1139 | p->RIOHalted = 1; | ||
1140 | p->RIOSystemUp = 0; | ||
1141 | |||
1142 | for ( Host=0; Host<p->RIONumHosts; Host++ ) { | ||
1143 | (void)RIOBoardTest( p->RIOHosts[Host].PaddrP, | ||
1144 | p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, | ||
1145 | p->RIOHosts[Host].Slot ); | ||
1146 | bzero( (caddr_t)&p->RIOHosts[Host].Flags, | ||
1147 | ((int)&p->RIOHosts[Host].____end_marker____) - | ||
1148 | ((int)&p->RIOHosts[Host].Flags) ); | ||
1149 | p->RIOHosts[Host].Flags = RC_WAITING; | ||
1150 | #if 0 | ||
1151 | RIOSetupDataStructs(p); | ||
1152 | #endif | ||
1153 | } | ||
1154 | RIOFoadWakeup(p); | ||
1155 | p->RIONumBootPkts = 0; | ||
1156 | p->RIOBooting = 0; | ||
1157 | |||
1158 | #ifdef RINGBUFFER_SUPPORT | ||
1159 | for( loop=0; loop<RIO_PORTS; loop++ ) | ||
1160 | if ( p->RIOPortp[loop]->TxRingBuffer ) | ||
1161 | sysfree((void *)p->RIOPortp[loop]->TxRingBuffer, | ||
1162 | RIOBufferSize ); | ||
1163 | #endif | ||
1164 | #if 0 | ||
1165 | bzero((caddr_t)&p->RIOPortp[0],RIO_PORTS*sizeof(struct Port)); | ||
1166 | #else | ||
1167 | printk ("HEEEEELP!\n"); | ||
1168 | #endif | ||
1169 | |||
1170 | for( loop=0; loop<RIO_PORTS; loop++ ) { | ||
1171 | #if 0 | ||
1172 | p->RIOPortp[loop]->TtyP = &p->channel[loop]; | ||
1173 | #endif | ||
1174 | |||
1175 | spin_lock_init(&p->RIOPortp[loop]->portSem); | ||
1176 | p->RIOPortp[loop]->InUse = NOT_INUSE; | ||
1177 | } | ||
1178 | |||
1179 | p->RIOSystemUp = 0; | ||
1180 | return retval; | ||
1181 | |||
1182 | case RIO_DOWNLOAD: | ||
1183 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n"); | ||
1184 | if ( !su ) { | ||
1185 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n"); | ||
1186 | p->RIOError.Error = NOT_SUPER_USER; | ||
1187 | return -EPERM; | ||
1188 | } | ||
1189 | if ( copyin((int)arg, (caddr_t)&DownLoad, | ||
1190 | sizeof(DownLoad) )==COPYFAIL ) { | ||
1191 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n"); | ||
1192 | p->RIOError.Error = COPYIN_FAILED; | ||
1193 | return -EFAULT; | ||
1194 | } | ||
1195 | rio_dprintk (RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", | ||
1196 | DownLoad.ProductCode); | ||
1197 | |||
1198 | /* | ||
1199 | ** It is important that the product code is an unsigned object! | ||
1200 | */ | ||
1201 | if ( DownLoad.ProductCode > MAX_PRODUCT ) { | ||
1202 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", | ||
1203 | DownLoad.ProductCode); | ||
1204 | p->RIOError.Error = NO_SUCH_PRODUCT; | ||
1205 | return -ENXIO; | ||
1206 | } | ||
1207 | /* | ||
1208 | ** do something! | ||
1209 | */ | ||
1210 | retval = (*(RIOBootTable[DownLoad.ProductCode]))(p, &DownLoad); | ||
1211 | /* <-- Panic */ | ||
1212 | p->RIOHalted = 0; | ||
1213 | /* | ||
1214 | ** and go back, content with a job well completed. | ||
1215 | */ | ||
1216 | return retval; | ||
1217 | |||
1218 | case RIO_PARMS: | ||
1219 | { | ||
1220 | uint host; | ||
1221 | |||
1222 | if (copyin((int)arg, (caddr_t)&host, | ||
1223 | sizeof(host) ) == COPYFAIL ) { | ||
1224 | rio_dprintk (RIO_DEBUG_CTRL, | ||
1225 | "RIO_HOST_REQ: Copy in from user space failed\n"); | ||
1226 | p->RIOError.Error = COPYIN_FAILED; | ||
1227 | return -EFAULT; | ||
1228 | } | ||
1229 | /* | ||
1230 | ** Fetch the parmmap | ||
1231 | */ | ||
1232 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS\n"); | ||
1233 | if ( copyout( (caddr_t)p->RIOHosts[host].ParmMapP, | ||
1234 | (int)arg, sizeof(PARM_MAP) )==COPYFAIL ) { | ||
1235 | p->RIOError.Error = COPYOUT_FAILED; | ||
1236 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n"); | ||
1237 | return -EFAULT; | ||
1238 | } | ||
1239 | } | ||
1240 | return retval; | ||
1241 | |||
1242 | case RIO_HOST_REQ: | ||
1243 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ\n"); | ||
1244 | if (copyin((int)arg, (caddr_t)&HostReq, | ||
1245 | sizeof(HostReq) )==COPYFAIL ) { | ||
1246 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n"); | ||
1247 | p->RIOError.Error = COPYIN_FAILED; | ||
1248 | return -EFAULT; | ||
1249 | } | ||
1250 | if ( HostReq.HostNum >= p->RIONumHosts ) { | ||
1251 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1252 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", | ||
1253 | HostReq.HostNum); | ||
1254 | return -ENXIO; | ||
1255 | } | ||
1256 | rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum); | ||
1257 | |||
1258 | if (copyout((caddr_t)&p->RIOHosts[HostReq.HostNum], | ||
1259 | (int)HostReq.HostP,sizeof(struct Host) ) == COPYFAIL) { | ||
1260 | p->RIOError.Error = COPYOUT_FAILED; | ||
1261 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n"); | ||
1262 | return -EFAULT; | ||
1263 | } | ||
1264 | return retval; | ||
1265 | |||
1266 | case RIO_HOST_DPRAM: | ||
1267 | rio_dprintk (RIO_DEBUG_CTRL, "Request for DPRAM\n"); | ||
1268 | if ( copyin( (int)arg, (caddr_t)&HostDpRam, | ||
1269 | sizeof(HostDpRam) )==COPYFAIL ) { | ||
1270 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n"); | ||
1271 | p->RIOError.Error = COPYIN_FAILED; | ||
1272 | return -EFAULT; | ||
1273 | } | ||
1274 | if ( HostDpRam.HostNum >= p->RIONumHosts ) { | ||
1275 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1276 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", | ||
1277 | HostDpRam.HostNum); | ||
1278 | return -ENXIO; | ||
1279 | } | ||
1280 | rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum); | ||
1281 | |||
1282 | if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) { | ||
1283 | int off; | ||
1284 | /* It's hardware like this that really gets on my tits. */ | ||
1285 | static unsigned char copy[sizeof(struct DpRam)]; | ||
1286 | for ( off=0; off<sizeof(struct DpRam); off++ ) | ||
1287 | copy[off] = p->RIOHosts[HostDpRam.HostNum].Caddr[off]; | ||
1288 | if ( copyout( (caddr_t)copy, (int)HostDpRam.DpRamP, | ||
1289 | sizeof(struct DpRam) ) == COPYFAIL ) { | ||
1290 | p->RIOError.Error = COPYOUT_FAILED; | ||
1291 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); | ||
1292 | return -EFAULT; | ||
1293 | } | ||
1294 | } | ||
1295 | else if (copyout((caddr_t)p->RIOHosts[HostDpRam.HostNum].Caddr, | ||
1296 | (int)HostDpRam.DpRamP, | ||
1297 | sizeof(struct DpRam) ) == COPYFAIL ) { | ||
1298 | p->RIOError.Error = COPYOUT_FAILED; | ||
1299 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n"); | ||
1300 | return -EFAULT; | ||
1301 | } | ||
1302 | return retval; | ||
1303 | |||
1304 | case RIO_SET_BUSY: | ||
1305 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY\n"); | ||
1306 | if ( (int)arg < 0 || (int)arg > 511 ) { | ||
1307 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %d\n",(int)arg); | ||
1308 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1309 | return -EINVAL; | ||
1310 | } | ||
1311 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1312 | p->RIOPortp[(int)arg]->State |= RIO_BUSY; | ||
1313 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1314 | return retval; | ||
1315 | |||
1316 | case RIO_HOST_PORT: | ||
1317 | /* | ||
1318 | ** The daemon want port information | ||
1319 | ** (probably for debug reasons) | ||
1320 | */ | ||
1321 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT\n"); | ||
1322 | if ( copyin((int)arg, (caddr_t)&PortReq, | ||
1323 | sizeof(PortReq) )==COPYFAIL ) { | ||
1324 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n"); | ||
1325 | p->RIOError.Error = COPYIN_FAILED; | ||
1326 | return -EFAULT; | ||
1327 | } | ||
1328 | |||
1329 | if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */ | ||
1330 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", | ||
1331 | PortReq.SysPort); | ||
1332 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1333 | return -ENXIO; | ||
1334 | } | ||
1335 | rio_dprintk (RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort); | ||
1336 | if (copyout((caddr_t)p->RIOPortp[PortReq.SysPort], | ||
1337 | (int)PortReq.PortP, | ||
1338 | sizeof(struct Port) ) == COPYFAIL) { | ||
1339 | p->RIOError.Error = COPYOUT_FAILED; | ||
1340 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n"); | ||
1341 | return -EFAULT; | ||
1342 | } | ||
1343 | return retval; | ||
1344 | |||
1345 | case RIO_HOST_RUP: | ||
1346 | /* | ||
1347 | ** The daemon want rup information | ||
1348 | ** (probably for debug reasons) | ||
1349 | */ | ||
1350 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP\n"); | ||
1351 | if (copyin((int)arg, (caddr_t)&RupReq, | ||
1352 | sizeof(RupReq) )==COPYFAIL ) { | ||
1353 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n"); | ||
1354 | p->RIOError.Error = COPYIN_FAILED; | ||
1355 | return -EFAULT; | ||
1356 | } | ||
1357 | if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */ | ||
1358 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", | ||
1359 | RupReq.HostNum); | ||
1360 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1361 | return -ENXIO; | ||
1362 | } | ||
1363 | if ( RupReq.RupNum >= MAX_RUP+LINKS_PER_UNIT ) { /* eek! */ | ||
1364 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", | ||
1365 | RupReq.RupNum); | ||
1366 | p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; | ||
1367 | return -EINVAL; | ||
1368 | } | ||
1369 | HostP = &p->RIOHosts[RupReq.HostNum]; | ||
1370 | |||
1371 | if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { | ||
1372 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", | ||
1373 | RupReq.HostNum); | ||
1374 | p->RIOError.Error = HOST_NOT_RUNNING; | ||
1375 | return -EIO; | ||
1376 | } | ||
1377 | rio_dprintk (RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", | ||
1378 | RupReq.RupNum,RupReq.HostNum); | ||
1379 | |||
1380 | if (copyout((caddr_t)HostP->UnixRups[RupReq.RupNum].RupP, | ||
1381 | (int)RupReq.RupP,sizeof(struct RUP) ) == COPYFAIL) { | ||
1382 | p->RIOError.Error = COPYOUT_FAILED; | ||
1383 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n"); | ||
1384 | return -EFAULT; | ||
1385 | } | ||
1386 | return retval; | ||
1387 | |||
1388 | case RIO_HOST_LPB: | ||
1389 | /* | ||
1390 | ** The daemon want lpb information | ||
1391 | ** (probably for debug reasons) | ||
1392 | */ | ||
1393 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB\n"); | ||
1394 | if (copyin((int)arg, (caddr_t)&LpbReq, | ||
1395 | sizeof(LpbReq) )==COPYFAIL ) { | ||
1396 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n"); | ||
1397 | p->RIOError.Error = COPYIN_FAILED; | ||
1398 | return -EFAULT; | ||
1399 | } | ||
1400 | if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */ | ||
1401 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", | ||
1402 | LpbReq.Host); | ||
1403 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1404 | return -ENXIO; | ||
1405 | } | ||
1406 | if ( LpbReq.Link >= LINKS_PER_UNIT ) { /* eek! */ | ||
1407 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", | ||
1408 | LpbReq.Link); | ||
1409 | p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE; | ||
1410 | return -EINVAL; | ||
1411 | } | ||
1412 | HostP = &p->RIOHosts[LpbReq.Host]; | ||
1413 | |||
1414 | if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) { | ||
1415 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", | ||
1416 | LpbReq.Host ); | ||
1417 | p->RIOError.Error = HOST_NOT_RUNNING; | ||
1418 | return -EIO; | ||
1419 | } | ||
1420 | rio_dprintk (RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", | ||
1421 | LpbReq.Link, LpbReq.Host); | ||
1422 | |||
1423 | if (copyout((caddr_t)&HostP->LinkStrP[LpbReq.Link], | ||
1424 | (int)LpbReq.LpbP,sizeof(struct LPB) ) == COPYFAIL) { | ||
1425 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n"); | ||
1426 | p->RIOError.Error = COPYOUT_FAILED; | ||
1427 | return -EFAULT; | ||
1428 | } | ||
1429 | return retval; | ||
1430 | |||
1431 | /* | ||
1432 | ** Here 3 IOCTL's that allow us to change the way in which | ||
1433 | ** rio logs errors. send them just to syslog or send them | ||
1434 | ** to both syslog and console or send them to just the console. | ||
1435 | ** | ||
1436 | ** See RioStrBuf() in util.c for the other half. | ||
1437 | */ | ||
1438 | case RIO_SYSLOG_ONLY: | ||
1439 | p->RIOPrintLogState = PRINT_TO_LOG; /* Just syslog */ | ||
1440 | return 0; | ||
1441 | |||
1442 | case RIO_SYSLOG_CONS: | ||
1443 | p->RIOPrintLogState = PRINT_TO_LOG_CONS;/* syslog and console */ | ||
1444 | return 0; | ||
1445 | |||
1446 | case RIO_CONS_ONLY: | ||
1447 | p->RIOPrintLogState = PRINT_TO_CONS; /* Just console */ | ||
1448 | return 0; | ||
1449 | |||
1450 | case RIO_SIGNALS_ON: | ||
1451 | if ( p->RIOSignalProcess ) { | ||
1452 | p->RIOError.Error = SIGNALS_ALREADY_SET; | ||
1453 | return -EBUSY; | ||
1454 | } | ||
1455 | p->RIOSignalProcess = getpid(); | ||
1456 | p->RIOPrintDisabled = DONT_PRINT; | ||
1457 | return retval; | ||
1458 | |||
1459 | case RIO_SIGNALS_OFF: | ||
1460 | if ( p->RIOSignalProcess != getpid() ) { | ||
1461 | p->RIOError.Error = NOT_RECEIVING_PROCESS; | ||
1462 | return -EPERM; | ||
1463 | } | ||
1464 | rio_dprintk (RIO_DEBUG_CTRL, "Clear signal process to zero\n"); | ||
1465 | p->RIOSignalProcess = 0; | ||
1466 | return retval; | ||
1467 | |||
1468 | case RIO_SET_BYTE_MODE: | ||
1469 | for ( Host=0; Host<p->RIONumHosts; Host++ ) | ||
1470 | if ( p->RIOHosts[Host].Type == RIO_AT ) | ||
1471 | p->RIOHosts[Host].Mode &= ~WORD_OPERATION; | ||
1472 | return retval; | ||
1473 | |||
1474 | case RIO_SET_WORD_MODE: | ||
1475 | for ( Host=0; Host<p->RIONumHosts; Host++ ) | ||
1476 | if ( p->RIOHosts[Host].Type == RIO_AT ) | ||
1477 | p->RIOHosts[Host].Mode |= WORD_OPERATION; | ||
1478 | return retval; | ||
1479 | |||
1480 | case RIO_SET_FAST_BUS: | ||
1481 | for ( Host=0; Host<p->RIONumHosts; Host++ ) | ||
1482 | if ( p->RIOHosts[Host].Type == RIO_AT ) | ||
1483 | p->RIOHosts[Host].Mode |= FAST_AT_BUS; | ||
1484 | return retval; | ||
1485 | |||
1486 | case RIO_SET_SLOW_BUS: | ||
1487 | for ( Host=0; Host<p->RIONumHosts; Host++ ) | ||
1488 | if ( p->RIOHosts[Host].Type == RIO_AT ) | ||
1489 | p->RIOHosts[Host].Mode &= ~FAST_AT_BUS; | ||
1490 | return retval; | ||
1491 | |||
1492 | case RIO_MAP_B50_TO_50: | ||
1493 | case RIO_MAP_B50_TO_57600: | ||
1494 | case RIO_MAP_B110_TO_110: | ||
1495 | case RIO_MAP_B110_TO_115200: | ||
1496 | rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping\n"); | ||
1497 | port = (uint) arg; | ||
1498 | if ( port < 0 || port > 511 ) { | ||
1499 | rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port); | ||
1500 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1501 | return -EINVAL; | ||
1502 | } | ||
1503 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1504 | switch( cmd ) | ||
1505 | { | ||
1506 | case RIO_MAP_B50_TO_50 : | ||
1507 | p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50; | ||
1508 | break; | ||
1509 | case RIO_MAP_B50_TO_57600 : | ||
1510 | p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50; | ||
1511 | break; | ||
1512 | case RIO_MAP_B110_TO_110 : | ||
1513 | p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110; | ||
1514 | break; | ||
1515 | case RIO_MAP_B110_TO_115200 : | ||
1516 | p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110; | ||
1517 | break; | ||
1518 | } | ||
1519 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1520 | return retval; | ||
1521 | |||
1522 | case RIO_STREAM_INFO: | ||
1523 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n"); | ||
1524 | return -EINVAL; | ||
1525 | |||
1526 | case RIO_SEND_PACKET: | ||
1527 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n"); | ||
1528 | if ( copyin( (int)arg, (caddr_t)&SendPack, | ||
1529 | sizeof(SendPack) )==COPYFAIL ) { | ||
1530 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n"); | ||
1531 | p->RIOError.Error = COPYIN_FAILED; | ||
1532 | return -EFAULT; | ||
1533 | } | ||
1534 | if ( SendPack.PortNum >= 128 ) { | ||
1535 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1536 | return -ENXIO; | ||
1537 | } | ||
1538 | |||
1539 | PortP = p->RIOPortp[SendPack.PortNum]; | ||
1540 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1541 | |||
1542 | if ( !can_add_transmit(&PacketP,PortP) ) { | ||
1543 | p->RIOError.Error = UNIT_IS_IN_USE; | ||
1544 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1545 | return -ENOSPC; | ||
1546 | } | ||
1547 | |||
1548 | for ( loop=0; loop<(ushort)(SendPack.Len & 127); loop++ ) | ||
1549 | WBYTE(PacketP->data[loop], SendPack.Data[loop] ); | ||
1550 | |||
1551 | WBYTE(PacketP->len, SendPack.Len); | ||
1552 | |||
1553 | add_transmit( PortP ); | ||
1554 | /* | ||
1555 | ** Count characters transmitted for port statistics reporting | ||
1556 | */ | ||
1557 | if (PortP->statsGather) | ||
1558 | PortP->txchars += (SendPack.Len & 127); | ||
1559 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1560 | return retval; | ||
1561 | |||
1562 | case RIO_NO_MESG: | ||
1563 | if ( su ) | ||
1564 | p->RIONoMessage = 1; | ||
1565 | return su ? 0 : -EPERM; | ||
1566 | |||
1567 | case RIO_MESG: | ||
1568 | if ( su ) | ||
1569 | p->RIONoMessage = 0; | ||
1570 | return su ? 0 : -EPERM; | ||
1571 | |||
1572 | case RIO_WHAT_MESG: | ||
1573 | if ( copyout( (caddr_t)&p->RIONoMessage, (int)arg, | ||
1574 | sizeof(p->RIONoMessage) )==COPYFAIL ) { | ||
1575 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n"); | ||
1576 | p->RIOError.Error = COPYOUT_FAILED; | ||
1577 | return -EFAULT; | ||
1578 | } | ||
1579 | return 0; | ||
1580 | |||
1581 | case RIO_MEM_DUMP : | ||
1582 | if (copyin((int)arg, (caddr_t)&SubCmd, | ||
1583 | sizeof(struct SubCmdStruct)) == COPYFAIL) { | ||
1584 | p->RIOError.Error = COPYIN_FAILED; | ||
1585 | return -EFAULT; | ||
1586 | } | ||
1587 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", | ||
1588 | SubCmd.Host, SubCmd.Rup, SubCmd.Addr); | ||
1589 | |||
1590 | if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) { | ||
1591 | p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; | ||
1592 | return -EINVAL; | ||
1593 | } | ||
1594 | |||
1595 | if (SubCmd.Host >= p->RIONumHosts ) { | ||
1596 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1597 | return -EINVAL; | ||
1598 | } | ||
1599 | |||
1600 | port = p->RIOHosts[SubCmd.Host]. | ||
1601 | UnixRups[SubCmd.Rup].BaseSysPort; | ||
1602 | |||
1603 | PortP = p->RIOPortp[port]; | ||
1604 | |||
1605 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1606 | |||
1607 | if ( RIOPreemptiveCmd(p, PortP, MEMDUMP ) == RIO_FAIL ) { | ||
1608 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n"); | ||
1609 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1610 | return -EBUSY; | ||
1611 | } | ||
1612 | else | ||
1613 | PortP->State |= RIO_BUSY; | ||
1614 | |||
1615 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1616 | if ( copyout( (caddr_t)p->RIOMemDump, (int)arg, | ||
1617 | MEMDUMP_SIZE) == COPYFAIL ) { | ||
1618 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n"); | ||
1619 | p->RIOError.Error = COPYOUT_FAILED; | ||
1620 | return -EFAULT; | ||
1621 | } | ||
1622 | return 0; | ||
1623 | |||
1624 | case RIO_TICK: | ||
1625 | if ((int)arg < 0 || (int)arg >= p->RIONumHosts) | ||
1626 | return -EINVAL; | ||
1627 | rio_dprintk (RIO_DEBUG_CTRL, "Set interrupt for host %d\n", (int)arg); | ||
1628 | WBYTE(p->RIOHosts[(int)arg].SetInt , 0xff); | ||
1629 | return 0; | ||
1630 | |||
1631 | case RIO_TOCK: | ||
1632 | if ((int)arg < 0 || (int)arg >= p->RIONumHosts) | ||
1633 | return -EINVAL; | ||
1634 | rio_dprintk (RIO_DEBUG_CTRL, "Clear interrupt for host %d\n", (int)arg); | ||
1635 | WBYTE((p->RIOHosts[(int)arg].ResetInt) , 0xff); | ||
1636 | return 0; | ||
1637 | |||
1638 | case RIO_READ_CHECK: | ||
1639 | /* Check reads for pkts with data[0] the same */ | ||
1640 | p->RIOReadCheck = !p->RIOReadCheck; | ||
1641 | if (copyout((caddr_t)&p->RIOReadCheck,(int)arg, | ||
1642 | sizeof(uint))== COPYFAIL) { | ||
1643 | p->RIOError.Error = COPYOUT_FAILED; | ||
1644 | return -EFAULT; | ||
1645 | } | ||
1646 | return 0; | ||
1647 | |||
1648 | case RIO_READ_REGISTER : | ||
1649 | if (copyin((int)arg, (caddr_t)&SubCmd, | ||
1650 | sizeof(struct SubCmdStruct)) == COPYFAIL) { | ||
1651 | p->RIOError.Error = COPYIN_FAILED; | ||
1652 | return -EFAULT; | ||
1653 | } | ||
1654 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", | ||
1655 | SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr); | ||
1656 | |||
1657 | if (SubCmd.Port > 511) { | ||
1658 | rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", | ||
1659 | SubCmd.Port); | ||
1660 | p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; | ||
1661 | return -EINVAL; | ||
1662 | } | ||
1663 | |||
1664 | if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) { | ||
1665 | p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE; | ||
1666 | return -EINVAL; | ||
1667 | } | ||
1668 | |||
1669 | if (SubCmd.Host >= p->RIONumHosts ) { | ||
1670 | p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE; | ||
1671 | return -EINVAL; | ||
1672 | } | ||
1673 | |||
1674 | port = p->RIOHosts[SubCmd.Host]. | ||
1675 | UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port; | ||
1676 | PortP = p->RIOPortp[port]; | ||
1677 | |||
1678 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1679 | |||
1680 | if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) { | ||
1681 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n"); | ||
1682 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1683 | return -EBUSY; | ||
1684 | } | ||
1685 | else | ||
1686 | PortP->State |= RIO_BUSY; | ||
1687 | |||
1688 | rio_spin_unlock_irqrestore( &PortP->portSem , flags); | ||
1689 | if (copyout((caddr_t)&p->CdRegister, (int)arg, | ||
1690 | sizeof(uint)) == COPYFAIL ) { | ||
1691 | rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n"); | ||
1692 | p->RIOError.Error = COPYOUT_FAILED; | ||
1693 | return -EFAULT; | ||
1694 | } | ||
1695 | return 0; | ||
1696 | /* | ||
1697 | ** rio_make_dev: given port number (0-511) ORed with port type | ||
1698 | ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t | ||
1699 | ** value to pass to mknod to create the correct device node. | ||
1700 | */ | ||
1701 | case RIO_MAKE_DEV: | ||
1702 | { | ||
1703 | uint port = (uint)arg & RIO_MODEM_MASK; | ||
1704 | |||
1705 | switch ( (uint)arg & RIO_DEV_MASK ) { | ||
1706 | case RIO_DEV_DIRECT: | ||
1707 | arg = (caddr_t)drv_makedev(MAJOR(dev), port); | ||
1708 | rio_dprintk (RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n",port, (int)arg); | ||
1709 | return (int)arg; | ||
1710 | case RIO_DEV_MODEM: | ||
1711 | arg = (caddr_t)drv_makedev(MAJOR(dev), (port|RIO_MODEM_BIT) ); | ||
1712 | rio_dprintk (RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n",port, (int)arg); | ||
1713 | return (int)arg; | ||
1714 | case RIO_DEV_XPRINT: | ||
1715 | arg = (caddr_t)drv_makedev(MAJOR(dev), port); | ||
1716 | rio_dprintk (RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n",port, (int)arg); | ||
1717 | return (int)arg; | ||
1718 | } | ||
1719 | rio_dprintk (RIO_DEBUG_CTRL, "MAKE Device is called\n"); | ||
1720 | return -EINVAL; | ||
1721 | } | ||
1722 | /* | ||
1723 | ** rio_minor: given a dev_t from a stat() call, return | ||
1724 | ** the port number (0-511) ORed with the port type | ||
1725 | ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT ) | ||
1726 | */ | ||
1727 | case RIO_MINOR: | ||
1728 | { | ||
1729 | dev_t dv; | ||
1730 | int mino; | ||
1731 | |||
1732 | dv = (dev_t)((int)arg); | ||
1733 | mino = RIO_UNMODEM(dv); | ||
1734 | |||
1735 | if ( RIO_ISMODEM(dv) ) { | ||
1736 | rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino); | ||
1737 | arg = (caddr_t)(mino | RIO_DEV_MODEM); | ||
1738 | } | ||
1739 | else { | ||
1740 | rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino); | ||
1741 | arg = (caddr_t)(mino | RIO_DEV_DIRECT); | ||
1742 | } | ||
1743 | return (int)arg; | ||
1744 | } | ||
1745 | } | ||
1746 | rio_dprintk (RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n",cmd); | ||
1747 | p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; | ||
1748 | |||
1749 | func_exit (); | ||
1750 | return -EINVAL; | ||
1751 | } | ||
1752 | |||
1753 | /* | ||
1754 | ** Pre-emptive commands go on RUPs and are only one byte long. | ||
1755 | */ | ||
1756 | int | ||
1757 | RIOPreemptiveCmd(p, PortP, Cmd) | ||
1758 | struct rio_info * p; | ||
1759 | struct Port *PortP; | ||
1760 | uchar Cmd; | ||
1761 | { | ||
1762 | struct CmdBlk *CmdBlkP; | ||
1763 | struct PktCmd_M *PktCmdP; | ||
1764 | int Ret; | ||
1765 | ushort rup; | ||
1766 | int port; | ||
1767 | |||
1768 | #ifdef CHECK | ||
1769 | CheckPortP( PortP ); | ||
1770 | #endif | ||
1771 | |||
1772 | if ( PortP->State & RIO_DELETED ) { | ||
1773 | rio_dprintk (RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n"); | ||
1774 | return RIO_FAIL; | ||
1775 | } | ||
1776 | |||
1777 | if (((int)((char)PortP->InUse) == -1) || ! (CmdBlkP = RIOGetCmdBlk()) ) { | ||
1778 | rio_dprintk (RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n", | ||
1779 | Cmd, PortP->PortNum); | ||
1780 | return RIO_FAIL; | ||
1781 | } | ||
1782 | |||
1783 | rio_dprintk (RIO_DEBUG_CTRL, "Command blk 0x%x - InUse now %d\n", | ||
1784 | (int)CmdBlkP,PortP->InUse); | ||
1785 | |||
1786 | PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0]; | ||
1787 | |||
1788 | CmdBlkP->Packet.src_unit = 0; | ||
1789 | if (PortP->SecondBlock) | ||
1790 | rup = PortP->ID2; | ||
1791 | else | ||
1792 | rup = PortP->RupNum; | ||
1793 | CmdBlkP->Packet.dest_unit = rup; | ||
1794 | CmdBlkP->Packet.src_port = COMMAND_RUP; | ||
1795 | CmdBlkP->Packet.dest_port = COMMAND_RUP; | ||
1796 | CmdBlkP->Packet.len = PKT_CMD_BIT | 2; | ||
1797 | CmdBlkP->PostFuncP = RIOUnUse; | ||
1798 | CmdBlkP->PostArg = (int)PortP; | ||
1799 | PktCmdP->Command = Cmd; | ||
1800 | port = PortP->HostPort % (ushort)PORTS_PER_RTA; | ||
1801 | /* | ||
1802 | ** Index ports 8-15 for 2nd block of 16 port RTA. | ||
1803 | */ | ||
1804 | if (PortP->SecondBlock) | ||
1805 | port += (ushort) PORTS_PER_RTA; | ||
1806 | PktCmdP->PhbNum = port; | ||
1807 | |||
1808 | switch ( Cmd ) { | ||
1809 | case MEMDUMP: | ||
1810 | rio_dprintk (RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%x (addr 0x%x)\n", | ||
1811 | (int)CmdBlkP, (int)SubCmd.Addr); | ||
1812 | PktCmdP->SubCommand = MEMDUMP; | ||
1813 | PktCmdP->SubAddr = SubCmd.Addr; | ||
1814 | break; | ||
1815 | case FCLOSE: | ||
1816 | rio_dprintk (RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%x\n",(int)CmdBlkP); | ||
1817 | break; | ||
1818 | case READ_REGISTER: | ||
1819 | rio_dprintk (RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%x\n", | ||
1820 | (int)SubCmd.Addr, (int)CmdBlkP); | ||
1821 | PktCmdP->SubCommand = READ_REGISTER; | ||
1822 | PktCmdP->SubAddr = SubCmd.Addr; | ||
1823 | break; | ||
1824 | case RESUME: | ||
1825 | rio_dprintk (RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%x\n",(int)CmdBlkP); | ||
1826 | break; | ||
1827 | case RFLUSH: | ||
1828 | rio_dprintk (RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%x\n",(int)CmdBlkP); | ||
1829 | CmdBlkP->PostFuncP = RIORFlushEnable; | ||
1830 | break; | ||
1831 | case SUSPEND: | ||
1832 | rio_dprintk (RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%x\n",(int)CmdBlkP); | ||
1833 | break; | ||
1834 | |||
1835 | case MGET : | ||
1836 | rio_dprintk (RIO_DEBUG_CTRL, "Queue MGET command blk 0x%x\n", (int)CmdBlkP); | ||
1837 | break; | ||
1838 | |||
1839 | case MSET : | ||
1840 | case MBIC : | ||
1841 | case MBIS : | ||
1842 | CmdBlkP->Packet.data[4] = (char) PortP->ModemLines; | ||
1843 | rio_dprintk (RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%x\n", (int)CmdBlkP); | ||
1844 | break; | ||
1845 | |||
1846 | case WFLUSH: | ||
1847 | /* | ||
1848 | ** If we have queued up the maximum number of Write flushes | ||
1849 | ** allowed then we should not bother sending any more to the | ||
1850 | ** RTA. | ||
1851 | */ | ||
1852 | if ((int)((char)PortP->WflushFlag) == (int)-1) { | ||
1853 | rio_dprintk (RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!"); | ||
1854 | RIOFreeCmdBlk(CmdBlkP); | ||
1855 | return(RIO_FAIL); | ||
1856 | } else { | ||
1857 | rio_dprintk (RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%x\n", | ||
1858 | (int)CmdBlkP); | ||
1859 | CmdBlkP->PostFuncP = RIOWFlushMark; | ||
1860 | } | ||
1861 | break; | ||
1862 | } | ||
1863 | |||
1864 | PortP->InUse++; | ||
1865 | |||
1866 | Ret = RIOQueueCmdBlk( PortP->HostP, rup, CmdBlkP ); | ||
1867 | |||
1868 | return Ret; | ||
1869 | } | ||
diff --git a/drivers/char/rio/riodrvr.h b/drivers/char/rio/riodrvr.h new file mode 100644 index 000000000000..bc38ac5dfbde --- /dev/null +++ b/drivers/char/rio/riodrvr.h | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : riodrvr.h | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 09:22:46 | ||
26 | ** Retrieved : 11/6/98 09:22:46 | ||
27 | ** | ||
28 | ** ident @(#)riodrvr.h 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __riodrvr_h | ||
34 | #define __riodrvr_h | ||
35 | |||
36 | #include <asm/param.h> /* for HZ */ | ||
37 | |||
38 | #ifdef SCCS_LABELS | ||
39 | static char *_riodrvr_h_sccs_ = "@(#)riodrvr.h 1.3"; | ||
40 | #endif | ||
41 | |||
42 | #define MEMDUMP_SIZE 32 | ||
43 | #define MOD_DISABLE (RIO_NOREAD|RIO_NOWRITE|RIO_NOXPRINT) | ||
44 | |||
45 | |||
46 | struct rio_info { | ||
47 | int mode; /* Intr or polled, word/byte */ | ||
48 | spinlock_t RIOIntrSem; /* Interrupt thread sem */ | ||
49 | int current_chan; /* current channel */ | ||
50 | int RIOFailed; /* Not initialised ? */ | ||
51 | int RIOInstallAttempts; /* no. of rio-install() calls */ | ||
52 | int RIOLastPCISearch; /* status of last search */ | ||
53 | int RIONumHosts; /* Number of RIO Hosts */ | ||
54 | struct Host * RIOHosts; /* RIO Host values */ | ||
55 | struct Port **RIOPortp; /* RIO port values */ | ||
56 | /* | ||
57 | ** 02.03.1999 ARG - ESIL 0820 fix | ||
58 | ** We no longer use RIOBootMode | ||
59 | ** | ||
60 | int RIOBootMode; * RIO boot mode * | ||
61 | ** | ||
62 | */ | ||
63 | int RIOPrintDisabled; /* RIO printing disabled ? */ | ||
64 | int RIOPrintLogState; /* RIO printing state ? */ | ||
65 | int RIOPolling; /* Polling ? */ | ||
66 | /* | ||
67 | ** 09.12.1998 ARG - ESIL 0776 part fix | ||
68 | ** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted. | ||
69 | ** The fix for this ESIL introduces another member (RIORtaDisCons) here to be | ||
70 | ** updated in RIOConCon() - to keep track of RTA connections/disconnections. | ||
71 | ** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons. | ||
72 | */ | ||
73 | int RIOHalted; /* halted ? */ | ||
74 | int RIORtaDisCons; /* RTA connections/disconnections */ | ||
75 | uint RIOReadCheck; /* Rio read check */ | ||
76 | uint RIONoMessage; /* To display message or not */ | ||
77 | uint RIONumBootPkts; /* how many packets for an RTA */ | ||
78 | uint RIOBootCount; /* size of RTA code */ | ||
79 | uint RIOBooting; /* count of outstanding boots */ | ||
80 | uint RIOSystemUp; /* Booted ?? */ | ||
81 | uint RIOCounting; /* for counting interrupts */ | ||
82 | uint RIOIntCount; /* # of intr since last check */ | ||
83 | uint RIOTxCount; /* number of xmit intrs */ | ||
84 | uint RIORxCount; /* number of rx intrs */ | ||
85 | uint RIORupCount; /* number of rup intrs */ | ||
86 | int RIXTimer; | ||
87 | int RIOBufferSize; /* Buffersize */ | ||
88 | int RIOBufferMask; /* Buffersize */ | ||
89 | |||
90 | int RIOFirstMajor; /* First host card's major no */ | ||
91 | |||
92 | uint RIOLastPortsMapped; /* highest port number known */ | ||
93 | uint RIOFirstPortsMapped; /* lowest port number known */ | ||
94 | |||
95 | uint RIOLastPortsBooted; /* highest port number running */ | ||
96 | uint RIOFirstPortsBooted; /* lowest port number running */ | ||
97 | |||
98 | uint RIOLastPortsOpened; /* highest port number running */ | ||
99 | uint RIOFirstPortsOpened; /* lowest port number running */ | ||
100 | |||
101 | /* Flag to say that the topology information has been changed. */ | ||
102 | uint RIOQuickCheck; | ||
103 | uint CdRegister; /* ??? */ | ||
104 | int RIOSignalProcess; /* Signalling process */ | ||
105 | int rio_debug; /* To debug ... */ | ||
106 | int RIODebugWait; /* For what ??? */ | ||
107 | int tpri; /* Thread prio */ | ||
108 | int tid; /* Thread id */ | ||
109 | uint _RIO_Polled; /* Counter for polling */ | ||
110 | uint _RIO_Interrupted; /* Counter for interrupt */ | ||
111 | int intr_tid; /* iointset return value */ | ||
112 | int TxEnSem; /* TxEnable Semaphore */ | ||
113 | |||
114 | |||
115 | struct Error RIOError; /* to Identify what went wrong */ | ||
116 | struct Conf RIOConf; /* Configuration ??? */ | ||
117 | struct ttystatics channel[RIO_PORTS]; /* channel information */ | ||
118 | char RIOBootPackets[1+(SIXTY_FOUR_K/RTA_BOOT_DATA_SIZE)] | ||
119 | [RTA_BOOT_DATA_SIZE]; | ||
120 | struct Map RIOConnectTable[TOTAL_MAP_ENTRIES]; | ||
121 | struct Map RIOSavedTable[TOTAL_MAP_ENTRIES]; | ||
122 | |||
123 | /* RTA to host binding table for master/slave operation */ | ||
124 | ulong RIOBindTab[MAX_RTA_BINDINGS]; | ||
125 | /* RTA memory dump variable */ | ||
126 | uchar RIOMemDump[MEMDUMP_SIZE]; | ||
127 | struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES]; | ||
128 | |||
129 | }; | ||
130 | |||
131 | |||
132 | #ifdef linux | ||
133 | #define debug(x) printk x | ||
134 | #else | ||
135 | #define debug(x) kkprintf x | ||
136 | #endif | ||
137 | |||
138 | |||
139 | |||
140 | #define RIO_RESET_INT 0x7d80 | ||
141 | #define WRBYTE(x,y) *(volatile unsigned char *)((x)) = \ | ||
142 | (unsigned char)(y) | ||
143 | |||
144 | #endif /* __riodrvr.h */ | ||
diff --git a/drivers/char/rio/rioinfo.h b/drivers/char/rio/rioinfo.h new file mode 100644 index 000000000000..e08421c9558e --- /dev/null +++ b/drivers/char/rio/rioinfo.h | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : rioinfo.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 14:07:49 | ||
26 | ** Retrieved : 11/6/98 14:07:50 | ||
27 | ** | ||
28 | ** ident @(#)rioinfo.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rioinfo_h | ||
34 | #define __rioinfo_h | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_rioinfo_h_sccs_ = "@(#)rioinfo.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** Host card data structure | ||
42 | */ | ||
43 | struct RioHostInfo { | ||
44 | long location; /* RIO Card Base I/O address */ | ||
45 | long vector; /* RIO Card IRQ vector */ | ||
46 | int bus; /* ISA/EISA/MCA/PCI */ | ||
47 | int mode; /* pointer to host mode - INTERRUPT / POLLED */ | ||
48 | struct old_sgttyb | ||
49 | * Sg; /* pointer to default term characteristics */ | ||
50 | }; | ||
51 | |||
52 | |||
53 | /* Mode in rio device info */ | ||
54 | #define INTERRUPTED_MODE 0x01 /* Interrupt is generated */ | ||
55 | #define POLLED_MODE 0x02 /* No interrupt */ | ||
56 | #define AUTO_MODE 0x03 /* Auto mode */ | ||
57 | |||
58 | #define WORD_ACCESS_MODE 0x10 /* Word Access Mode */ | ||
59 | #define BYTE_ACCESS_MODE 0x20 /* Byte Access Mode */ | ||
60 | |||
61 | |||
62 | /* Bus type that RIO supports */ | ||
63 | #define ISA_BUS 0x01 /* The card is ISA */ | ||
64 | #define EISA_BUS 0x02 /* The card is EISA */ | ||
65 | #define MCA_BUS 0x04 /* The card is MCA */ | ||
66 | #define PCI_BUS 0x08 /* The card is PCI */ | ||
67 | |||
68 | /* | ||
69 | ** 11.11.1998 ARG - ESIL ???? part fix | ||
70 | ** Moved definition for 'CHAN' here from rioinfo.c (it is now | ||
71 | ** called 'DEF_TERM_CHARACTERISTICS'). | ||
72 | */ | ||
73 | |||
74 | #define DEF_TERM_CHARACTERISTICS \ | ||
75 | { \ | ||
76 | B19200, B19200, /* input and output speed */ \ | ||
77 | 'H' - '@', /* erase char */ \ | ||
78 | -1, /* 2nd erase char */ \ | ||
79 | 'U' - '@', /* kill char */ \ | ||
80 | ECHO | CRMOD, /* mode */ \ | ||
81 | 'C' - '@', /* interrupt character */ \ | ||
82 | '\\' - '@', /* quit char */ \ | ||
83 | 'Q' - '@', /* start char */ \ | ||
84 | 'S' - '@', /* stop char */ \ | ||
85 | 'D' - '@', /* EOF */ \ | ||
86 | -1, /* brk */ \ | ||
87 | (LCRTBS | LCRTERA | LCRTKIL | LCTLECH), /* local mode word */ \ | ||
88 | 'Z' - '@', /* process stop */ \ | ||
89 | 'Y' - '@', /* delayed stop */ \ | ||
90 | 'R' - '@', /* reprint line */ \ | ||
91 | 'O' - '@', /* flush output */ \ | ||
92 | 'W' - '@', /* word erase */ \ | ||
93 | 'V' - '@' /* literal next char */ \ | ||
94 | } | ||
95 | |||
96 | #endif /* __rioinfo_h */ | ||
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c new file mode 100644 index 000000000000..dca941ed10cf --- /dev/null +++ b/drivers/char/rio/rioinit.c | |||
@@ -0,0 +1,1617 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : rioinit.c | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 10:33:43 | ||
26 | ** Retrieved : 11/6/98 10:33:49 | ||
27 | ** | ||
28 | ** ident @(#)rioinit.c 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | #ifdef SCCS_LABELS | ||
33 | static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3"; | ||
34 | #endif | ||
35 | |||
36 | #include <linux/config.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/errno.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <asm/system.h> | ||
42 | #include <asm/string.h> | ||
43 | #include <asm/semaphore.h> | ||
44 | #include <asm/uaccess.h> | ||
45 | |||
46 | #include <linux/termios.h> | ||
47 | #include <linux/serial.h> | ||
48 | |||
49 | #include <linux/generic_serial.h> | ||
50 | |||
51 | |||
52 | #include "linux_compat.h" | ||
53 | #include "typdef.h" | ||
54 | #include "pkt.h" | ||
55 | #include "daemon.h" | ||
56 | #include "rio.h" | ||
57 | #include "riospace.h" | ||
58 | #include "top.h" | ||
59 | #include "cmdpkt.h" | ||
60 | #include "map.h" | ||
61 | #include "riotypes.h" | ||
62 | #include "rup.h" | ||
63 | #include "port.h" | ||
64 | #include "riodrvr.h" | ||
65 | #include "rioinfo.h" | ||
66 | #include "func.h" | ||
67 | #include "errors.h" | ||
68 | #include "pci.h" | ||
69 | |||
70 | #include "parmmap.h" | ||
71 | #include "unixrup.h" | ||
72 | #include "board.h" | ||
73 | #include "host.h" | ||
74 | #include "error.h" | ||
75 | #include "phb.h" | ||
76 | #include "link.h" | ||
77 | #include "cmdblk.h" | ||
78 | #include "route.h" | ||
79 | #include "control.h" | ||
80 | #include "cirrus.h" | ||
81 | #include "rioioctl.h" | ||
82 | #include "rio_linux.h" | ||
83 | |||
84 | #undef bcopy | ||
85 | #define bcopy rio_pcicopy | ||
86 | |||
87 | int RIOPCIinit(struct rio_info *p, int Mode); | ||
88 | |||
89 | #if 0 | ||
90 | static void RIOAllocateInterrupts(struct rio_info *); | ||
91 | static int RIOReport(struct rio_info *); | ||
92 | static void RIOStopInterrupts(struct rio_info *, int, int); | ||
93 | #endif | ||
94 | |||
95 | static int RIOScrub(int, BYTE *, int); | ||
96 | |||
97 | #if 0 | ||
98 | extern int rio_intr(); | ||
99 | |||
100 | /* | ||
101 | ** Init time code. | ||
102 | */ | ||
103 | void | ||
104 | rioinit( p, info ) | ||
105 | struct rio_info * p; | ||
106 | struct RioHostInfo * info; | ||
107 | { | ||
108 | /* | ||
109 | ** Multi-Host card support - taking the easy way out - sorry ! | ||
110 | ** We allocate and set up the Host and Port structs when the | ||
111 | ** driver is called to 'install' the first host. | ||
112 | ** We check for this first 'call' by testing the RIOPortp pointer. | ||
113 | */ | ||
114 | if ( !p->RIOPortp ) | ||
115 | { | ||
116 | rio_dprintk (RIO_DEBUG_INIT, "Allocating and setting up driver data structures\n"); | ||
117 | |||
118 | RIOAllocDataStructs(p); /* allocate host/port structs */ | ||
119 | RIOSetupDataStructs(p); /* setup topology structs */ | ||
120 | } | ||
121 | |||
122 | RIOInitHosts( p, info ); /* hunt down the hardware */ | ||
123 | |||
124 | RIOAllocateInterrupts(p); /* allocate interrupts */ | ||
125 | RIOReport(p); /* show what we found */ | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | ** Initialise the Cards | ||
130 | */ | ||
131 | void | ||
132 | RIOInitHosts(p, info) | ||
133 | struct rio_info * p; | ||
134 | struct RioHostInfo * info; | ||
135 | { | ||
136 | /* | ||
137 | ** 15.10.1998 ARG - ESIL 0762 part fix | ||
138 | ** If there is no ISA card definition - we always look for PCI cards. | ||
139 | ** As we currently only support one host card this lets an ISA card | ||
140 | ** definition take precedence over PLUG and PLAY. | ||
141 | ** No ISA card - we are PLUG and PLAY with PCI. | ||
142 | */ | ||
143 | |||
144 | /* | ||
145 | ** Note - for PCI both these will be zero, that's okay because | ||
146 | ** RIOPCIInit() fills them in if a card is found. | ||
147 | */ | ||
148 | p->RIOHosts[p->RIONumHosts].Ivec = info->vector; | ||
149 | p->RIOHosts[p->RIONumHosts].PaddrP = info->location; | ||
150 | |||
151 | /* | ||
152 | ** Check that we are able to accommodate another host | ||
153 | */ | ||
154 | if ( p->RIONumHosts >= RIO_HOSTS ) | ||
155 | { | ||
156 | p->RIOFailed++; | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | if ( info->bus & ISA_BUS ) | ||
161 | { | ||
162 | rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (ISA)\n", p->RIONumHosts); | ||
163 | RIOISAinit(p, p->mode); | ||
164 | } | ||
165 | else | ||
166 | { | ||
167 | rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (PCI)\n", p->RIONumHosts); | ||
168 | RIOPCIinit(p, RIO_PCI_DEFAULT_MODE); | ||
169 | } | ||
170 | |||
171 | rio_dprintk (RIO_DEBUG_INIT, "Total hosts initialised so far : %d\n", p->RIONumHosts); | ||
172 | |||
173 | |||
174 | #ifdef FUTURE_RELEASE | ||
175 | if (p->bus & EISA_BUS) | ||
176 | /* EISA card */ | ||
177 | RIOEISAinit(p, RIO_EISA_DEFAULT_MODE); | ||
178 | |||
179 | if (p->bus & MCA_BUS) | ||
180 | /* MCA card */ | ||
181 | RIOMCAinit(p, RIO_MCA_DEFAULT_MODE); | ||
182 | #endif | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | ** go through memory for an AT host that we pass in the device info | ||
187 | ** structure and initialise | ||
188 | */ | ||
189 | void | ||
190 | RIOISAinit(p, mode) | ||
191 | struct rio_info * p; | ||
192 | int mode; | ||
193 | { | ||
194 | |||
195 | /* XXX Need to implement this. */ | ||
196 | #if 0 | ||
197 | p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec, | ||
198 | (int (*)())rio_intr, (char*)p->RIONumHosts); | ||
199 | |||
200 | rio_dprintk (RIO_DEBUG_INIT, "Set interrupt handler, intr_tid = 0x%x\n", p->intr_tid ); | ||
201 | |||
202 | if (RIODoAT(p, p->RIOHosts[p->RIONumHosts].PaddrP, mode)) { | ||
203 | return; | ||
204 | } | ||
205 | else { | ||
206 | rio_dprintk (RIO_DEBUG_INIT, "RIODoAT failed\n"); | ||
207 | p->RIOFailed++; | ||
208 | } | ||
209 | #endif | ||
210 | |||
211 | } | ||
212 | |||
213 | /* | ||
214 | ** RIODoAT : | ||
215 | ** | ||
216 | ** Map in a boards physical address, check that the board is there, | ||
217 | ** test the board and if everything is okay assign the board an entry | ||
218 | ** in the Rio Hosts structure. | ||
219 | */ | ||
220 | int | ||
221 | RIODoAT(p, Base, mode) | ||
222 | struct rio_info * p; | ||
223 | int Base; | ||
224 | int mode; | ||
225 | { | ||
226 | #define FOUND 1 | ||
227 | #define NOT_FOUND 0 | ||
228 | |||
229 | caddr_t cardAddr; | ||
230 | |||
231 | /* | ||
232 | ** Check to see if we actually have a board at this physical address. | ||
233 | */ | ||
234 | if ((cardAddr = RIOCheckForATCard(Base)) != 0) { | ||
235 | /* | ||
236 | ** Now test the board to see if it is working. | ||
237 | */ | ||
238 | if (RIOBoardTest(Base, cardAddr, RIO_AT, 0) == RIO_SUCCESS) { | ||
239 | /* | ||
240 | ** Fill out a slot in the Rio host structure. | ||
241 | */ | ||
242 | if (RIOAssignAT(p, Base, cardAddr, mode)) { | ||
243 | return(FOUND); | ||
244 | } | ||
245 | } | ||
246 | RIOMapout(Base, RIO_AT_MEM_SIZE, cardAddr); | ||
247 | } | ||
248 | return(NOT_FOUND); | ||
249 | } | ||
250 | |||
251 | caddr_t | ||
252 | RIOCheckForATCard(Base) | ||
253 | int Base; | ||
254 | { | ||
255 | int off; | ||
256 | struct DpRam *cardp; /* (Points at the host) */ | ||
257 | caddr_t virtAddr; | ||
258 | unsigned char RIOSigTab[24]; | ||
259 | /* | ||
260 | ** Table of values to search for as prom signature of a host card | ||
261 | */ | ||
262 | strcpy(RIOSigTab, "JBJGPGGHINSMJPJR"); | ||
263 | |||
264 | /* | ||
265 | ** Hey! Yes, You reading this code! Yo, grab a load a this: | ||
266 | ** | ||
267 | ** IF the card is using WORD MODE rather than BYTE MODE | ||
268 | ** then it will occupy 128K of PHYSICAL memory area. So, | ||
269 | ** you might think that the following Mapin is wrong. Well, | ||
270 | ** it isn't, because the SECOND 64K of occupied space is an | ||
271 | ** EXACT COPY of the FIRST 64K. (good?), so, we need only | ||
272 | ** map it in in one 64K block. | ||
273 | */ | ||
274 | if (RIOMapin(Base, RIO_AT_MEM_SIZE, &virtAddr) == -1) { | ||
275 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't map the board in!\n"); | ||
276 | return((caddr_t)0); | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | ** virtAddr points to the DP ram of the system. | ||
281 | ** We now cast this to a pointer to a RIO Host, | ||
282 | ** and have a rummage about in the PROM. | ||
283 | */ | ||
284 | cardp = (struct DpRam *)virtAddr; | ||
285 | |||
286 | for (off=0; RIOSigTab[off]; off++) { | ||
287 | if ((RBYTE(cardp->DpSignature[off]) & 0xFF) != RIOSigTab[off]) { | ||
288 | /* | ||
289 | ** Signature mismatch - card not at this address | ||
290 | */ | ||
291 | RIOMapout(Base, RIO_AT_MEM_SIZE, virtAddr); | ||
292 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't match the signature 0x%x 0x%x!\n", | ||
293 | (int)cardp, off); | ||
294 | return((caddr_t)0); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | ** If we get here then we must have found a valid board so return | ||
300 | ** its virtual address. | ||
301 | */ | ||
302 | return(virtAddr); | ||
303 | } | ||
304 | #endif | ||
305 | |||
306 | /** | ||
307 | ** RIOAssignAT : | ||
308 | ** | ||
309 | ** Fill out the fields in the p->RIOHosts structure now we know we know | ||
310 | ** we have a board present. | ||
311 | ** | ||
312 | ** bits < 0 indicates 8 bit operation requested, | ||
313 | ** bits > 0 indicates 16 bit operation. | ||
314 | */ | ||
315 | int | ||
316 | RIOAssignAT(p, Base, virtAddr, mode) | ||
317 | struct rio_info * p; | ||
318 | int Base; | ||
319 | caddr_t virtAddr; | ||
320 | int mode; | ||
321 | { | ||
322 | int bits; | ||
323 | struct DpRam *cardp = (struct DpRam *)virtAddr; | ||
324 | |||
325 | if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE)) | ||
326 | bits = BYTE_OPERATION; | ||
327 | else | ||
328 | bits = WORD_OPERATION; | ||
329 | |||
330 | /* | ||
331 | ** Board has passed its scrub test. Fill in all the | ||
332 | ** transient stuff. | ||
333 | */ | ||
334 | p->RIOHosts[p->RIONumHosts].Caddr = virtAddr; | ||
335 | p->RIOHosts[p->RIONumHosts].CardP = (struct DpRam *)virtAddr; | ||
336 | |||
337 | /* | ||
338 | ** Revision 01 AT host cards don't support WORD operations, | ||
339 | */ | ||
340 | if ( RBYTE(cardp->DpRevision) == 01 ) | ||
341 | bits = BYTE_OPERATION; | ||
342 | |||
343 | p->RIOHosts[p->RIONumHosts].Type = RIO_AT; | ||
344 | p->RIOHosts[p->RIONumHosts].Copy = bcopy; | ||
345 | /* set this later */ | ||
346 | p->RIOHosts[p->RIONumHosts].Slot = -1; | ||
347 | p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits; | ||
348 | WBYTE(p->RIOHosts[p->RIONumHosts].Control, | ||
349 | BOOT_FROM_RAM | EXTERNAL_BUS_OFF | | ||
350 | p->RIOHosts[p->RIONumHosts].Mode | | ||
351 | INTERRUPT_DISABLE ); | ||
352 | WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff); | ||
353 | WBYTE(p->RIOHosts[p->RIONumHosts].Control, | ||
354 | BOOT_FROM_RAM | EXTERNAL_BUS_OFF | | ||
355 | p->RIOHosts[p->RIONumHosts].Mode | | ||
356 | INTERRUPT_DISABLE ); | ||
357 | WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff); | ||
358 | p->RIOHosts[p->RIONumHosts].UniqueNum = | ||
359 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)| | ||
360 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)| | ||
361 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)| | ||
362 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24); | ||
363 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum); | ||
364 | |||
365 | p->RIONumHosts++; | ||
366 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base); | ||
367 | return(1); | ||
368 | } | ||
369 | #if 0 | ||
370 | #ifdef FUTURE_RELEASE | ||
371 | int RIOMCAinit(int Mode) | ||
372 | { | ||
373 | uchar SlotNumber; | ||
374 | caddr_t Caddr; | ||
375 | uint Paddr; | ||
376 | uint Ivec; | ||
377 | int Handle; | ||
378 | int ret = 0; | ||
379 | |||
380 | /* | ||
381 | ** Valid mode information for MCA cards | ||
382 | ** is only FAST LINKS | ||
383 | */ | ||
384 | Mode = (Mode & FAST_LINKS) ? McaTpFastLinks : McaTpSlowLinks; | ||
385 | rio_dprintk (RIO_DEBUG_INIT, "RIOMCAinit(%d)\n",Mode); | ||
386 | |||
387 | |||
388 | /* | ||
389 | ** Check out each of the slots | ||
390 | */ | ||
391 | for (SlotNumber = 0; SlotNumber < McaMaxSlots; SlotNumber++) { | ||
392 | /* | ||
393 | ** Enable the slot we want to talk to | ||
394 | */ | ||
395 | outb( McaSlotSelect, SlotNumber | McaSlotEnable ); | ||
396 | |||
397 | /* | ||
398 | ** Read the ID word from the slot | ||
399 | */ | ||
400 | if (((inb(McaIdHigh)<< 8)|inb(McaIdLow)) == McaRIOId) | ||
401 | { | ||
402 | rio_dprintk (RIO_DEBUG_INIT, "Potential MCA card in slot %d\n", SlotNumber); | ||
403 | |||
404 | /* | ||
405 | ** Card appears to be a RIO MCA card! | ||
406 | */ | ||
407 | RIOMachineType |= (1<<RIO_MCA); | ||
408 | |||
409 | /* | ||
410 | ** Just check we haven't found too many wonderful objects | ||
411 | */ | ||
412 | if ( RIONumHosts >= RIO_HOSTS ) | ||
413 | { | ||
414 | Rprintf(RIOMesgTooManyCards); | ||
415 | return(ret); | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | ** McaIrqEnable contains the interrupt vector, and a card | ||
420 | ** enable bit. | ||
421 | */ | ||
422 | Ivec = inb(McaIrqEnable); | ||
423 | |||
424 | rio_dprintk (RIO_DEBUG_INIT, "Ivec is %x\n", Ivec); | ||
425 | |||
426 | switch ( Ivec & McaIrqMask ) | ||
427 | { | ||
428 | case McaIrq9: | ||
429 | rio_dprintk (RIO_DEBUG_INIT, "IRQ9\n"); | ||
430 | break; | ||
431 | case McaIrq3: | ||
432 | rio_dprintk (RIO_DEBUG_INIT, "IRQ3\n"); | ||
433 | break; | ||
434 | case McaIrq4: | ||
435 | rio_dprintk (RIO_DEBUG_INIT, "IRQ4\n"); | ||
436 | break; | ||
437 | case McaIrq7: | ||
438 | rio_dprintk (RIO_DEBUG_INIT, "IRQ7\n"); | ||
439 | break; | ||
440 | case McaIrq10: | ||
441 | rio_dprintk (RIO_DEBUG_INIT, "IRQ10\n"); | ||
442 | break; | ||
443 | case McaIrq11: | ||
444 | rio_dprintk (RIO_DEBUG_INIT, "IRQ11\n"); | ||
445 | break; | ||
446 | case McaIrq12: | ||
447 | rio_dprintk (RIO_DEBUG_INIT, "IRQ12\n"); | ||
448 | break; | ||
449 | case McaIrq15: | ||
450 | rio_dprintk (RIO_DEBUG_INIT, "IRQ15\n"); | ||
451 | break; | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | ** If the card enable bit isn't set, then set it! | ||
456 | */ | ||
457 | if ((Ivec & McaCardEnable) != McaCardEnable) { | ||
458 | rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable not set - setting!\n"); | ||
459 | outb(McaIrqEnable,Ivec|McaCardEnable); | ||
460 | } else | ||
461 | rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable already set\n"); | ||
462 | |||
463 | /* | ||
464 | ** Convert the IRQ enable mask into something useful | ||
465 | */ | ||
466 | Ivec = RIOMcaToIvec[Ivec & McaIrqMask]; | ||
467 | |||
468 | /* | ||
469 | ** Find the physical address | ||
470 | */ | ||
471 | rio_dprintk (RIO_DEBUG_INIT, "inb(McaMemory) is %x\n", inb(McaMemory)); | ||
472 | Paddr = McaAddress(inb(McaMemory)); | ||
473 | |||
474 | rio_dprintk (RIO_DEBUG_INIT, "MCA card has Ivec %d Addr %x\n", Ivec, Paddr); | ||
475 | |||
476 | if ( Paddr != 0 ) | ||
477 | { | ||
478 | |||
479 | /* | ||
480 | ** Tell the memory mapper that we want to talk to it | ||
481 | */ | ||
482 | Handle = RIOMapin( Paddr, RIO_MCA_MEM_SIZE, &Caddr ); | ||
483 | |||
484 | if ( Handle == -1 ) { | ||
485 | rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE, Paddr; | ||
486 | continue; | ||
487 | } | ||
488 | |||
489 | rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr); | ||
490 | |||
491 | /* | ||
492 | ** And check that it is actually there! | ||
493 | */ | ||
494 | if ( RIOBoardTest( Paddr,Caddr,RIO_MCA,SlotNumber ) == RIO_SUCCESS ) | ||
495 | { | ||
496 | rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n"); | ||
497 | rio_dprintk (RIO_DEBUG_INIT, "Slot %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", | ||
498 | SlotNumber, RIO_MCA, Paddr, Caddr, Mode); | ||
499 | |||
500 | /* | ||
501 | ** Board has passed its scrub test. Fill in all the | ||
502 | ** transient stuff. | ||
503 | */ | ||
504 | p->RIOHosts[RIONumHosts].Slot = SlotNumber; | ||
505 | p->RIOHosts[RIONumHosts].Ivec = Ivec; | ||
506 | p->RIOHosts[RIONumHosts].Type = RIO_MCA; | ||
507 | p->RIOHosts[RIONumHosts].Copy = bcopy; | ||
508 | p->RIOHosts[RIONumHosts].PaddrP = Paddr; | ||
509 | p->RIOHosts[RIONumHosts].Caddr = Caddr; | ||
510 | p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr; | ||
511 | p->RIOHosts[RIONumHosts].Mode = Mode; | ||
512 | WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt , 0xff); | ||
513 | p->RIOHosts[RIONumHosts].UniqueNum = | ||
514 | ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)| | ||
515 | ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)| | ||
516 | ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)| | ||
517 | ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24); | ||
518 | RIONumHosts++; | ||
519 | ret++; | ||
520 | } | ||
521 | else | ||
522 | { | ||
523 | /* | ||
524 | ** It failed the test, so ignore it. | ||
525 | */ | ||
526 | rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n"); | ||
527 | RIOMapout(Paddr, RIO_MCA_MEM_SIZE, Caddr ); | ||
528 | } | ||
529 | } | ||
530 | else | ||
531 | { | ||
532 | rio_dprintk (RIO_DEBUG_INIT, "Slot %d - Paddr zero!\n", SlotNumber); | ||
533 | } | ||
534 | } | ||
535 | else | ||
536 | { | ||
537 | rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber); | ||
538 | } | ||
539 | } | ||
540 | /* | ||
541 | ** Now we have checked all the slots, turn off the MCA slot selector | ||
542 | */ | ||
543 | outb(McaSlotSelect,0); | ||
544 | rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber); | ||
545 | return ret; | ||
546 | } | ||
547 | |||
548 | int RIOEISAinit( int Mode ) | ||
549 | { | ||
550 | static int EISADone = 0; | ||
551 | uint Paddr; | ||
552 | int PollIntMixMsgDone = 0; | ||
553 | caddr_t Caddr; | ||
554 | ushort Ident; | ||
555 | uchar EisaSlot; | ||
556 | uchar Ivec; | ||
557 | int ret = 0; | ||
558 | |||
559 | /* | ||
560 | ** The only valid mode information for EISA hosts is fast or slow | ||
561 | ** links. | ||
562 | */ | ||
563 | Mode = (Mode & FAST_LINKS) ? EISA_TP_FAST_LINKS : EISA_TP_SLOW_LINKS; | ||
564 | |||
565 | if ( EISADone ) | ||
566 | { | ||
567 | rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit() - already done, return.\n"); | ||
568 | return(0); | ||
569 | } | ||
570 | |||
571 | EISADone++; | ||
572 | |||
573 | rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit()\n"); | ||
574 | |||
575 | |||
576 | /* | ||
577 | ** First check all cards to see if ANY are set for polled mode operation. | ||
578 | ** If so, set ALL to polled. | ||
579 | */ | ||
580 | |||
581 | for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ ) | ||
582 | { | ||
583 | Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) | | ||
584 | INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO); | ||
585 | |||
586 | if ( Ident == RIO_EISA_IDENT ) | ||
587 | { | ||
588 | rio_dprintk (RIO_DEBUG_INIT, "Found Specialix product\n"); | ||
589 | |||
590 | if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE ) | ||
591 | { | ||
592 | rio_dprintk (RIO_DEBUG_INIT, "Not Specialix RIO - Product number %x\n", | ||
593 | INBZ(EisaSlot, EISA_PRODUCT_NUMBER)); | ||
594 | continue; /* next slot */ | ||
595 | } | ||
596 | /* | ||
597 | ** Its a Specialix RIO! | ||
598 | */ | ||
599 | rio_dprintk (RIO_DEBUG_INIT, "RIO Revision %d\n", | ||
600 | INBZ(EisaSlot, EISA_REVISION_NUMBER)); | ||
601 | |||
602 | RIOMachineType |= (1<<RIO_EISA); | ||
603 | |||
604 | /* | ||
605 | ** Just check we haven't found too many wonderful objects | ||
606 | */ | ||
607 | if ( RIONumHosts >= RIO_HOSTS ) | ||
608 | { | ||
609 | Rprintf(RIOMesgTooManyCards); | ||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | /* | ||
614 | ** Ensure that the enable bit is set! | ||
615 | */ | ||
616 | OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT ); | ||
617 | |||
618 | /* | ||
619 | ** EISA_INTERRUPT_VEC contains the interrupt vector. | ||
620 | */ | ||
621 | Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC); | ||
622 | |||
623 | #ifdef RIODEBUG | ||
624 | switch ( Ivec & EISA_INTERRUPT_MASK ) | ||
625 | { | ||
626 | case EISA_IRQ_3: | ||
627 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 3\n"); | ||
628 | break; | ||
629 | case EISA_IRQ_4: | ||
630 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 4\n"); | ||
631 | break; | ||
632 | case EISA_IRQ_5: | ||
633 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 5\n"); | ||
634 | break; | ||
635 | case EISA_IRQ_6: | ||
636 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 6\n"); | ||
637 | break; | ||
638 | case EISA_IRQ_7: | ||
639 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 7\n"); | ||
640 | break; | ||
641 | case EISA_IRQ_9: | ||
642 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 9\n"); | ||
643 | break; | ||
644 | case EISA_IRQ_10: | ||
645 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 10\n"); | ||
646 | break; | ||
647 | case EISA_IRQ_11: | ||
648 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 11\n"); | ||
649 | break; | ||
650 | case EISA_IRQ_12: | ||
651 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 12\n"); | ||
652 | break; | ||
653 | case EISA_IRQ_14: | ||
654 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 14\n"); | ||
655 | break; | ||
656 | case EISA_IRQ_15: | ||
657 | rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 15\n"); | ||
658 | break; | ||
659 | case EISA_POLLED: | ||
660 | rio_dprintk (RIO_DEBUG_INIT, "EISA POLLED\n"); | ||
661 | break; | ||
662 | default: | ||
663 | rio_dprintk (RIO_DEBUG_INIT, NULL,DBG_INIT|DBG_FAIL,"Shagged interrupt number!\n"); | ||
664 | Ivec &= EISA_CONTROL_MASK; | ||
665 | } | ||
666 | #endif | ||
667 | |||
668 | if ( (Ivec & EISA_INTERRUPT_MASK) == | ||
669 | EISA_POLLED ) | ||
670 | { | ||
671 | RIOWillPoll = 1; | ||
672 | break; /* From EisaSlot loop */ | ||
673 | } | ||
674 | } | ||
675 | } | ||
676 | |||
677 | /* | ||
678 | ** Do it all again now we know whether to change all cards to polled | ||
679 | ** mode or not | ||
680 | */ | ||
681 | |||
682 | for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ ) | ||
683 | { | ||
684 | Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) | | ||
685 | INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO); | ||
686 | |||
687 | if ( Ident == RIO_EISA_IDENT ) | ||
688 | { | ||
689 | if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE ) | ||
690 | continue; /* next slot */ | ||
691 | |||
692 | /* | ||
693 | ** Its a Specialix RIO! | ||
694 | */ | ||
695 | |||
696 | /* | ||
697 | ** Ensure that the enable bit is set! | ||
698 | */ | ||
699 | OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT ); | ||
700 | |||
701 | /* | ||
702 | ** EISA_INTERRUPT_VEC contains the interrupt vector. | ||
703 | */ | ||
704 | Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC); | ||
705 | |||
706 | if ( RIOWillPoll ) | ||
707 | { | ||
708 | /* | ||
709 | ** If we are going to operate in polled mode, but this | ||
710 | ** board is configured to be interrupt driven, display | ||
711 | ** the message explaining the situation to the punter, | ||
712 | ** assuming we haven't already done so. | ||
713 | */ | ||
714 | |||
715 | if ( !PollIntMixMsgDone && | ||
716 | (Ivec & EISA_INTERRUPT_MASK) != EISA_POLLED ) | ||
717 | { | ||
718 | Rprintf(RIOMesgAllPolled); | ||
719 | PollIntMixMsgDone = 1; | ||
720 | } | ||
721 | |||
722 | /* | ||
723 | ** Ungraciously ignore whatever the board reports as its | ||
724 | ** interrupt vector... | ||
725 | */ | ||
726 | |||
727 | Ivec &= ~EISA_INTERRUPT_MASK; | ||
728 | |||
729 | /* | ||
730 | ** ...and force it to dance to the poll tune. | ||
731 | */ | ||
732 | |||
733 | Ivec |= EISA_POLLED; | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | ** Convert the IRQ enable mask into something useful (0-15) | ||
738 | */ | ||
739 | Ivec = RIOEisaToIvec(Ivec); | ||
740 | |||
741 | rio_dprintk (RIO_DEBUG_INIT, "EISA host in slot %d has Ivec 0x%x\n", | ||
742 | EisaSlot, Ivec); | ||
743 | |||
744 | /* | ||
745 | ** Find the physical address | ||
746 | */ | ||
747 | Paddr = (INBZ(EisaSlot,EISA_MEMORY_BASE_HI)<<24) | | ||
748 | (INBZ(EisaSlot,EISA_MEMORY_BASE_LO)<<16); | ||
749 | |||
750 | rio_dprintk (RIO_DEBUG_INIT, "EISA card has Ivec %d Addr %x\n", Ivec, Paddr); | ||
751 | |||
752 | if ( Paddr == 0 ) | ||
753 | { | ||
754 | rio_dprintk (RIO_DEBUG_INIT, | ||
755 | "Board in slot %d configured for address zero!\n", EisaSlot); | ||
756 | continue; | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | ** Tell the memory mapper that we want to talk to it | ||
761 | */ | ||
762 | rio_dprintk (RIO_DEBUG_INIT, "About to map EISA card \n"); | ||
763 | |||
764 | if (RIOMapin( Paddr, RIO_EISA_MEM_SIZE, &Caddr) == -1) { | ||
765 | rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n", | ||
766 | RIO_EISA_MEM_SIZE,Paddr); | ||
767 | continue; | ||
768 | } | ||
769 | |||
770 | rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr); | ||
771 | |||
772 | /* | ||
773 | ** And check that it is actually there! | ||
774 | */ | ||
775 | if ( RIOBoardTest( Paddr,Caddr,RIO_EISA,EisaSlot) == RIO_SUCCESS ) | ||
776 | { | ||
777 | rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n"); | ||
778 | rio_dprintk (RIO_DEBUG_INIT, | ||
779 | "Slot %d. Ivec %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", | ||
780 | EisaSlot,Ivec,RIO_EISA,Paddr,Caddr,Mode); | ||
781 | |||
782 | /* | ||
783 | ** Board has passed its scrub test. Fill in all the | ||
784 | ** transient stuff. | ||
785 | */ | ||
786 | p->RIOHosts[RIONumHosts].Slot = EisaSlot; | ||
787 | p->RIOHosts[RIONumHosts].Ivec = Ivec; | ||
788 | p->RIOHosts[RIONumHosts].Type = RIO_EISA; | ||
789 | p->RIOHosts[RIONumHosts].Copy = bcopy; | ||
790 | p->RIOHosts[RIONumHosts].PaddrP = Paddr; | ||
791 | p->RIOHosts[RIONumHosts].Caddr = Caddr; | ||
792 | p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr; | ||
793 | p->RIOHosts[RIONumHosts].Mode = Mode; | ||
794 | /* | ||
795 | ** because the EISA prom is mapped into IO space, we | ||
796 | ** need to copy the unqiue number into the memory area | ||
797 | ** that it would have occupied, so that the download | ||
798 | ** code can determine its ID and card type. | ||
799 | */ | ||
800 | WBYTE(p->RIOHosts[RIONumHosts].Unique[0],INBZ(EisaSlot,EISA_UNIQUE_NUM_0)); | ||
801 | WBYTE(p->RIOHosts[RIONumHosts].Unique[1],INBZ(EisaSlot,EISA_UNIQUE_NUM_1)); | ||
802 | WBYTE(p->RIOHosts[RIONumHosts].Unique[2],INBZ(EisaSlot,EISA_UNIQUE_NUM_2)); | ||
803 | WBYTE(p->RIOHosts[RIONumHosts].Unique[3],INBZ(EisaSlot,EISA_UNIQUE_NUM_3)); | ||
804 | p->RIOHosts[RIONumHosts].UniqueNum = | ||
805 | ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)| | ||
806 | ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)| | ||
807 | ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)| | ||
808 | ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24); | ||
809 | INBZ(EisaSlot,EISA_INTERRUPT_RESET); | ||
810 | RIONumHosts++; | ||
811 | ret++; | ||
812 | } | ||
813 | else | ||
814 | { | ||
815 | /* | ||
816 | ** It failed the test, so ignore it. | ||
817 | */ | ||
818 | rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n"); | ||
819 | |||
820 | RIOMapout(Paddr, RIO_EISA_MEM_SIZE, Caddr ); | ||
821 | } | ||
822 | } | ||
823 | } | ||
824 | if (RIOMachineType & RIO_EISA) | ||
825 | return ret+1; | ||
826 | return ret; | ||
827 | } | ||
828 | #endif | ||
829 | |||
830 | |||
831 | #ifndef linux | ||
832 | |||
833 | #define CONFIG_ADDRESS 0xcf8 | ||
834 | #define CONFIG_DATA 0xcfc | ||
835 | #define FORWARD_REG 0xcfa | ||
836 | |||
837 | |||
838 | static int | ||
839 | read_config(int bus_number, int device_num, int r_number) | ||
840 | { | ||
841 | unsigned int cav; | ||
842 | unsigned int val; | ||
843 | |||
844 | /* | ||
845 | Build config_address_value: | ||
846 | |||
847 | 31 24 23 16 15 11 10 8 7 0 | ||
848 | ------------------------------------------------------ | ||
849 | |1| 0000000 | bus_number | device # | 000 | register | | ||
850 | ------------------------------------------------------ | ||
851 | */ | ||
852 | |||
853 | cav = r_number & 0xff; | ||
854 | cav |= ((device_num & 0x1f) << 11); | ||
855 | cav |= ((bus_number & 0xff) << 16); | ||
856 | cav |= 0x80000000; /* Enable bit */ | ||
857 | outpd(CONFIG_ADDRESS,cav); | ||
858 | val = inpd(CONFIG_DATA); | ||
859 | outpd(CONFIG_ADDRESS,0); | ||
860 | return val; | ||
861 | } | ||
862 | |||
863 | static | ||
864 | write_config(bus_number,device_num,r_number,val) | ||
865 | { | ||
866 | unsigned int cav; | ||
867 | |||
868 | /* | ||
869 | Build config_address_value: | ||
870 | |||
871 | 31 24 23 16 15 11 10 8 7 0 | ||
872 | ------------------------------------------------------ | ||
873 | |1| 0000000 | bus_number | device # | 000 | register | | ||
874 | ------------------------------------------------------ | ||
875 | */ | ||
876 | |||
877 | cav = r_number & 0xff; | ||
878 | cav |= ((device_num & 0x1f) << 11); | ||
879 | cav |= ((bus_number & 0xff) << 16); | ||
880 | cav |= 0x80000000; /* Enable bit */ | ||
881 | outpd(CONFIG_ADDRESS, cav); | ||
882 | outpd(CONFIG_DATA, val); | ||
883 | outpd(CONFIG_ADDRESS, 0); | ||
884 | return val; | ||
885 | } | ||
886 | #else | ||
887 | /* XXX Implement these... */ | ||
888 | static int | ||
889 | read_config(int bus_number, int device_num, int r_number) | ||
890 | { | ||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | static int | ||
895 | write_config(int bus_number, int device_num, int r_number) | ||
896 | { | ||
897 | return 0; | ||
898 | } | ||
899 | |||
900 | #endif | ||
901 | |||
902 | int | ||
903 | RIOPCIinit(p, Mode) | ||
904 | struct rio_info *p; | ||
905 | int Mode; | ||
906 | { | ||
907 | #define MAX_PCI_SLOT 32 | ||
908 | #define RIO_PCI_JET_CARD 0x200011CB | ||
909 | |||
910 | static int slot; /* count of machine's PCI slots searched so far */ | ||
911 | caddr_t Caddr; /* Virtual address of the current PCI host card. */ | ||
912 | unsigned char Ivec; /* interrupt vector for the current PCI host */ | ||
913 | unsigned long Paddr; /* Physical address for the current PCI host */ | ||
914 | int Handle; /* Handle to Virtual memory allocated for current PCI host */ | ||
915 | |||
916 | |||
917 | rio_dprintk (RIO_DEBUG_INIT, "Search for a RIO PCI card - start at slot %d\n", slot); | ||
918 | |||
919 | /* | ||
920 | ** Initialise the search status | ||
921 | */ | ||
922 | p->RIOLastPCISearch = RIO_FAIL; | ||
923 | |||
924 | while ( (slot < MAX_PCI_SLOT) & (p->RIOLastPCISearch != RIO_SUCCESS) ) | ||
925 | { | ||
926 | rio_dprintk (RIO_DEBUG_INIT, "Currently testing slot %d\n", slot); | ||
927 | |||
928 | if (read_config(0,slot,0) == RIO_PCI_JET_CARD) { | ||
929 | p->RIOHosts[p->RIONumHosts].Ivec = 0; | ||
930 | Paddr = read_config(0,slot,0x18); | ||
931 | Paddr = Paddr - (Paddr & 0x1); /* Mask off the io bit */ | ||
932 | |||
933 | if ( (Paddr == 0) || ((Paddr & 0xffff0000) == 0xffff0000) ) { | ||
934 | rio_dprintk (RIO_DEBUG_INIT, "Goofed up slot\n"); /* what! */ | ||
935 | slot++; | ||
936 | continue; | ||
937 | } | ||
938 | |||
939 | p->RIOHosts[p->RIONumHosts].PaddrP = Paddr; | ||
940 | Ivec = (read_config(0,slot,0x3c) & 0xff); | ||
941 | |||
942 | rio_dprintk (RIO_DEBUG_INIT, "PCI Host at 0x%x, Intr %d\n", (int)Paddr, Ivec); | ||
943 | |||
944 | Handle = RIOMapin( Paddr, RIO_PCI_MEM_SIZE, &Caddr ); | ||
945 | if (Handle == -1) { | ||
946 | rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at 0x%x\n", RIO_PCI_MEM_SIZE, (int)Paddr); | ||
947 | slot++; | ||
948 | continue; | ||
949 | } | ||
950 | p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32; | ||
951 | p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec, | ||
952 | (int (*)())rio_intr, (char *)p->RIONumHosts); | ||
953 | if (RIOBoardTest( Paddr, Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) { | ||
954 | rio_dprintk (RIO_DEBUG_INIT, ("Board has passed test\n"); | ||
955 | rio_dprintk (RIO_DEBUG_INIT, ("Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", Paddr, Caddr, Mode); | ||
956 | |||
957 | /* | ||
958 | ** Board has passed its scrub test. Fill in all the | ||
959 | ** transient stuff. | ||
960 | */ | ||
961 | p->RIOHosts[p->RIONumHosts].Slot = 0; | ||
962 | p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32; | ||
963 | p->RIOHosts[p->RIONumHosts].Type = RIO_PCI; | ||
964 | p->RIOHosts[p->RIONumHosts].Copy = rio_pcicopy; | ||
965 | p->RIOHosts[p->RIONumHosts].PaddrP = Paddr; | ||
966 | p->RIOHosts[p->RIONumHosts].Caddr = Caddr; | ||
967 | p->RIOHosts[p->RIONumHosts].CardP = (struct DpRam *)Caddr; | ||
968 | p->RIOHosts[p->RIONumHosts].Mode = Mode; | ||
969 | |||
970 | #if 0 | ||
971 | WBYTE(p->RIOHosts[p->RIONumHosts].Control, | ||
972 | BOOT_FROM_RAM | EXTERNAL_BUS_OFF | | ||
973 | p->RIOHosts[p->RIONumHosts].Mode | | ||
974 | INTERRUPT_DISABLE ); | ||
975 | WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff); | ||
976 | WBYTE(p->RIOHosts[p->RIONumHosts].Control, | ||
977 | BOOT_FROM_RAM | EXTERNAL_BUS_OFF | | ||
978 | p->RIOHosts[p->RIONumHosts].Mode | | ||
979 | INTERRUPT_DISABLE ); | ||
980 | WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff); | ||
981 | #else | ||
982 | WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); | ||
983 | #endif | ||
984 | p->RIOHosts[p->RIONumHosts].UniqueNum = | ||
985 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)| | ||
986 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)| | ||
987 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)| | ||
988 | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24); | ||
989 | |||
990 | rio_dprintk (RIO_DEBUG_INIT, "Unique no 0x%x.\n", | ||
991 | p->RIOHosts[p->RIONumHosts].UniqueNum); | ||
992 | |||
993 | p->RIOLastPCISearch = RIO_SUCCESS; | ||
994 | p->RIONumHosts++; | ||
995 | } | ||
996 | } | ||
997 | slot++; | ||
998 | } | ||
999 | |||
1000 | if ( slot >= MAX_PCI_SLOT ) { | ||
1001 | rio_dprintk (RIO_DEBUG_INIT, "All %d PCI slots have tested for RIO cards !!!\n", | ||
1002 | MAX_PCI_SLOT); | ||
1003 | } | ||
1004 | |||
1005 | |||
1006 | /* | ||
1007 | ** I don't think we want to do this anymore | ||
1008 | ** | ||
1009 | |||
1010 | if (!p->RIOLastPCISearch == RIO_FAIL ) { | ||
1011 | p->RIOFailed++; | ||
1012 | } | ||
1013 | |||
1014 | ** | ||
1015 | */ | ||
1016 | } | ||
1017 | |||
1018 | #ifdef FUTURE_RELEASE | ||
1019 | void riohalt( void ) | ||
1020 | { | ||
1021 | int host; | ||
1022 | for ( host=0; host<p->RIONumHosts; host++ ) | ||
1023 | { | ||
1024 | rio_dprintk (RIO_DEBUG_INIT, "Stop host %d\n", host); | ||
1025 | (void)RIOBoardTest( p->RIOHosts[host].PaddrP, p->RIOHosts[host].Caddr, p->RIOHosts[host].Type,p->RIOHosts[host].Slot ); | ||
1026 | } | ||
1027 | } | ||
1028 | #endif | ||
1029 | #endif | ||
1030 | |||
1031 | static uchar val[] = { | ||
1032 | #ifdef VERY_LONG_TEST | ||
1033 | 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, | ||
1034 | 0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, | ||
1035 | #endif | ||
1036 | 0xff, 0x00, 0x00 }; | ||
1037 | |||
1038 | #define TEST_END sizeof(val) | ||
1039 | |||
1040 | /* | ||
1041 | ** RAM test a board. | ||
1042 | ** Nothing too complicated, just enough to check it out. | ||
1043 | */ | ||
1044 | int | ||
1045 | RIOBoardTest(paddr, caddr, type, slot) | ||
1046 | paddr_t paddr; | ||
1047 | caddr_t caddr; | ||
1048 | uchar type; | ||
1049 | int slot; | ||
1050 | { | ||
1051 | struct DpRam *DpRam = (struct DpRam *)caddr; | ||
1052 | char *ram[4]; | ||
1053 | int size[4]; | ||
1054 | int op, bank; | ||
1055 | int nbanks; | ||
1056 | |||
1057 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=0x%x, slot=%d\n", | ||
1058 | type,(int)DpRam, slot); | ||
1059 | |||
1060 | RIOHostReset(type, DpRam, slot); | ||
1061 | |||
1062 | /* | ||
1063 | ** Scrub the memory. This comes in several banks: | ||
1064 | ** DPsram1 - 7000h bytes | ||
1065 | ** DPsram2 - 200h bytes | ||
1066 | ** DPsram3 - 7000h bytes | ||
1067 | ** scratch - 1000h bytes | ||
1068 | */ | ||
1069 | |||
1070 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n"); | ||
1071 | |||
1072 | size[0] = DP_SRAM1_SIZE; | ||
1073 | size[1] = DP_SRAM2_SIZE; | ||
1074 | size[2] = DP_SRAM3_SIZE; | ||
1075 | size[3] = DP_SCRATCH_SIZE; | ||
1076 | |||
1077 | ram[0] = (char *)&DpRam->DpSram1[0]; | ||
1078 | ram[1] = (char *)&DpRam->DpSram2[0]; | ||
1079 | ram[2] = (char *)&DpRam->DpSram3[0]; | ||
1080 | nbanks = (type == RIO_PCI) ? 3 : 4; | ||
1081 | if (nbanks == 4) | ||
1082 | ram[3] = (char *)&DpRam->DpScratch[0]; | ||
1083 | |||
1084 | |||
1085 | if (nbanks == 3) { | ||
1086 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n", | ||
1087 | (int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2]); | ||
1088 | } else { | ||
1089 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x), 0x%x(0x%x)\n", | ||
1090 | (int)ram[0], size[0], (int)ram[1], size[1], (int)ram[2], size[2], (int)ram[3], | ||
1091 | size[3]); | ||
1092 | } | ||
1093 | |||
1094 | /* | ||
1095 | ** This scrub operation will test for crosstalk between | ||
1096 | ** banks. TEST_END is a magic number, and relates to the offset | ||
1097 | ** within the 'val' array used by Scrub. | ||
1098 | */ | ||
1099 | for (op=0; op<TEST_END; op++) { | ||
1100 | for (bank=0; bank<nbanks; bank++) { | ||
1101 | if (RIOScrub(op, (BYTE *)ram[bank], size[bank]) == RIO_FAIL) { | ||
1102 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: RIOScrub band %d, op %d failed\n", | ||
1103 | bank, op); | ||
1104 | return RIO_FAIL; | ||
1105 | } | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1109 | rio_dprintk (RIO_DEBUG_INIT, "Test completed\n"); | ||
1110 | return RIO_SUCCESS; | ||
1111 | } | ||
1112 | |||
1113 | |||
1114 | /* | ||
1115 | ** Scrub an area of RAM. | ||
1116 | ** Define PRETEST and POSTTEST for a more thorough checking of the | ||
1117 | ** state of the memory. | ||
1118 | ** Call with op set to an index into the above 'val' array to determine | ||
1119 | ** which value will be written into memory. | ||
1120 | ** Call with op set to zero means that the RAM will not be read and checked | ||
1121 | ** before it is written. | ||
1122 | ** Call with op not zero, and the RAM will be read and compated with val[op-1] | ||
1123 | ** to check that the data from the previous phase was retained. | ||
1124 | */ | ||
1125 | static int | ||
1126 | RIOScrub(op, ram, size) | ||
1127 | int op; | ||
1128 | BYTE * ram; | ||
1129 | int size; | ||
1130 | { | ||
1131 | int off; | ||
1132 | unsigned char oldbyte; | ||
1133 | unsigned char newbyte; | ||
1134 | unsigned char invbyte; | ||
1135 | unsigned short oldword; | ||
1136 | unsigned short newword; | ||
1137 | unsigned short invword; | ||
1138 | unsigned short swapword; | ||
1139 | |||
1140 | if (op) { | ||
1141 | oldbyte = val[op-1]; | ||
1142 | oldword = oldbyte | (oldbyte<<8); | ||
1143 | } else | ||
1144 | oldbyte = oldword = 0; /* Tell the compiler we've initilalized them. */ | ||
1145 | newbyte = val[op]; | ||
1146 | newword = newbyte | (newbyte<<8); | ||
1147 | invbyte = ~newbyte; | ||
1148 | invword = invbyte | (invbyte<<8); | ||
1149 | |||
1150 | /* | ||
1151 | ** Check that the RAM contains the value that should have been left there | ||
1152 | ** by the previous test (not applicable for pass zero) | ||
1153 | */ | ||
1154 | if (op) { | ||
1155 | for (off=0; off<size; off++) { | ||
1156 | if (RBYTE(ram[off]) != oldbyte) { | ||
1157 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 1: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, RBYTE(ram[off])); | ||
1158 | return RIO_FAIL; | ||
1159 | } | ||
1160 | } | ||
1161 | for (off=0; off<size; off+=2) { | ||
1162 | if (*(ushort *)&ram[off] != oldword) { | ||
1163 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: WORD at offset 0x%x should have been=%x, was=%x\n",off,oldword,*(ushort *)&ram[off]); | ||
1164 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1])); | ||
1165 | return RIO_FAIL; | ||
1166 | } | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | /* | ||
1171 | ** Now write the INVERSE of the test data into every location, using | ||
1172 | ** BYTE write operations, first checking before each byte is written | ||
1173 | ** that the location contains the old value still, and checking after | ||
1174 | ** the write that the location contains the data specified - this is | ||
1175 | ** the BYTE read/write test. | ||
1176 | */ | ||
1177 | for (off=0; off<size; off++) { | ||
1178 | if (op && (RBYTE(ram[off]) != oldbyte)) { | ||
1179 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, RBYTE(ram[off])); | ||
1180 | return RIO_FAIL; | ||
1181 | } | ||
1182 | WBYTE(ram[off],invbyte); | ||
1183 | if (RBYTE(ram[off]) != invbyte) { | ||
1184 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Inv Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, invbyte, RBYTE(ram[off])); | ||
1185 | return RIO_FAIL; | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | /* | ||
1190 | ** now, use WORD operations to write the test value into every location, | ||
1191 | ** check as before that the location contains the previous test value | ||
1192 | ** before overwriting, and that it contains the data value written | ||
1193 | ** afterwards. | ||
1194 | ** This is the WORD operation test. | ||
1195 | */ | ||
1196 | for (off=0; off<size; off+=2) { | ||
1197 | if (*(ushort *)&ram[off] != invword) { | ||
1198 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: WORD at offset 0x%x should have been=%x, was=%x\n", off, invword, *(ushort *)&ram[off]); | ||
1199 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1])); | ||
1200 | return RIO_FAIL; | ||
1201 | } | ||
1202 | |||
1203 | *(ushort *)&ram[off] = newword; | ||
1204 | if ( *(ushort *)&ram[off] != newword ) { | ||
1205 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, *(ushort *)&ram[off]); | ||
1206 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1])); | ||
1207 | return RIO_FAIL; | ||
1208 | } | ||
1209 | } | ||
1210 | |||
1211 | /* | ||
1212 | ** now run through the block of memory again, first in byte mode | ||
1213 | ** then in word mode, and check that all the locations contain the | ||
1214 | ** required test data. | ||
1215 | */ | ||
1216 | for (off=0; off<size; off++) { | ||
1217 | if (RBYTE(ram[off]) != newbyte) { | ||
1218 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Byte Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, RBYTE(ram[off])); | ||
1219 | return RIO_FAIL; | ||
1220 | } | ||
1221 | } | ||
1222 | |||
1223 | for (off=0; off<size; off+=2) { | ||
1224 | if ( *(ushort *)&ram[off] != newword ) { | ||
1225 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, *(ushort *)&ram[off]); | ||
1226 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1])); | ||
1227 | return RIO_FAIL; | ||
1228 | } | ||
1229 | } | ||
1230 | |||
1231 | /* | ||
1232 | ** time to check out byte swapping errors | ||
1233 | */ | ||
1234 | swapword = invbyte | (newbyte << 8); | ||
1235 | |||
1236 | for (off=0; off<size; off+=2) { | ||
1237 | WBYTE(ram[off],invbyte); | ||
1238 | WBYTE(ram[off+1],newbyte); | ||
1239 | } | ||
1240 | |||
1241 | for ( off=0; off<size; off+=2 ) { | ||
1242 | if (*(ushort *)&ram[off] != swapword) { | ||
1243 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, swapword, *((ushort *)&ram[off])); | ||
1244 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, RBYTE(ram[off]), off+1, RBYTE(ram[off+1])); | ||
1245 | return RIO_FAIL; | ||
1246 | } | ||
1247 | *((ushort *)&ram[off]) = ~swapword; | ||
1248 | } | ||
1249 | |||
1250 | for (off=0; off<size; off+=2) { | ||
1251 | if (RBYTE(ram[off]) != newbyte) { | ||
1252 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, RBYTE(ram[off])); | ||
1253 | return RIO_FAIL; | ||
1254 | } | ||
1255 | if (RBYTE(ram[off+1]) != invbyte) { | ||
1256 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off+1, invbyte, RBYTE(ram[off+1])); | ||
1257 | return RIO_FAIL; | ||
1258 | } | ||
1259 | *((ushort *)&ram[off]) = newword; | ||
1260 | } | ||
1261 | return RIO_SUCCESS; | ||
1262 | } | ||
1263 | |||
1264 | /* | ||
1265 | ** try to ensure that every host is either in polled mode | ||
1266 | ** or is in interrupt mode. Only allow interrupt mode if | ||
1267 | ** all hosts can interrupt (why?) | ||
1268 | ** and force into polled mode if told to. Patch up the | ||
1269 | ** interrupt vector & salute The Queen when you've done. | ||
1270 | */ | ||
1271 | #if 0 | ||
1272 | static void | ||
1273 | RIOAllocateInterrupts(p) | ||
1274 | struct rio_info * p; | ||
1275 | { | ||
1276 | int Host; | ||
1277 | |||
1278 | /* | ||
1279 | ** Easy case - if we have been told to poll, then we poll. | ||
1280 | */ | ||
1281 | if (p->mode & POLLED_MODE) { | ||
1282 | RIOStopInterrupts(p, 0, 0); | ||
1283 | return; | ||
1284 | } | ||
1285 | |||
1286 | /* | ||
1287 | ** check - if any host has been set to polled mode, then all must be. | ||
1288 | */ | ||
1289 | for (Host=0; Host<p->RIONumHosts; Host++) { | ||
1290 | if ( (p->RIOHosts[Host].Type != RIO_AT) && | ||
1291 | (p->RIOHosts[Host].Ivec == POLLED) ) { | ||
1292 | RIOStopInterrupts(p, 1, Host ); | ||
1293 | return; | ||
1294 | } | ||
1295 | } | ||
1296 | for (Host=0; Host<p->RIONumHosts; Host++) { | ||
1297 | if (p->RIOHosts[Host].Type == RIO_AT) { | ||
1298 | if ( (p->RIOHosts[Host].Ivec - 32) == 0) { | ||
1299 | RIOStopInterrupts(p, 2, Host ); | ||
1300 | return; | ||
1301 | } | ||
1302 | } | ||
1303 | } | ||
1304 | } | ||
1305 | |||
1306 | /* | ||
1307 | ** something has decided that we can't be doing with these | ||
1308 | ** new-fangled interrupt thingies. Set everything up to just | ||
1309 | ** poll. | ||
1310 | */ | ||
1311 | static void | ||
1312 | RIOStopInterrupts(p, Reason, Host) | ||
1313 | struct rio_info * p; | ||
1314 | int Reason; | ||
1315 | int Host; | ||
1316 | { | ||
1317 | #ifdef FUTURE_RELEASE | ||
1318 | switch (Reason) { | ||
1319 | case 0: /* forced into polling by rio_polled */ | ||
1320 | break; | ||
1321 | case 1: /* SCU has set 'Host' into polled mode */ | ||
1322 | break; | ||
1323 | case 2: /* there aren't enough interrupt vectors for 'Host' */ | ||
1324 | break; | ||
1325 | } | ||
1326 | #endif | ||
1327 | |||
1328 | for (Host=0; Host<p->RIONumHosts; Host++ ) { | ||
1329 | struct Host *HostP = &p->RIOHosts[Host]; | ||
1330 | |||
1331 | switch (HostP->Type) { | ||
1332 | case RIO_AT: | ||
1333 | /* | ||
1334 | ** The AT host has it's interrupts disabled by clearing the | ||
1335 | ** int_enable bit. | ||
1336 | */ | ||
1337 | HostP->Mode &= ~INTERRUPT_ENABLE; | ||
1338 | HostP->Ivec = POLLED; | ||
1339 | break; | ||
1340 | #ifdef FUTURE_RELEASE | ||
1341 | case RIO_EISA: | ||
1342 | /* | ||
1343 | ** The EISA host has it's interrupts disabled by setting the | ||
1344 | ** Ivec to zero | ||
1345 | */ | ||
1346 | HostP->Ivec = POLLED; | ||
1347 | break; | ||
1348 | #endif | ||
1349 | case RIO_PCI: | ||
1350 | /* | ||
1351 | ** The PCI host has it's interrupts disabled by clearing the | ||
1352 | ** int_enable bit, like a regular host card. | ||
1353 | */ | ||
1354 | HostP->Mode &= ~RIO_PCI_INT_ENABLE; | ||
1355 | HostP->Ivec = POLLED; | ||
1356 | break; | ||
1357 | #ifdef FUTURE_RELEASE | ||
1358 | case RIO_MCA: | ||
1359 | /* | ||
1360 | ** There's always one, isn't there? | ||
1361 | ** The MCA host card cannot have it's interrupts disabled. | ||
1362 | */ | ||
1363 | RIOPatchVec(HostP); | ||
1364 | break; | ||
1365 | #endif | ||
1366 | } | ||
1367 | } | ||
1368 | } | ||
1369 | |||
1370 | /* | ||
1371 | ** This function is called at init time to setup the data structures. | ||
1372 | */ | ||
1373 | void | ||
1374 | RIOAllocDataStructs(p) | ||
1375 | struct rio_info * p; | ||
1376 | { | ||
1377 | int port, | ||
1378 | host, | ||
1379 | tm; | ||
1380 | |||
1381 | p->RIOPortp = (struct Port *)sysbrk(RIO_PORTS * sizeof(struct Port)); | ||
1382 | if (!p->RIOPortp) { | ||
1383 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for port structures\n"); | ||
1384 | p->RIOFailed++; | ||
1385 | return; | ||
1386 | } | ||
1387 | bzero( p->RIOPortp, sizeof(struct Port) * RIO_PORTS ); | ||
1388 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for port structs\n"); | ||
1389 | rio_dprintk (RIO_DEBUG_INIT, "First RIO port struct @0x%x, size=0x%x bytes\n", | ||
1390 | (int)p->RIOPortp, sizeof(struct Port)); | ||
1391 | |||
1392 | for( port=0; port<RIO_PORTS; port++ ) { | ||
1393 | p->RIOPortp[port].PortNum = port; | ||
1394 | p->RIOPortp[port].TtyP = &p->channel[port]; | ||
1395 | sreset (p->RIOPortp[port].InUse); /* Let the first guy uses it */ | ||
1396 | p->RIOPortp[port].portSem = -1; /* Let the first guy takes it */ | ||
1397 | p->RIOPortp[port].ParamSem = -1; /* Let the first guy takes it */ | ||
1398 | p->RIOPortp[port].timeout_id = 0; /* Let the first guy takes it */ | ||
1399 | } | ||
1400 | |||
1401 | p->RIOHosts = (struct Host *)sysbrk(RIO_HOSTS * sizeof(struct Host)); | ||
1402 | if (!p->RIOHosts) { | ||
1403 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for host structures\n"); | ||
1404 | p->RIOFailed++; | ||
1405 | return; | ||
1406 | } | ||
1407 | bzero(p->RIOHosts, sizeof(struct Host)*RIO_HOSTS); | ||
1408 | rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for host structs\n"); | ||
1409 | rio_dprintk (RIO_DEBUG_INIT, "First RIO host struct @0x%x, size=0x%x bytes\n", | ||
1410 | (int)p->RIOHosts, sizeof(struct Host)); | ||
1411 | |||
1412 | for( host=0; host<RIO_HOSTS; host++ ) { | ||
1413 | spin_lock_init (&p->RIOHosts[host].HostLock); | ||
1414 | p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */ | ||
1415 | } | ||
1416 | /* | ||
1417 | ** check that the buffer size is valid, round down to the next power of | ||
1418 | ** two if necessary; if the result is zero, then, hey, no double buffers. | ||
1419 | */ | ||
1420 | for ( tm = 1; tm && tm <= p->RIOConf.BufferSize; tm <<= 1 ) | ||
1421 | ; | ||
1422 | tm >>= 1; | ||
1423 | p->RIOBufferSize = tm; | ||
1424 | p->RIOBufferMask = tm ? tm - 1 : 0; | ||
1425 | } | ||
1426 | |||
1427 | /* | ||
1428 | ** this function gets called whenever the data structures need to be | ||
1429 | ** re-setup, for example, after a riohalt (why did I ever invent it?) | ||
1430 | */ | ||
1431 | void | ||
1432 | RIOSetupDataStructs(p) | ||
1433 | struct rio_info * p; | ||
1434 | { | ||
1435 | int host, entry, rup; | ||
1436 | |||
1437 | for ( host=0; host<RIO_HOSTS; host++ ) { | ||
1438 | struct Host *HostP = &p->RIOHosts[host]; | ||
1439 | for ( entry=0; entry<LINKS_PER_UNIT; entry++ ) { | ||
1440 | HostP->Topology[entry].Unit = ROUTE_DISCONNECT; | ||
1441 | HostP->Topology[entry].Link = NO_LINK; | ||
1442 | } | ||
1443 | bcopy("HOST X", HostP->Name, 7); | ||
1444 | HostP->Name[5] = '1'+host; | ||
1445 | for (rup=0; rup<(MAX_RUP + LINKS_PER_UNIT); rup++) { | ||
1446 | if (rup < MAX_RUP) { | ||
1447 | for (entry=0; entry<LINKS_PER_UNIT; entry++ ) { | ||
1448 | HostP->Mapping[rup].Topology[entry].Unit = ROUTE_DISCONNECT; | ||
1449 | HostP->Mapping[rup].Topology[entry].Link = NO_LINK; | ||
1450 | } | ||
1451 | RIODefaultName(p, HostP, rup); | ||
1452 | } | ||
1453 | spin_lock_init(&HostP->UnixRups[rup].RupLock); | ||
1454 | } | ||
1455 | } | ||
1456 | } | ||
1457 | #endif | ||
1458 | |||
1459 | int | ||
1460 | RIODefaultName(p, HostP, UnitId) | ||
1461 | struct rio_info * p; | ||
1462 | struct Host * HostP; | ||
1463 | uint UnitId; | ||
1464 | { | ||
1465 | #ifdef CHECK | ||
1466 | CheckHost( Host ); | ||
1467 | CheckUnitId( UnitId ); | ||
1468 | #endif | ||
1469 | bcopy("UNKNOWN RTA X-XX",HostP->Mapping[UnitId].Name,17); | ||
1470 | HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts); | ||
1471 | if ((UnitId+1) > 9) { | ||
1472 | HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10); | ||
1473 | HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10); | ||
1474 | } | ||
1475 | else { | ||
1476 | HostP->Mapping[UnitId].Name[14]='1'+UnitId; | ||
1477 | HostP->Mapping[UnitId].Name[15]=0; | ||
1478 | } | ||
1479 | return 0; | ||
1480 | } | ||
1481 | |||
1482 | #define RIO_RELEASE "Linux" | ||
1483 | #define RELEASE_ID "1.0" | ||
1484 | |||
1485 | #if 0 | ||
1486 | static int | ||
1487 | RIOReport(p) | ||
1488 | struct rio_info * p; | ||
1489 | { | ||
1490 | char * RIORelease = RIO_RELEASE; | ||
1491 | char * RIORelID = RELEASE_ID; | ||
1492 | int host; | ||
1493 | |||
1494 | rio_dprintk (RIO_DEBUG_INIT, "RIO : Release: %s ID: %s\n", RIORelease, RIORelID); | ||
1495 | |||
1496 | if ( p->RIONumHosts==0 ) { | ||
1497 | rio_dprintk (RIO_DEBUG_INIT, "\nNo Hosts configured\n"); | ||
1498 | return(0); | ||
1499 | } | ||
1500 | |||
1501 | for ( host=0; host < p->RIONumHosts; host++ ) { | ||
1502 | struct Host *HostP = &p->RIOHosts[host]; | ||
1503 | switch ( HostP->Type ) { | ||
1504 | case RIO_AT: | ||
1505 | rio_dprintk (RIO_DEBUG_INIT, "AT BUS : found the card at 0x%x\n", HostP->PaddrP); | ||
1506 | } | ||
1507 | } | ||
1508 | return 0; | ||
1509 | } | ||
1510 | #endif | ||
1511 | |||
1512 | static struct rioVersion stVersion; | ||
1513 | |||
1514 | struct rioVersion * | ||
1515 | RIOVersid(void) | ||
1516 | { | ||
1517 | strlcpy(stVersion.version, "RIO driver for linux V1.0", | ||
1518 | sizeof(stVersion.version)); | ||
1519 | strlcpy(stVersion.buildDate, __DATE__, | ||
1520 | sizeof(stVersion.buildDate)); | ||
1521 | |||
1522 | return &stVersion; | ||
1523 | } | ||
1524 | |||
1525 | #if 0 | ||
1526 | int | ||
1527 | RIOMapin(paddr, size, vaddr) | ||
1528 | paddr_t paddr; | ||
1529 | int size; | ||
1530 | caddr_t * vaddr; | ||
1531 | { | ||
1532 | *vaddr = (caddr_t)permap( (long)paddr, size); | ||
1533 | return ((int)*vaddr); | ||
1534 | } | ||
1535 | |||
1536 | void | ||
1537 | RIOMapout(paddr, size, vaddr) | ||
1538 | paddr_t paddr; | ||
1539 | long size; | ||
1540 | caddr_t vaddr; | ||
1541 | { | ||
1542 | } | ||
1543 | #endif | ||
1544 | |||
1545 | |||
1546 | void | ||
1547 | RIOHostReset(Type, DpRamP, Slot) | ||
1548 | uint Type; | ||
1549 | volatile struct DpRam *DpRamP; | ||
1550 | uint Slot; | ||
1551 | { | ||
1552 | /* | ||
1553 | ** Reset the Tpu | ||
1554 | */ | ||
1555 | rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: type 0x%x", Type); | ||
1556 | switch ( Type ) { | ||
1557 | case RIO_AT: | ||
1558 | rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n"); | ||
1559 | WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF | | ||
1560 | INTERRUPT_DISABLE | BYTE_OPERATION | | ||
1561 | SLOW_LINKS | SLOW_AT_BUS); | ||
1562 | WBYTE(DpRamP->DpResetTpu, 0xFF); | ||
1563 | rio_udelay (3); | ||
1564 | |||
1565 | rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n"); | ||
1566 | WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF | | ||
1567 | INTERRUPT_DISABLE | BYTE_OPERATION | | ||
1568 | SLOW_LINKS | SLOW_AT_BUS); | ||
1569 | WBYTE(DpRamP->DpResetTpu, 0xFF); | ||
1570 | rio_udelay (3); | ||
1571 | break; | ||
1572 | #ifdef FUTURE_RELEASE | ||
1573 | case RIO_EISA: | ||
1574 | /* | ||
1575 | ** Bet this doesn't work! | ||
1576 | */ | ||
1577 | OUTBZ( Slot, EISA_CONTROL_PORT, | ||
1578 | EISA_TP_RUN | EISA_TP_BUS_DISABLE | | ||
1579 | EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM ); | ||
1580 | OUTBZ( Slot, EISA_CONTROL_PORT, | ||
1581 | EISA_TP_RESET | EISA_TP_BUS_DISABLE | | ||
1582 | EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM ); | ||
1583 | suspend( 3 ); | ||
1584 | OUTBZ( Slot, EISA_CONTROL_PORT, | ||
1585 | EISA_TP_RUN | EISA_TP_BUS_DISABLE | | ||
1586 | EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM ); | ||
1587 | break; | ||
1588 | case RIO_MCA: | ||
1589 | WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable ); | ||
1590 | WBYTE(DpRamP->DpResetTpu , 0xFF ); | ||
1591 | suspend( 3 ); | ||
1592 | WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable ); | ||
1593 | WBYTE(DpRamP->DpResetTpu , 0xFF ); | ||
1594 | suspend( 3 ); | ||
1595 | break; | ||
1596 | #endif | ||
1597 | case RIO_PCI: | ||
1598 | rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n"); | ||
1599 | DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM; | ||
1600 | DpRamP->DpResetInt = 0xFF; | ||
1601 | DpRamP->DpResetTpu = 0xFF; | ||
1602 | rio_udelay (100); | ||
1603 | /* for (i=0; i<6000; i++); */ | ||
1604 | /* suspend( 3 ); */ | ||
1605 | break; | ||
1606 | #ifdef FUTURE_RELEASE | ||
1607 | default: | ||
1608 | Rprintf(RIOMesgNoSupport,Type,DpRamP,Slot); | ||
1609 | return; | ||
1610 | #endif | ||
1611 | |||
1612 | default: | ||
1613 | rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n"); | ||
1614 | break; | ||
1615 | } | ||
1616 | return; | ||
1617 | } | ||
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c new file mode 100644 index 000000000000..e42e7b50bf6b --- /dev/null +++ b/drivers/char/rio/riointr.c | |||
@@ -0,0 +1,951 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : riointr.c | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 10:33:44 | ||
26 | ** Retrieved : 11/6/98 10:33:49 | ||
27 | ** | ||
28 | ** ident @(#)riointr.c 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | #ifdef SCCS_LABELS | ||
33 | static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2"; | ||
34 | #endif | ||
35 | |||
36 | |||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/errno.h> | ||
40 | #include <linux/tty.h> | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/string.h> | ||
44 | #include <asm/semaphore.h> | ||
45 | #include <asm/uaccess.h> | ||
46 | |||
47 | #include <linux/termios.h> | ||
48 | #include <linux/serial.h> | ||
49 | |||
50 | #include <linux/generic_serial.h> | ||
51 | |||
52 | #include <linux/delay.h> | ||
53 | |||
54 | #include "linux_compat.h" | ||
55 | #include "rio_linux.h" | ||
56 | #include "typdef.h" | ||
57 | #include "pkt.h" | ||
58 | #include "daemon.h" | ||
59 | #include "rio.h" | ||
60 | #include "riospace.h" | ||
61 | #include "top.h" | ||
62 | #include "cmdpkt.h" | ||
63 | #include "map.h" | ||
64 | #include "riotypes.h" | ||
65 | #include "rup.h" | ||
66 | #include "port.h" | ||
67 | #include "riodrvr.h" | ||
68 | #include "rioinfo.h" | ||
69 | #include "func.h" | ||
70 | #include "errors.h" | ||
71 | #include "pci.h" | ||
72 | |||
73 | #include "parmmap.h" | ||
74 | #include "unixrup.h" | ||
75 | #include "board.h" | ||
76 | #include "host.h" | ||
77 | #include "error.h" | ||
78 | #include "phb.h" | ||
79 | #include "link.h" | ||
80 | #include "cmdblk.h" | ||
81 | #include "route.h" | ||
82 | #include "control.h" | ||
83 | #include "cirrus.h" | ||
84 | #include "rioioctl.h" | ||
85 | |||
86 | |||
87 | static void RIOReceive(struct rio_info *, struct Port *); | ||
88 | |||
89 | |||
90 | static char *firstchars (char *p, int nch) | ||
91 | { | ||
92 | static char buf[2][128]; | ||
93 | static int t=0; | ||
94 | t = ! t; | ||
95 | memcpy (buf[t], p, nch); | ||
96 | buf[t][nch] = 0; | ||
97 | return buf[t]; | ||
98 | } | ||
99 | |||
100 | |||
101 | #define INCR( P, I ) ((P) = (((P)+(I)) & p->RIOBufferMask)) | ||
102 | /* Enable and start the transmission of packets */ | ||
103 | void | ||
104 | RIOTxEnable(en) | ||
105 | char * en; | ||
106 | { | ||
107 | struct Port * PortP; | ||
108 | struct rio_info *p; | ||
109 | struct tty_struct* tty; | ||
110 | int c; | ||
111 | struct PKT * PacketP; | ||
112 | unsigned long flags; | ||
113 | |||
114 | PortP = (struct Port *)en; | ||
115 | p = (struct rio_info *)PortP->p; | ||
116 | tty = PortP->gs.tty; | ||
117 | |||
118 | |||
119 | rio_dprintk (RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", | ||
120 | PortP->PortNum, PortP->gs.xmit_cnt); | ||
121 | |||
122 | if (!PortP->gs.xmit_cnt) return; | ||
123 | |||
124 | |||
125 | /* This routine is an order of magnitude simpler than the specialix | ||
126 | version. One of the disadvantages is that this version will send | ||
127 | an incomplete packet (usually 64 bytes instead of 72) once for | ||
128 | every 4k worth of data. Let's just say that this won't influence | ||
129 | performance significantly..... */ | ||
130 | |||
131 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
132 | |||
133 | while (can_add_transmit( &PacketP, PortP )) { | ||
134 | c = PortP->gs.xmit_cnt; | ||
135 | if (c > PKT_MAX_DATA_LEN) c = PKT_MAX_DATA_LEN; | ||
136 | |||
137 | /* Don't copy past the end of the source buffer */ | ||
138 | if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail) | ||
139 | c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail; | ||
140 | |||
141 | { int t; | ||
142 | t = (c > 10)?10:c; | ||
143 | |||
144 | rio_dprintk (RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", | ||
145 | PortP->PortNum, c, | ||
146 | firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail , t), | ||
147 | firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail + c-t, t)); | ||
148 | } | ||
149 | /* If for one reason or another, we can't copy more data, | ||
150 | we're done! */ | ||
151 | if (c == 0) break; | ||
152 | |||
153 | rio_memcpy_toio (PortP->HostP->Caddr, (caddr_t)PacketP->data, | ||
154 | PortP->gs.xmit_buf + PortP->gs.xmit_tail, c); | ||
155 | /* udelay (1); */ | ||
156 | |||
157 | writeb (c, &(PacketP->len)); | ||
158 | if (!( PortP->State & RIO_DELETED ) ) { | ||
159 | add_transmit ( PortP ); | ||
160 | /* | ||
161 | ** Count chars tx'd for port statistics reporting | ||
162 | */ | ||
163 | if ( PortP->statsGather ) | ||
164 | PortP->txchars += c; | ||
165 | } | ||
166 | PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1); | ||
167 | PortP->gs.xmit_cnt -= c; | ||
168 | } | ||
169 | |||
170 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
171 | |||
172 | if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2*PKT_MAX_DATA_LEN)) { | ||
173 | rio_dprintk (RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....", | ||
174 | (int)(PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)), | ||
175 | PortP->gs.wakeup_chars, PortP->gs.xmit_cnt); | ||
176 | if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && | ||
177 | PortP->gs.tty->ldisc.write_wakeup) | ||
178 | (PortP->gs.tty->ldisc.write_wakeup)(PortP->gs.tty); | ||
179 | rio_dprintk (RIO_DEBUG_INTR, "(%d/%d)\n", | ||
180 | PortP->gs.wakeup_chars, PortP->gs.xmit_cnt); | ||
181 | wake_up_interruptible(&PortP->gs.tty->write_wait); | ||
182 | } | ||
183 | |||
184 | } | ||
185 | |||
186 | |||
187 | /* | ||
188 | ** RIO Host Service routine. Does all the work traditionally associated with an | ||
189 | ** interrupt. | ||
190 | */ | ||
191 | static int RupIntr; | ||
192 | static int RxIntr; | ||
193 | static int TxIntr; | ||
194 | void | ||
195 | RIOServiceHost(p, HostP, From) | ||
196 | struct rio_info * p; | ||
197 | struct Host *HostP; | ||
198 | int From; | ||
199 | { | ||
200 | rio_spin_lock (&HostP->HostLock); | ||
201 | if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) { | ||
202 | static int t =0; | ||
203 | rio_spin_unlock (&HostP->HostLock); | ||
204 | if ((t++ % 200) == 0) | ||
205 | rio_dprintk (RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int)HostP->Flags); | ||
206 | return; | ||
207 | } | ||
208 | rio_spin_unlock (&HostP->HostLock); | ||
209 | |||
210 | if ( RWORD( HostP->ParmMapP->rup_intr ) ) { | ||
211 | WWORD( HostP->ParmMapP->rup_intr , 0 ); | ||
212 | p->RIORupCount++; | ||
213 | RupIntr++; | ||
214 | rio_dprintk (RIO_DEBUG_INTR, "rio: RUP interrupt on host %d\n", HostP-p->RIOHosts); | ||
215 | RIOPollHostCommands(p, HostP ); | ||
216 | } | ||
217 | |||
218 | if ( RWORD( HostP->ParmMapP->rx_intr ) ) { | ||
219 | int port; | ||
220 | |||
221 | WWORD( HostP->ParmMapP->rx_intr , 0 ); | ||
222 | p->RIORxCount++; | ||
223 | RxIntr++; | ||
224 | |||
225 | rio_dprintk (RIO_DEBUG_INTR, "rio: RX interrupt on host %d\n", HostP-p->RIOHosts); | ||
226 | /* | ||
227 | ** Loop through every port. If the port is mapped into | ||
228 | ** the system ( i.e. has /dev/ttyXXXX associated ) then it is | ||
229 | ** worth checking. If the port isn't open, grab any packets | ||
230 | ** hanging on its receive queue and stuff them on the free | ||
231 | ** list; check for commands on the way. | ||
232 | */ | ||
233 | for ( port=p->RIOFirstPortsBooted; | ||
234 | port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) { | ||
235 | struct Port *PortP = p->RIOPortp[port]; | ||
236 | struct tty_struct *ttyP; | ||
237 | struct PKT *PacketP; | ||
238 | |||
239 | /* | ||
240 | ** not mapped in - most of the RIOPortp[] information | ||
241 | ** has not been set up! | ||
242 | ** Optimise: ports come in bundles of eight. | ||
243 | */ | ||
244 | if ( !PortP->Mapped ) { | ||
245 | port += 7; | ||
246 | continue; /* with the next port */ | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | ** If the host board isn't THIS host board, check the next one. | ||
251 | ** optimise: ports come in bundles of eight. | ||
252 | */ | ||
253 | if ( PortP->HostP != HostP ) { | ||
254 | port += 7; | ||
255 | continue; | ||
256 | } | ||
257 | |||
258 | /* | ||
259 | ** Let us see - is the port open? If not, then don't service it. | ||
260 | */ | ||
261 | if ( !( PortP->PortState & PORT_ISOPEN ) ) { | ||
262 | continue; | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | ** find corresponding tty structure. The process of mapping | ||
267 | ** the ports puts these here. | ||
268 | */ | ||
269 | ttyP = PortP->gs.tty; | ||
270 | |||
271 | /* | ||
272 | ** Lock the port before we begin working on it. | ||
273 | */ | ||
274 | rio_spin_lock(&PortP->portSem); | ||
275 | |||
276 | /* | ||
277 | ** Process received data if there is any. | ||
278 | */ | ||
279 | if ( can_remove_receive( &PacketP, PortP ) ) | ||
280 | RIOReceive(p, PortP); | ||
281 | |||
282 | /* | ||
283 | ** If there is no data left to be read from the port, and | ||
284 | ** it's handshake bit is set, then we must clear the handshake, | ||
285 | ** so that that downstream RTA is re-enabled. | ||
286 | */ | ||
287 | if ( !can_remove_receive( &PacketP, PortP ) && | ||
288 | ( RWORD( PortP->PhbP->handshake )==PHB_HANDSHAKE_SET ) ) { | ||
289 | /* | ||
290 | ** MAGIC! ( Basically, handshake the RX buffer, so that | ||
291 | ** the RTAs upstream can be re-enabled. ) | ||
292 | */ | ||
293 | rio_dprintk (RIO_DEBUG_INTR, "Set RX handshake bit\n"); | ||
294 | WWORD( PortP->PhbP->handshake, | ||
295 | PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET ); | ||
296 | } | ||
297 | rio_spin_unlock(&PortP->portSem); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | if ( RWORD( HostP->ParmMapP->tx_intr ) ) { | ||
302 | int port; | ||
303 | |||
304 | WWORD( HostP->ParmMapP->tx_intr , 0); | ||
305 | |||
306 | p->RIOTxCount++; | ||
307 | TxIntr++; | ||
308 | rio_dprintk (RIO_DEBUG_INTR, "rio: TX interrupt on host %d\n", HostP-p->RIOHosts); | ||
309 | |||
310 | /* | ||
311 | ** Loop through every port. | ||
312 | ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX | ||
313 | ** associated ) then it is worth checking. | ||
314 | */ | ||
315 | for ( port=p->RIOFirstPortsBooted; | ||
316 | port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) { | ||
317 | struct Port *PortP = p->RIOPortp[port]; | ||
318 | struct tty_struct *ttyP; | ||
319 | struct PKT *PacketP; | ||
320 | |||
321 | /* | ||
322 | ** not mapped in - most of the RIOPortp[] information | ||
323 | ** has not been set up! | ||
324 | */ | ||
325 | if ( !PortP->Mapped ) { | ||
326 | port += 7; | ||
327 | continue; /* with the next port */ | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | ** If the host board isn't running, then its data structures | ||
332 | ** are no use to us - continue quietly. | ||
333 | */ | ||
334 | if ( PortP->HostP != HostP ) { | ||
335 | port += 7; | ||
336 | continue; /* with the next port */ | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | ** Let us see - is the port open? If not, then don't service it. | ||
341 | */ | ||
342 | if ( !( PortP->PortState & PORT_ISOPEN ) ) { | ||
343 | continue; | ||
344 | } | ||
345 | |||
346 | rio_dprintk (RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port); | ||
347 | /* | ||
348 | ** Lock the port before we begin working on it. | ||
349 | */ | ||
350 | rio_spin_lock(&PortP->portSem); | ||
351 | |||
352 | /* | ||
353 | ** If we can't add anything to the transmit queue, then | ||
354 | ** we need do none of this processing. | ||
355 | */ | ||
356 | if ( !can_add_transmit( &PacketP, PortP ) ) { | ||
357 | rio_dprintk (RIO_DEBUG_INTR, "Can't add to port, so skipping.\n"); | ||
358 | rio_spin_unlock(&PortP->portSem); | ||
359 | continue; | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | ** find corresponding tty structure. The process of mapping | ||
364 | ** the ports puts these here. | ||
365 | */ | ||
366 | ttyP = PortP->gs.tty; | ||
367 | /* If ttyP is NULL, the port is getting closed. Forget about it. */ | ||
368 | if (!ttyP) { | ||
369 | rio_dprintk (RIO_DEBUG_INTR, "no tty, so skipping.\n"); | ||
370 | rio_spin_unlock(&PortP->portSem); | ||
371 | continue; | ||
372 | } | ||
373 | /* | ||
374 | ** If there is more room available we start up the transmit | ||
375 | ** data process again. This can be direct I/O, if the cookmode | ||
376 | ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the | ||
377 | ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch | ||
378 | ** characters via the line discipline. We must always call | ||
379 | ** the line discipline, | ||
380 | ** so that user input characters can be echoed correctly. | ||
381 | ** | ||
382 | ** ++++ Update +++++ | ||
383 | ** With the advent of double buffering, we now see if | ||
384 | ** TxBufferOut-In is non-zero. If so, then we copy a packet | ||
385 | ** to the output place, and set it going. If this empties | ||
386 | ** the buffer, then we must issue a wakeup( ) on OUT. | ||
387 | ** If it frees space in the buffer then we must issue | ||
388 | ** a wakeup( ) on IN. | ||
389 | ** | ||
390 | ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we | ||
391 | ** have to send a WFLUSH command down the PHB, to mark the | ||
392 | ** end point of a WFLUSH. We also need to clear out any | ||
393 | ** data from the double buffer! ( note that WflushFlag is a | ||
394 | ** *count* of the number of WFLUSH commands outstanding! ) | ||
395 | ** | ||
396 | ** ++++ And there's more! | ||
397 | ** If an RTA is powered off, then on again, and rebooted, | ||
398 | ** whilst it has ports open, then we need to re-open the ports. | ||
399 | ** ( reasonable enough ). We can't do this when we spot the | ||
400 | ** re-boot, in interrupt time, because the queue is probably | ||
401 | ** full. So, when we come in here, we need to test if any | ||
402 | ** ports are in this condition, and re-open the port before | ||
403 | ** we try to send any more data to it. Now, the re-booted | ||
404 | ** RTA will be discarding packets from the PHB until it | ||
405 | ** receives this open packet, but don't worry tooo much | ||
406 | ** about that. The one thing that is interesting is the | ||
407 | ** combination of this effect and the WFLUSH effect! | ||
408 | */ | ||
409 | /* For now don't handle RTA reboots. -- REW. | ||
410 | Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */ | ||
411 | if ( PortP->MagicFlags ) { | ||
412 | #if 1 | ||
413 | if ( PortP->MagicFlags & MAGIC_REBOOT ) { | ||
414 | /* | ||
415 | ** well, the RTA has been rebooted, and there is room | ||
416 | ** on its queue to add the open packet that is required. | ||
417 | ** | ||
418 | ** The messy part of this line is trying to decide if | ||
419 | ** we need to call the Param function as a tty or as | ||
420 | ** a modem. | ||
421 | ** DONT USE CLOCAL AS A TEST FOR THIS! | ||
422 | ** | ||
423 | ** If we can't param the port, then move on to the | ||
424 | ** next port. | ||
425 | */ | ||
426 | PortP->InUse = NOT_INUSE; | ||
427 | |||
428 | rio_spin_unlock(&PortP->portSem); | ||
429 | if ( RIOParam(PortP, OPEN, ((PortP->Cor2Copy & | ||
430 | (COR2_RTSFLOW|COR2_CTSFLOW ) )== | ||
431 | (COR2_RTSFLOW|COR2_CTSFLOW ) ) ? | ||
432 | TRUE : FALSE, DONT_SLEEP ) == RIO_FAIL ) { | ||
433 | continue; /* with next port */ | ||
434 | } | ||
435 | rio_spin_lock(&PortP->portSem); | ||
436 | PortP->MagicFlags &= ~MAGIC_REBOOT; | ||
437 | } | ||
438 | #endif | ||
439 | |||
440 | /* | ||
441 | ** As mentioned above, this is a tacky hack to cope | ||
442 | ** with WFLUSH | ||
443 | */ | ||
444 | if ( PortP->WflushFlag ) { | ||
445 | rio_dprintk (RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n"); | ||
446 | |||
447 | if ( PortP->InUse ) | ||
448 | rio_dprintk (RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n"); | ||
449 | } | ||
450 | |||
451 | while ( PortP->WflushFlag && | ||
452 | can_add_transmit( &PacketP, PortP ) && | ||
453 | ( PortP->InUse == NOT_INUSE ) ) { | ||
454 | int p; | ||
455 | struct PktCmd *PktCmdP; | ||
456 | |||
457 | rio_dprintk (RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n"); | ||
458 | /* | ||
459 | ** make it look just like a WFLUSH command | ||
460 | */ | ||
461 | PktCmdP = ( struct PktCmd * )&PacketP->data[0]; | ||
462 | |||
463 | WBYTE( PktCmdP->Command , WFLUSH ); | ||
464 | |||
465 | p = PortP->HostPort % ( ushort )PORTS_PER_RTA; | ||
466 | |||
467 | /* | ||
468 | ** If second block of ports for 16 port RTA, add 8 | ||
469 | ** to index 8-15. | ||
470 | */ | ||
471 | if ( PortP->SecondBlock ) | ||
472 | p += PORTS_PER_RTA; | ||
473 | |||
474 | WBYTE( PktCmdP->PhbNum, p ); | ||
475 | |||
476 | /* | ||
477 | ** to make debuggery easier | ||
478 | */ | ||
479 | WBYTE( PacketP->data[ 2], 'W' ); | ||
480 | WBYTE( PacketP->data[ 3], 'F' ); | ||
481 | WBYTE( PacketP->data[ 4], 'L' ); | ||
482 | WBYTE( PacketP->data[ 5], 'U' ); | ||
483 | WBYTE( PacketP->data[ 6], 'S' ); | ||
484 | WBYTE( PacketP->data[ 7], 'H' ); | ||
485 | WBYTE( PacketP->data[ 8], ' ' ); | ||
486 | WBYTE( PacketP->data[ 9], '0'+PortP->WflushFlag ); | ||
487 | WBYTE( PacketP->data[10], ' ' ); | ||
488 | WBYTE( PacketP->data[11], ' ' ); | ||
489 | WBYTE( PacketP->data[12], '\0' ); | ||
490 | |||
491 | /* | ||
492 | ** its two bytes long! | ||
493 | */ | ||
494 | WBYTE( PacketP->len , PKT_CMD_BIT | 2 ); | ||
495 | |||
496 | /* | ||
497 | ** queue it! | ||
498 | */ | ||
499 | if ( !( PortP->State & RIO_DELETED ) ) { | ||
500 | add_transmit( PortP ); | ||
501 | /* | ||
502 | ** Count chars tx'd for port statistics reporting | ||
503 | */ | ||
504 | if ( PortP->statsGather ) | ||
505 | PortP->txchars += 2; | ||
506 | } | ||
507 | |||
508 | if ( --( PortP->WflushFlag ) == 0 ) { | ||
509 | PortP->MagicFlags &= ~MAGIC_FLUSH; | ||
510 | } | ||
511 | |||
512 | rio_dprintk (RIO_DEBUG_INTR, "Wflush count now stands at %d\n", | ||
513 | PortP->WflushFlag); | ||
514 | } | ||
515 | if ( PortP->MagicFlags & MORE_OUTPUT_EYGOR ) { | ||
516 | if ( PortP->MagicFlags & MAGIC_FLUSH ) { | ||
517 | PortP->MagicFlags |= MORE_OUTPUT_EYGOR; | ||
518 | } | ||
519 | else { | ||
520 | if ( !can_add_transmit( &PacketP, PortP ) ) { | ||
521 | rio_spin_unlock(&PortP->portSem); | ||
522 | continue; | ||
523 | } | ||
524 | rio_spin_unlock(&PortP->portSem); | ||
525 | RIOTxEnable((char *)PortP); | ||
526 | rio_spin_lock(&PortP->portSem); | ||
527 | PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR; | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | |||
532 | |||
533 | /* | ||
534 | ** If we can't add anything to the transmit queue, then | ||
535 | ** we need do none of the remaining processing. | ||
536 | */ | ||
537 | if (!can_add_transmit( &PacketP, PortP ) ) { | ||
538 | rio_spin_unlock(&PortP->portSem); | ||
539 | continue; | ||
540 | } | ||
541 | |||
542 | rio_spin_unlock(&PortP->portSem); | ||
543 | RIOTxEnable((char *)PortP); | ||
544 | } | ||
545 | } | ||
546 | } | ||
547 | |||
548 | /* | ||
549 | ** Routine for handling received data for clist drivers. | ||
550 | ** NB: Called with the tty locked. The spl from the lockb( ) is passed. | ||
551 | ** we return the ttySpl level that we re-locked at. | ||
552 | */ | ||
553 | static void | ||
554 | RIOReceive(p, PortP) | ||
555 | struct rio_info * p; | ||
556 | struct Port * PortP; | ||
557 | { | ||
558 | struct tty_struct *TtyP; | ||
559 | register ushort transCount; | ||
560 | struct PKT *PacketP; | ||
561 | register uint DataCnt; | ||
562 | uchar * ptr; | ||
563 | int copied =0; | ||
564 | |||
565 | static int intCount, RxIntCnt; | ||
566 | |||
567 | /* | ||
568 | ** The receive data process is to remove packets from the | ||
569 | ** PHB until there aren't any more or the current cblock | ||
570 | ** is full. When this occurs, there will be some left over | ||
571 | ** data in the packet, that we must do something with. | ||
572 | ** As we haven't unhooked the packet from the read list | ||
573 | ** yet, we can just leave the packet there, having first | ||
574 | ** made a note of how far we got. This means that we need | ||
575 | ** a pointer per port saying where we start taking the | ||
576 | ** data from - this will normally be zero, but when we | ||
577 | ** run out of space it will be set to the offset of the | ||
578 | ** next byte to copy from the packet data area. The packet | ||
579 | ** length field is decremented by the number of bytes that | ||
580 | ** we succesfully removed from the packet. When this reaches | ||
581 | ** zero, we reset the offset pointer to be zero, and free | ||
582 | ** the packet from the front of the queue. | ||
583 | */ | ||
584 | |||
585 | intCount++; | ||
586 | |||
587 | TtyP = PortP->gs.tty; | ||
588 | if (!TtyP) { | ||
589 | rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: tty is null. \n"); | ||
590 | return; | ||
591 | } | ||
592 | |||
593 | if (PortP->State & RIO_THROTTLE_RX) { | ||
594 | rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n"); | ||
595 | return; | ||
596 | } | ||
597 | |||
598 | if ( PortP->State & RIO_DELETED ) | ||
599 | { | ||
600 | while ( can_remove_receive( &PacketP, PortP ) ) | ||
601 | { | ||
602 | remove_receive( PortP ); | ||
603 | put_free_end( PortP->HostP, PacketP ); | ||
604 | } | ||
605 | } | ||
606 | else | ||
607 | { | ||
608 | /* | ||
609 | ** loop, just so long as: | ||
610 | ** i ) there's some data ( i.e. can_remove_receive ) | ||
611 | ** ii ) we haven't been blocked | ||
612 | ** iii ) there's somewhere to put the data | ||
613 | ** iv ) we haven't outstayed our welcome | ||
614 | */ | ||
615 | transCount = 1; | ||
616 | while ( can_remove_receive(&PacketP, PortP) | ||
617 | && transCount) | ||
618 | { | ||
619 | #ifdef STATS | ||
620 | PortP->Stat.RxIntCnt++; | ||
621 | #endif /* STATS */ | ||
622 | RxIntCnt++; | ||
623 | |||
624 | /* | ||
625 | ** check that it is not a command! | ||
626 | */ | ||
627 | if ( PacketP->len & PKT_CMD_BIT ) { | ||
628 | rio_dprintk (RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n"); | ||
629 | /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */ | ||
630 | rio_dprintk (RIO_DEBUG_INTR, " dest_unit = %d\n", PacketP->dest_unit); | ||
631 | rio_dprintk (RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port); | ||
632 | rio_dprintk (RIO_DEBUG_INTR, " src_unit = %d\n", PacketP->src_unit); | ||
633 | rio_dprintk (RIO_DEBUG_INTR, " src_port = %d\n", PacketP->src_port); | ||
634 | rio_dprintk (RIO_DEBUG_INTR, " len = %d\n", PacketP->len); | ||
635 | rio_dprintk (RIO_DEBUG_INTR, " control = %d\n", PacketP->control); | ||
636 | rio_dprintk (RIO_DEBUG_INTR, " csum = %d\n", PacketP->csum); | ||
637 | rio_dprintk (RIO_DEBUG_INTR, " data bytes: "); | ||
638 | for ( DataCnt=0; DataCnt<PKT_MAX_DATA_LEN; DataCnt++ ) | ||
639 | rio_dprintk (RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]); | ||
640 | remove_receive( PortP ); | ||
641 | put_free_end( PortP->HostP, PacketP ); | ||
642 | continue; /* with next packet */ | ||
643 | } | ||
644 | |||
645 | /* | ||
646 | ** How many characters can we move 'upstream' ? | ||
647 | ** | ||
648 | ** Determine the minimum of the amount of data | ||
649 | ** available and the amount of space in which to | ||
650 | ** put it. | ||
651 | ** | ||
652 | ** 1. Get the packet length by masking 'len' | ||
653 | ** for only the length bits. | ||
654 | ** 2. Available space is [buffer size] - [space used] | ||
655 | ** | ||
656 | ** Transfer count is the minimum of packet length | ||
657 | ** and available space. | ||
658 | */ | ||
659 | |||
660 | transCount = min_t(unsigned int, PacketP->len & PKT_LEN_MASK, | ||
661 | TTY_FLIPBUF_SIZE - TtyP->flip.count); | ||
662 | rio_dprintk (RIO_DEBUG_REC, "port %d: Copy %d bytes\n", | ||
663 | PortP->PortNum, transCount); | ||
664 | /* | ||
665 | ** To use the following 'kkprintfs' for debugging - change the '#undef' | ||
666 | ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the | ||
667 | ** driver). | ||
668 | */ | ||
669 | #undef ___DEBUG_IT___ | ||
670 | #ifdef ___DEBUG_IT___ | ||
671 | kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ", | ||
672 | intCount, | ||
673 | RxIntCnt, | ||
674 | PortP->PortNum, | ||
675 | TtyP->rxqueue.count, | ||
676 | transCount, | ||
677 | TtyP->flags ); | ||
678 | #endif | ||
679 | ptr = (uchar *) PacketP->data + PortP->RxDataStart; | ||
680 | |||
681 | rio_memcpy_fromio (TtyP->flip.char_buf_ptr, ptr, transCount); | ||
682 | memset(TtyP->flip.flag_buf_ptr, TTY_NORMAL, transCount); | ||
683 | |||
684 | #ifdef STATS | ||
685 | /* | ||
686 | ** keep a count for statistical purposes | ||
687 | */ | ||
688 | PortP->Stat.RxCharCnt += transCount; | ||
689 | #endif | ||
690 | PortP->RxDataStart += transCount; | ||
691 | PacketP->len -= transCount; | ||
692 | copied += transCount; | ||
693 | TtyP->flip.count += transCount; | ||
694 | TtyP->flip.char_buf_ptr += transCount; | ||
695 | TtyP->flip.flag_buf_ptr += transCount; | ||
696 | |||
697 | |||
698 | #ifdef ___DEBUG_IT___ | ||
699 | kkprintf("T:%d L:%d\n", DataCnt, PacketP->len ); | ||
700 | #endif | ||
701 | |||
702 | if ( PacketP->len == 0 ) | ||
703 | { | ||
704 | /* | ||
705 | ** If we have emptied the packet, then we can | ||
706 | ** free it, and reset the start pointer for | ||
707 | ** the next packet. | ||
708 | */ | ||
709 | remove_receive( PortP ); | ||
710 | put_free_end( PortP->HostP, PacketP ); | ||
711 | PortP->RxDataStart = 0; | ||
712 | #ifdef STATS | ||
713 | /* | ||
714 | ** more lies ( oops, I mean statistics ) | ||
715 | */ | ||
716 | PortP->Stat.RxPktCnt++; | ||
717 | #endif /* STATS */ | ||
718 | } | ||
719 | } | ||
720 | } | ||
721 | if (copied) { | ||
722 | rio_dprintk (RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied); | ||
723 | tty_flip_buffer_push (TtyP); | ||
724 | } | ||
725 | |||
726 | return; | ||
727 | } | ||
728 | |||
729 | #ifdef FUTURE_RELEASE | ||
730 | /* | ||
731 | ** The proc routine called by the line discipline to do the work for it. | ||
732 | ** The proc routine works hand in hand with the interrupt routine. | ||
733 | */ | ||
734 | int | ||
735 | riotproc(p, tp, cmd, port) | ||
736 | struct rio_info * p; | ||
737 | register struct ttystatics *tp; | ||
738 | int cmd; | ||
739 | int port; | ||
740 | { | ||
741 | register struct Port *PortP; | ||
742 | int SysPort; | ||
743 | struct PKT *PacketP; | ||
744 | |||
745 | SysPort = port; /* Believe me, it works. */ | ||
746 | |||
747 | if ( SysPort < 0 || SysPort >= RIO_PORTS ) { | ||
748 | rio_dprintk (RIO_DEBUG_INTR, "Illegal port %d derived from TTY in riotproc()\n",SysPort); | ||
749 | return 0; | ||
750 | } | ||
751 | PortP = p->RIOPortp[SysPort]; | ||
752 | |||
753 | if ((uint)PortP->PhbP < (uint)PortP->Caddr || | ||
754 | (uint)PortP->PhbP >= (uint)PortP->Caddr+SIXTY_FOUR_K ) { | ||
755 | rio_dprintk (RIO_DEBUG_INTR, "RIO: NULL or BAD PhbP on sys port %d in proc routine\n", | ||
756 | SysPort); | ||
757 | rio_dprintk (RIO_DEBUG_INTR, " PortP = 0x%x\n",PortP); | ||
758 | rio_dprintk (RIO_DEBUG_INTR, " PortP->PhbP = 0x%x\n",PortP->PhbP); | ||
759 | rio_dprintk (RIO_DEBUG_INTR, " PortP->Caddr = 0x%x\n",PortP->PhbP); | ||
760 | rio_dprintk (RIO_DEBUG_INTR, " PortP->HostPort = 0x%x\n",PortP->HostPort); | ||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | switch(cmd) { | ||
765 | case T_WFLUSH: | ||
766 | rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH\n"); | ||
767 | /* | ||
768 | ** Because of the spooky way the RIO works, we don't need | ||
769 | ** to issue a flush command on any of the SET*F commands, | ||
770 | ** as that causes trouble with getty and login, which issue | ||
771 | ** these commands to incur a READ flush, and rely on the fact | ||
772 | ** that the line discipline does a wait for drain for them. | ||
773 | ** As the rio doesn't wait for drain, the write flush would | ||
774 | ** destroy the Password: prompt. This isn't very friendly, so | ||
775 | ** here we only issue a WFLUSH command if we are in the interrupt | ||
776 | ** routine, or we aren't executing a SET*F command. | ||
777 | */ | ||
778 | if ( PortP->HostP->InIntr || !PortP->FlushCmdBodge ) { | ||
779 | /* | ||
780 | ** form a wflush packet - 1 byte long, no data | ||
781 | */ | ||
782 | if ( PortP->State & RIO_DELETED ) { | ||
783 | rio_dprintk (RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n"); | ||
784 | } | ||
785 | else { | ||
786 | if ( RIOPreemptiveCmd(p, PortP, WFLUSH ) == RIO_FAIL ) { | ||
787 | rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command failed\n"); | ||
788 | } | ||
789 | else | ||
790 | rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command\n"); | ||
791 | } | ||
792 | /* | ||
793 | ** WFLUSH operation - flush the data! | ||
794 | */ | ||
795 | PortP->TxBufferIn = PortP->TxBufferOut = 0; | ||
796 | } | ||
797 | else { | ||
798 | rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n"); | ||
799 | } | ||
800 | /* | ||
801 | ** sort out the line discipline | ||
802 | */ | ||
803 | if (PortP->CookMode == COOK_WELL) | ||
804 | goto start; | ||
805 | break; | ||
806 | |||
807 | case T_RESUME: | ||
808 | rio_dprintk (RIO_DEBUG_INTR, "T_RESUME\n"); | ||
809 | /* | ||
810 | ** send pre-emptive resume packet | ||
811 | */ | ||
812 | if ( PortP->State & RIO_DELETED ) { | ||
813 | rio_dprintk (RIO_DEBUG_INTR, "RESUME on deleted RTA\n"); | ||
814 | } | ||
815 | else { | ||
816 | if ( RIOPreemptiveCmd(p, PortP, RESUME ) == RIO_FAIL ) { | ||
817 | rio_dprintk (RIO_DEBUG_INTR, "T_RESUME Command failed\n"); | ||
818 | } | ||
819 | } | ||
820 | /* | ||
821 | ** and re-start the sender software! | ||
822 | */ | ||
823 | if (PortP->CookMode == COOK_WELL) | ||
824 | goto start; | ||
825 | break; | ||
826 | |||
827 | case T_TIME: | ||
828 | rio_dprintk (RIO_DEBUG_INTR, "T_TIME\n"); | ||
829 | /* | ||
830 | ** T_TIME is called when xDLY is set in oflags and | ||
831 | ** the line discipline timeout has expired. It's | ||
832 | ** function in life is to clear the TIMEOUT flag | ||
833 | ** and to re-start output to the port. | ||
834 | */ | ||
835 | /* | ||
836 | ** Fall through and re-start output | ||
837 | */ | ||
838 | case T_OUTPUT: | ||
839 | start: | ||
840 | if ( PortP->MagicFlags & MAGIC_FLUSH ) { | ||
841 | PortP->MagicFlags |= MORE_OUTPUT_EYGOR; | ||
842 | return 0; | ||
843 | } | ||
844 | RIOTxEnable((char *)PortP); | ||
845 | PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR; | ||
846 | /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n");*/ | ||
847 | break; | ||
848 | |||
849 | case T_SUSPEND: | ||
850 | rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND\n"); | ||
851 | /* | ||
852 | ** send a suspend pre-emptive packet. | ||
853 | */ | ||
854 | if ( PortP->State & RIO_DELETED ) { | ||
855 | rio_dprintk (RIO_DEBUG_INTR, "SUSPEND deleted RTA\n"); | ||
856 | } | ||
857 | else { | ||
858 | if ( RIOPreemptiveCmd(p, PortP, SUSPEND ) == RIO_FAIL ) { | ||
859 | rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND Command failed\n"); | ||
860 | } | ||
861 | } | ||
862 | /* | ||
863 | ** done! | ||
864 | */ | ||
865 | break; | ||
866 | |||
867 | case T_BLOCK: | ||
868 | rio_dprintk (RIO_DEBUG_INTR, "T_BLOCK\n"); | ||
869 | break; | ||
870 | |||
871 | case T_RFLUSH: | ||
872 | rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH\n"); | ||
873 | if ( PortP->State & RIO_DELETED ) { | ||
874 | rio_dprintk (RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n"); | ||
875 | PortP->RxDataStart = 0; | ||
876 | } | ||
877 | else { | ||
878 | if ( RIOPreemptiveCmd( p, PortP, RFLUSH ) == RIO_FAIL ) { | ||
879 | rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH Command failed\n"); | ||
880 | return 0; | ||
881 | } | ||
882 | PortP->RxDataStart = 0; | ||
883 | while ( can_remove_receive(&PacketP, PortP) ) { | ||
884 | remove_receive(PortP); | ||
885 | ShowPacket(DBG_PROC, PacketP ); | ||
886 | put_free_end(PortP->HostP, PacketP ); | ||
887 | } | ||
888 | if ( PortP->PhbP->handshake == PHB_HANDSHAKE_SET ) { | ||
889 | /* | ||
890 | ** MAGIC! | ||
891 | */ | ||
892 | rio_dprintk (RIO_DEBUG_INTR, "Set receive handshake bit\n"); | ||
893 | PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET; | ||
894 | } | ||
895 | } | ||
896 | break; | ||
897 | /* FALLTHROUGH */ | ||
898 | case T_UNBLOCK: | ||
899 | rio_dprintk (RIO_DEBUG_INTR, "T_UNBLOCK\n"); | ||
900 | /* | ||
901 | ** If there is any data to receive set a timeout to service it. | ||
902 | */ | ||
903 | RIOReceive(p, PortP); | ||
904 | break; | ||
905 | |||
906 | case T_BREAK: | ||
907 | rio_dprintk (RIO_DEBUG_INTR, "T_BREAK\n"); | ||
908 | /* | ||
909 | ** Send a break command. For Sys V | ||
910 | ** this is a timed break, so we | ||
911 | ** send a SBREAK[time] packet | ||
912 | */ | ||
913 | /* | ||
914 | ** Build a BREAK command | ||
915 | */ | ||
916 | if ( PortP->State & RIO_DELETED ) { | ||
917 | rio_dprintk (RIO_DEBUG_INTR, "BREAK on deleted RTA\n"); | ||
918 | } | ||
919 | else { | ||
920 | if (RIOShortCommand(PortP,SBREAK,2, | ||
921 | p->RIOConf.BreakInterval)==RIO_FAIL) { | ||
922 | rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n"); | ||
923 | } | ||
924 | } | ||
925 | |||
926 | /* | ||
927 | ** done! | ||
928 | */ | ||
929 | break; | ||
930 | |||
931 | case T_INPUT: | ||
932 | rio_dprintk (RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n"); | ||
933 | break; | ||
934 | case T_PARM: | ||
935 | rio_dprintk (RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n"); | ||
936 | break; | ||
937 | |||
938 | case T_SWTCH: | ||
939 | rio_dprintk (RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n"); | ||
940 | break; | ||
941 | |||
942 | default: | ||
943 | rio_dprintk (RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n",cmd); | ||
944 | } | ||
945 | /* | ||
946 | ** T_OUTPUT returns without passing through this point! | ||
947 | */ | ||
948 | /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n");*/ | ||
949 | return(0); | ||
950 | } | ||
951 | #endif | ||
diff --git a/drivers/char/rio/rioioctl.h b/drivers/char/rio/rioioctl.h new file mode 100644 index 000000000000..c3d679733c9a --- /dev/null +++ b/drivers/char/rio/rioioctl.h | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : rioioctl.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:13 | ||
26 | ** Retrieved : 11/6/98 11:34:22 | ||
27 | ** | ||
28 | ** ident @(#)rioioctl.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rioioctl_h__ | ||
34 | #define __rioioctl_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** RIO device driver - user ioctls and associated structures. | ||
42 | */ | ||
43 | |||
44 | struct portStats { | ||
45 | int port; | ||
46 | int gather; | ||
47 | ulong txchars; | ||
48 | ulong rxchars; | ||
49 | ulong opens; | ||
50 | ulong closes; | ||
51 | ulong ioctls; | ||
52 | }; | ||
53 | |||
54 | |||
55 | #define rIOC ('r'<<8) | ||
56 | #define TCRIOSTATE (rIOC | 1) | ||
57 | #define TCRIOXPON (rIOC | 2) | ||
58 | #define TCRIOXPOFF (rIOC | 3) | ||
59 | #define TCRIOXPCPS (rIOC | 4) | ||
60 | #define TCRIOXPRINT (rIOC | 5) | ||
61 | #define TCRIOIXANYON (rIOC | 6) | ||
62 | #define TCRIOIXANYOFF (rIOC | 7) | ||
63 | #define TCRIOIXONON (rIOC | 8) | ||
64 | #define TCRIOIXONOFF (rIOC | 9) | ||
65 | #define TCRIOMBIS (rIOC | 10) | ||
66 | #define TCRIOMBIC (rIOC | 11) | ||
67 | #define TCRIOTRIAD (rIOC | 12) | ||
68 | #define TCRIOTSTATE (rIOC | 13) | ||
69 | |||
70 | /* | ||
71 | ** 15.10.1998 ARG - ESIL 0761 part fix | ||
72 | ** Add RIO ioctls for manipulating RTS and CTS flow control, (as LynxOS | ||
73 | ** appears to not support hardware flow control). | ||
74 | */ | ||
75 | #define TCRIOCTSFLOWEN (rIOC | 14) /* enable CTS flow control */ | ||
76 | #define TCRIOCTSFLOWDIS (rIOC | 15) /* disable CTS flow control */ | ||
77 | #define TCRIORTSFLOWEN (rIOC | 16) /* enable RTS flow control */ | ||
78 | #define TCRIORTSFLOWDIS (rIOC | 17) /* disable RTS flow control */ | ||
79 | |||
80 | /* | ||
81 | ** 09.12.1998 ARG - ESIL 0776 part fix | ||
82 | ** Definition for 'RIOC' also appears in daemon.h, so we'd better do a | ||
83 | ** #ifndef here first. | ||
84 | ** 'RIO_QUICK_CHECK' also #define'd here as this ioctl is now | ||
85 | ** allowed to be used by customers. | ||
86 | ** | ||
87 | ** 05.02.1999 ARG - | ||
88 | ** This is what I've decied to do with ioctls etc., which are intended to be | ||
89 | ** invoked from users applications : | ||
90 | ** Anything that needs to be defined here will be removed from daemon.h, that | ||
91 | ** way it won't end up having to be defined/maintained in two places. The only | ||
92 | ** consequence of this is that this file should now be #include'd by daemon.h | ||
93 | ** | ||
94 | ** 'stats' ioctls now #define'd here as they are to be used by customers. | ||
95 | */ | ||
96 | #define RIOC ('R'<<8)|('i'<<16)|('o'<<24) | ||
97 | |||
98 | #define RIO_QUICK_CHECK (RIOC | 105) | ||
99 | #define RIO_GATHER_PORT_STATS (RIOC | 193) | ||
100 | #define RIO_RESET_PORT_STATS (RIOC | 194) | ||
101 | #define RIO_GET_PORT_STATS (RIOC | 195) | ||
102 | |||
103 | #endif /* __rioioctl_h__ */ | ||
diff --git a/drivers/char/rio/riolocks.h b/drivers/char/rio/riolocks.h new file mode 100644 index 000000000000..0e0cdacebe0b --- /dev/null +++ b/drivers/char/rio/riolocks.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : riolocks.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:13 | ||
26 | ** Retrieved : 11/6/98 11:34:22 | ||
27 | ** | ||
28 | ** ident @(#)riolocks.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_riolocks_h__ | ||
34 | #define __rio_riolocks_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_riolocks_h_sccs_ = "@(#)riolocks.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | #define LOCKB(lk) lockb(lk); | ||
41 | #define UNLOCKB(lk, oldspl) unlockb(lk, oldspl); | ||
42 | |||
43 | #endif | ||
diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c new file mode 100644 index 000000000000..f10916326ecc --- /dev/null +++ b/drivers/char/rio/rioparam.c | |||
@@ -0,0 +1,744 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : rioparam.c | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 10:33:45 | ||
26 | ** Retrieved : 11/6/98 10:33:50 | ||
27 | ** | ||
28 | ** ident @(#)rioparam.c 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifdef SCCS_LABELS | ||
34 | static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; | ||
35 | #endif | ||
36 | |||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/errno.h> | ||
40 | #include <linux/tty.h> | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/string.h> | ||
44 | #include <asm/semaphore.h> | ||
45 | #include <asm/uaccess.h> | ||
46 | |||
47 | #include <linux/termios.h> | ||
48 | #include <linux/serial.h> | ||
49 | |||
50 | #include <linux/generic_serial.h> | ||
51 | |||
52 | |||
53 | #include "linux_compat.h" | ||
54 | #include "rio_linux.h" | ||
55 | #include "typdef.h" | ||
56 | #include "pkt.h" | ||
57 | #include "daemon.h" | ||
58 | #include "rio.h" | ||
59 | #include "riospace.h" | ||
60 | #include "top.h" | ||
61 | #include "cmdpkt.h" | ||
62 | #include "map.h" | ||
63 | #include "riotypes.h" | ||
64 | #include "rup.h" | ||
65 | #include "port.h" | ||
66 | #include "riodrvr.h" | ||
67 | #include "rioinfo.h" | ||
68 | #include "func.h" | ||
69 | #include "errors.h" | ||
70 | #include "pci.h" | ||
71 | |||
72 | #include "parmmap.h" | ||
73 | #include "unixrup.h" | ||
74 | #include "board.h" | ||
75 | #include "host.h" | ||
76 | #include "error.h" | ||
77 | #include "phb.h" | ||
78 | #include "link.h" | ||
79 | #include "cmdblk.h" | ||
80 | #include "route.h" | ||
81 | #include "control.h" | ||
82 | #include "cirrus.h" | ||
83 | #include "rioioctl.h" | ||
84 | #include "param.h" | ||
85 | #include "list.h" | ||
86 | #include "sam.h" | ||
87 | |||
88 | |||
89 | |||
90 | /* | ||
91 | ** The Scam, based on email from jeremyr@bugs.specialix.co.uk.... | ||
92 | ** | ||
93 | ** To send a command on a particular port, you put a packet with the | ||
94 | ** command bit set onto the port. The command bit is in the len field, | ||
95 | ** and gets ORed in with the actual byte count. | ||
96 | ** | ||
97 | ** When you send a packet with the command bit set, then the first | ||
98 | ** data byte ( data[0] ) is interpretted as the command to execute. | ||
99 | ** It also governs what data structure overlay should accompany the packet. | ||
100 | ** Commands are defined in cirrus/cirrus.h | ||
101 | ** | ||
102 | ** If you want the command to pre-emt data already on the queue for the | ||
103 | ** port, set the pre-emptive bit in conjunction with the command bit. | ||
104 | ** It is not defined what will happen if you set the preemptive bit | ||
105 | ** on a packet that is NOT a command. | ||
106 | ** | ||
107 | ** Pre-emptive commands should be queued at the head of the queue using | ||
108 | ** add_start(), whereas normal commands and data are enqueued using | ||
109 | ** add_end(). | ||
110 | ** | ||
111 | ** Most commands do not use the remaining bytes in the data array. The | ||
112 | ** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and | ||
113 | ** OPEN are currently analagous). With these three commands the following | ||
114 | ** 11 data bytes are all used to pass config information such as baud rate etc. | ||
115 | ** The fields are also defined in cirrus.h. Some contain straightforward | ||
116 | ** information such as the transmit XON character. Two contain the transmit and | ||
117 | ** receive baud rates respectively. For most baud rates there is a direct | ||
118 | ** mapping between the rates defined in <sys/termio.h> and the byte in the | ||
119 | ** packet. There are additional (non UNIX-standard) rates defined in | ||
120 | ** /u/dos/rio/cirrus/h/brates.h. | ||
121 | ** | ||
122 | ** The rest of the data fields contain approximations to the Cirrus registers | ||
123 | ** that are used to program number of bits etc. Each registers bit fields is | ||
124 | ** defined in cirrus.h. | ||
125 | ** | ||
126 | ** NB. Only use those bits that are defined as being driver specific | ||
127 | ** or common to the RTA and the driver. | ||
128 | ** | ||
129 | ** All commands going from RTA->Host will be dealt with by the Host code - you | ||
130 | ** will never see them. As with the SI there will be three fields to look out | ||
131 | ** for in each phb (not yet defined - needs defining a.s.a.p). | ||
132 | ** | ||
133 | ** modem_status - current state of handshake pins. | ||
134 | ** | ||
135 | ** port_status - current port status - equivalent to hi_stat for SI, indicates | ||
136 | ** if port is IDLE_OPEN, IDLE_CLOSED etc. | ||
137 | ** | ||
138 | ** break_status - bit X set if break has been received. | ||
139 | ** | ||
140 | ** Happy hacking. | ||
141 | ** | ||
142 | */ | ||
143 | |||
144 | /* | ||
145 | ** RIOParam is used to open or configure a port. You pass it a PortP, | ||
146 | ** which will have a tty struct attached to it. You also pass a command, | ||
147 | ** either OPEN or CONFIG. The port's setup is taken from the t_ fields | ||
148 | ** of the tty struct inside the PortP, and the port is either opened | ||
149 | ** or re-configured. You must also tell RIOParam if the device is a modem | ||
150 | ** device or not (i.e. top bit of minor number set or clear - take special | ||
151 | ** care when deciding on this!). | ||
152 | ** RIOParam neither flushes nor waits for drain, and is NOT preemptive. | ||
153 | ** | ||
154 | ** RIOParam assumes it will be called at splrio(), and also assumes | ||
155 | ** that CookMode is set correctly in the port structure. | ||
156 | ** | ||
157 | ** NB. for MPX | ||
158 | ** tty lock must NOT have been previously acquired. | ||
159 | */ | ||
160 | int | ||
161 | RIOParam(PortP, cmd, Modem, SleepFlag) | ||
162 | struct Port *PortP; | ||
163 | int cmd; | ||
164 | int Modem; | ||
165 | int SleepFlag; | ||
166 | { | ||
167 | register struct tty_struct *TtyP; | ||
168 | int retval; | ||
169 | register struct phb_param *phb_param_ptr; | ||
170 | PKT *PacketP; | ||
171 | int res; | ||
172 | uchar Cor1=0, Cor2=0, Cor4=0, Cor5=0; | ||
173 | uchar TxXon=0, TxXoff=0, RxXon=0, RxXoff=0; | ||
174 | uchar LNext=0, TxBaud=0, RxBaud=0; | ||
175 | int retries = 0xff; | ||
176 | unsigned long flags; | ||
177 | |||
178 | func_enter (); | ||
179 | |||
180 | TtyP = PortP->gs.tty; | ||
181 | |||
182 | rio_dprintk (RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", | ||
183 | PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP); | ||
184 | |||
185 | if (!TtyP) { | ||
186 | rio_dprintk (RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n"); | ||
187 | |||
188 | func_exit (); | ||
189 | |||
190 | return RIO_FAIL; | ||
191 | } | ||
192 | rio_spin_lock_irqsave(&PortP->portSem, flags ); | ||
193 | |||
194 | if (cmd == OPEN) { | ||
195 | /* | ||
196 | ** If the port is set to store or lock the parameters, and it is | ||
197 | ** paramed with OPEN, we want to restore the saved port termio, but | ||
198 | ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot. | ||
199 | */ | ||
200 | #if 0 | ||
201 | if (PortP->FirstOpen) { | ||
202 | PortP->StoredTty.iflag = TtyP->tm.c_iflag; | ||
203 | PortP->StoredTty.oflag = TtyP->tm.c_oflag; | ||
204 | PortP->StoredTty.cflag = TtyP->tm.c_cflag; | ||
205 | PortP->StoredTty.lflag = TtyP->tm.c_lflag; | ||
206 | PortP->StoredTty.line = TtyP->tm.c_line; | ||
207 | for (i = 0; i < NCC + 5; i++) | ||
208 | PortP->StoredTty.cc[i] = TtyP->tm.c_cc[i]; | ||
209 | PortP->FirstOpen = 0; | ||
210 | } | ||
211 | else if (PortP->Store || PortP->Lock) { | ||
212 | rio_dprintk (RIO_DEBUG_PARAM, "OPEN: Restoring stored/locked params\n"); | ||
213 | TtyP->tm.c_iflag = PortP->StoredTty.iflag; | ||
214 | TtyP->tm.c_oflag = PortP->StoredTty.oflag; | ||
215 | TtyP->tm.c_cflag = PortP->StoredTty.cflag; | ||
216 | TtyP->tm.c_lflag = PortP->StoredTty.lflag; | ||
217 | TtyP->tm.c_line = PortP->StoredTty.line; | ||
218 | for (i = 0; i < NCC + 5; i++) | ||
219 | TtyP->tm.c_cc[i] = PortP->StoredTty.cc[i]; | ||
220 | } | ||
221 | #endif | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | ** wait for space | ||
226 | */ | ||
227 | while ( !(res=can_add_transmit(&PacketP,PortP)) || | ||
228 | (PortP->InUse != NOT_INUSE) ) { | ||
229 | if (retries -- <= 0) { | ||
230 | break; | ||
231 | } | ||
232 | if ( PortP->InUse != NOT_INUSE ) { | ||
233 | rio_dprintk (RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n"); | ||
234 | } | ||
235 | |||
236 | if ( !res ) { | ||
237 | rio_dprintk (RIO_DEBUG_PARAM, "Port has no space on transmit queue\n"); | ||
238 | } | ||
239 | |||
240 | if ( SleepFlag != OK_TO_SLEEP ) { | ||
241 | rio_spin_unlock_irqrestore( &PortP->portSem, flags); | ||
242 | func_exit(); | ||
243 | |||
244 | return RIO_FAIL; | ||
245 | } | ||
246 | |||
247 | rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit\n"); | ||
248 | rio_spin_unlock_irqrestore( &PortP->portSem, flags); | ||
249 | retval = RIODelay(PortP, HUNDRED_MS); | ||
250 | rio_spin_lock_irqsave( &PortP->portSem, flags); | ||
251 | if (retval == RIO_FAIL) { | ||
252 | rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n"); | ||
253 | rio_spin_unlock_irqrestore( &PortP->portSem, flags); | ||
254 | pseterr(EINTR); | ||
255 | func_exit(); | ||
256 | |||
257 | return RIO_FAIL; | ||
258 | } | ||
259 | if ( PortP->State & RIO_DELETED ) { | ||
260 | rio_spin_unlock_irqrestore( &PortP->portSem, flags); | ||
261 | func_exit (); | ||
262 | |||
263 | return RIO_SUCCESS; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | if (!res) { | ||
268 | rio_spin_unlock_irqrestore( &PortP->portSem, flags); | ||
269 | func_exit (); | ||
270 | |||
271 | return RIO_FAIL; | ||
272 | } | ||
273 | |||
274 | rio_dprintk (RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n",res); | ||
275 | rio_dprintk (RIO_DEBUG_PARAM, "Packet is 0x%x\n",(int) PacketP); | ||
276 | |||
277 | phb_param_ptr = (struct phb_param *)PacketP->data; | ||
278 | |||
279 | |||
280 | #if 0 | ||
281 | /* | ||
282 | ** COR 1 | ||
283 | */ | ||
284 | if ( TtyP->tm.c_iflag & INPCK ) { | ||
285 | rio_dprintk (RIO_DEBUG_PARAM, "Parity checking on input enabled\n"); | ||
286 | Cor1 |= COR1_INPCK; | ||
287 | } | ||
288 | #endif | ||
289 | |||
290 | switch ( TtyP->termios->c_cflag & CSIZE ) { | ||
291 | case CS5: | ||
292 | { | ||
293 | rio_dprintk (RIO_DEBUG_PARAM, "5 bit data\n"); | ||
294 | Cor1 |= COR1_5BITS; | ||
295 | break; | ||
296 | } | ||
297 | case CS6: | ||
298 | { | ||
299 | rio_dprintk (RIO_DEBUG_PARAM, "6 bit data\n"); | ||
300 | Cor1 |= COR1_6BITS; | ||
301 | break; | ||
302 | } | ||
303 | case CS7: | ||
304 | { | ||
305 | rio_dprintk (RIO_DEBUG_PARAM, "7 bit data\n"); | ||
306 | Cor1 |= COR1_7BITS; | ||
307 | break; | ||
308 | } | ||
309 | case CS8: | ||
310 | { | ||
311 | rio_dprintk (RIO_DEBUG_PARAM, "8 bit data\n"); | ||
312 | Cor1 |= COR1_8BITS; | ||
313 | break; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | if ( TtyP->termios->c_cflag & CSTOPB ) { | ||
318 | rio_dprintk (RIO_DEBUG_PARAM, "2 stop bits\n"); | ||
319 | Cor1 |= COR1_2STOP; | ||
320 | } | ||
321 | else { | ||
322 | rio_dprintk (RIO_DEBUG_PARAM, "1 stop bit\n"); | ||
323 | Cor1 |= COR1_1STOP; | ||
324 | } | ||
325 | |||
326 | if ( TtyP->termios->c_cflag & PARENB ) { | ||
327 | rio_dprintk (RIO_DEBUG_PARAM, "Enable parity\n"); | ||
328 | Cor1 |= COR1_NORMAL; | ||
329 | } | ||
330 | else { | ||
331 | rio_dprintk (RIO_DEBUG_PARAM, "Disable parity\n"); | ||
332 | Cor1 |= COR1_NOP; | ||
333 | } | ||
334 | if ( TtyP->termios->c_cflag & PARODD ) { | ||
335 | rio_dprintk (RIO_DEBUG_PARAM, "Odd parity\n"); | ||
336 | Cor1 |= COR1_ODD; | ||
337 | } | ||
338 | else { | ||
339 | rio_dprintk (RIO_DEBUG_PARAM, "Even parity\n"); | ||
340 | Cor1 |= COR1_EVEN; | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | ** COR 2 | ||
345 | */ | ||
346 | if ( TtyP->termios->c_iflag & IXON ) { | ||
347 | rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop output control\n"); | ||
348 | Cor2 |= COR2_IXON; | ||
349 | } | ||
350 | else { | ||
351 | if ( PortP->Config & RIO_IXON ) { | ||
352 | rio_dprintk (RIO_DEBUG_PARAM, "Force enable start/stop output control\n"); | ||
353 | Cor2 |= COR2_IXON; | ||
354 | } | ||
355 | else | ||
356 | rio_dprintk (RIO_DEBUG_PARAM, "IXON has been disabled.\n"); | ||
357 | } | ||
358 | |||
359 | if (TtyP->termios->c_iflag & IXANY) { | ||
360 | if ( PortP->Config & RIO_IXANY ) { | ||
361 | rio_dprintk (RIO_DEBUG_PARAM, "Enable any key to restart output\n"); | ||
362 | Cor2 |= COR2_IXANY; | ||
363 | } | ||
364 | else | ||
365 | rio_dprintk (RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n"); | ||
366 | } | ||
367 | |||
368 | if ( TtyP->termios->c_iflag & IXOFF ) { | ||
369 | rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop input control 2\n"); | ||
370 | Cor2 |= COR2_IXOFF; | ||
371 | } | ||
372 | |||
373 | if ( TtyP->termios->c_cflag & HUPCL ) { | ||
374 | rio_dprintk (RIO_DEBUG_PARAM, "Hangup on last close\n"); | ||
375 | Cor2 |= COR2_HUPCL; | ||
376 | } | ||
377 | |||
378 | if ( C_CRTSCTS (TtyP)) { | ||
379 | rio_dprintk (RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n"); | ||
380 | Cor2 |= COR2_CTSFLOW; | ||
381 | Cor2 |= COR2_RTSFLOW; | ||
382 | } else { | ||
383 | rio_dprintk (RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n"); | ||
384 | Cor2 &= ~COR2_CTSFLOW; | ||
385 | Cor2 &= ~COR2_RTSFLOW; | ||
386 | } | ||
387 | |||
388 | |||
389 | if ( TtyP->termios->c_cflag & CLOCAL ) { | ||
390 | rio_dprintk (RIO_DEBUG_PARAM, "Local line\n"); | ||
391 | } | ||
392 | else { | ||
393 | rio_dprintk (RIO_DEBUG_PARAM, "Possible Modem line\n"); | ||
394 | } | ||
395 | |||
396 | /* | ||
397 | ** COR 4 (there is no COR 3) | ||
398 | */ | ||
399 | if ( TtyP->termios->c_iflag & IGNBRK ) { | ||
400 | rio_dprintk (RIO_DEBUG_PARAM, "Ignore break condition\n"); | ||
401 | Cor4 |= COR4_IGNBRK; | ||
402 | } | ||
403 | if ( !(TtyP->termios->c_iflag & BRKINT) ) { | ||
404 | rio_dprintk (RIO_DEBUG_PARAM, "Break generates NULL condition\n"); | ||
405 | Cor4 |= COR4_NBRKINT; | ||
406 | } else { | ||
407 | rio_dprintk (RIO_DEBUG_PARAM, "Interrupt on break condition\n"); | ||
408 | } | ||
409 | |||
410 | if ( TtyP->termios->c_iflag & INLCR ) { | ||
411 | rio_dprintk (RIO_DEBUG_PARAM, "Map newline to carriage return on input\n"); | ||
412 | Cor4 |= COR4_INLCR; | ||
413 | } | ||
414 | |||
415 | if ( TtyP->termios->c_iflag & IGNCR ) { | ||
416 | rio_dprintk (RIO_DEBUG_PARAM, "Ignore carriage return on input\n"); | ||
417 | Cor4 |= COR4_IGNCR; | ||
418 | } | ||
419 | |||
420 | if ( TtyP->termios->c_iflag & ICRNL ) { | ||
421 | rio_dprintk (RIO_DEBUG_PARAM, "Map carriage return to newline on input\n"); | ||
422 | Cor4 |= COR4_ICRNL; | ||
423 | } | ||
424 | if ( TtyP->termios->c_iflag & IGNPAR ) { | ||
425 | rio_dprintk (RIO_DEBUG_PARAM, "Ignore characters with parity errors\n"); | ||
426 | Cor4 |= COR4_IGNPAR; | ||
427 | } | ||
428 | if ( TtyP->termios->c_iflag & PARMRK ) { | ||
429 | rio_dprintk (RIO_DEBUG_PARAM, "Mark parity errors\n"); | ||
430 | Cor4 |= COR4_PARMRK; | ||
431 | } | ||
432 | |||
433 | /* | ||
434 | ** Set the RAISEMOD flag to ensure that the modem lines are raised | ||
435 | ** on reception of a config packet. | ||
436 | ** The download code handles the zero baud condition. | ||
437 | */ | ||
438 | Cor4 |= COR4_RAISEMOD; | ||
439 | |||
440 | /* | ||
441 | ** COR 5 | ||
442 | */ | ||
443 | |||
444 | Cor5 = COR5_CMOE; | ||
445 | |||
446 | /* | ||
447 | ** Set to monitor tbusy/tstop (or not). | ||
448 | */ | ||
449 | |||
450 | if (PortP->MonitorTstate) | ||
451 | Cor5 |= COR5_TSTATE_ON; | ||
452 | else | ||
453 | Cor5 |= COR5_TSTATE_OFF; | ||
454 | |||
455 | /* | ||
456 | ** Could set LNE here if you wanted LNext processing. SVR4 will use it. | ||
457 | */ | ||
458 | if ( TtyP->termios->c_iflag & ISTRIP ) { | ||
459 | rio_dprintk (RIO_DEBUG_PARAM, "Strip input characters\n"); | ||
460 | if (! (PortP->State & RIO_TRIAD_MODE)) { | ||
461 | Cor5 |= COR5_ISTRIP; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | if ( TtyP->termios->c_oflag & ONLCR ) { | ||
466 | rio_dprintk (RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n"); | ||
467 | if ( PortP->CookMode == COOK_MEDIUM ) | ||
468 | Cor5 |= COR5_ONLCR; | ||
469 | } | ||
470 | if ( TtyP->termios->c_oflag & OCRNL ) { | ||
471 | rio_dprintk (RIO_DEBUG_PARAM, "Map carriage return to newline on output\n"); | ||
472 | if ( PortP->CookMode == COOK_MEDIUM ) | ||
473 | Cor5 |= COR5_OCRNL; | ||
474 | } | ||
475 | if ( ( TtyP->termios->c_oflag & TABDLY) == TAB3 ) { | ||
476 | rio_dprintk (RIO_DEBUG_PARAM, "Tab delay 3 set\n"); | ||
477 | if ( PortP->CookMode == COOK_MEDIUM ) | ||
478 | Cor5 |= COR5_TAB3; | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | ** Flow control bytes. | ||
483 | */ | ||
484 | TxXon = TtyP->termios->c_cc[VSTART]; | ||
485 | TxXoff = TtyP->termios->c_cc[VSTOP]; | ||
486 | RxXon = TtyP->termios->c_cc[VSTART]; | ||
487 | RxXoff = TtyP->termios->c_cc[VSTOP]; | ||
488 | /* | ||
489 | ** LNEXT byte | ||
490 | */ | ||
491 | LNext = 0; | ||
492 | |||
493 | /* | ||
494 | ** Baud rate bytes | ||
495 | */ | ||
496 | rio_dprintk (RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", | ||
497 | TtyP->termios->c_cflag, CBAUD); | ||
498 | |||
499 | switch (TtyP->termios->c_cflag & CBAUD) { | ||
500 | #define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break | ||
501 | e(50);e(75);e(110);e(134);e(150);e(200);e(300);e(600);e(1200); | ||
502 | e(1800);e(2400);e(4800);e(9600);e(19200);e(38400);e(57600); | ||
503 | e(115200); /* e(230400);e(460800); e(921600); */ | ||
504 | } | ||
505 | |||
506 | /* XXX MIssing conversion table. XXX */ | ||
507 | /* (TtyP->termios->c_cflag & V_CBAUD); */ | ||
508 | |||
509 | rio_dprintk (RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud); | ||
510 | |||
511 | |||
512 | /* | ||
513 | ** Leftovers | ||
514 | */ | ||
515 | if ( TtyP->termios->c_cflag & CREAD ) | ||
516 | rio_dprintk (RIO_DEBUG_PARAM, "Enable receiver\n"); | ||
517 | #ifdef RCV1EN | ||
518 | if ( TtyP->termios->c_cflag & RCV1EN ) | ||
519 | rio_dprintk (RIO_DEBUG_PARAM, "RCV1EN (?)\n"); | ||
520 | #endif | ||
521 | #ifdef XMT1EN | ||
522 | if ( TtyP->termios->c_cflag & XMT1EN ) | ||
523 | rio_dprintk (RIO_DEBUG_PARAM, "XMT1EN (?)\n"); | ||
524 | #endif | ||
525 | #if 0 | ||
526 | if ( TtyP->termios->c_cflag & LOBLK ) | ||
527 | rio_dprintk (RIO_DEBUG_PARAM, "LOBLK - JCL output blocks when not current\n"); | ||
528 | #endif | ||
529 | if ( TtyP->termios->c_lflag & ISIG ) | ||
530 | rio_dprintk (RIO_DEBUG_PARAM, "Input character signal generating enabled\n"); | ||
531 | if ( TtyP->termios->c_lflag & ICANON ) | ||
532 | rio_dprintk (RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n"); | ||
533 | if ( TtyP->termios->c_lflag & XCASE ) | ||
534 | rio_dprintk (RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n"); | ||
535 | if ( TtyP->termios->c_lflag & ECHO ) | ||
536 | rio_dprintk (RIO_DEBUG_PARAM, "Enable input echo\n"); | ||
537 | if ( TtyP->termios->c_lflag & ECHOE ) | ||
538 | rio_dprintk (RIO_DEBUG_PARAM, "Enable echo erase\n"); | ||
539 | if ( TtyP->termios->c_lflag & ECHOK ) | ||
540 | rio_dprintk (RIO_DEBUG_PARAM, "Enable echo kill\n"); | ||
541 | if ( TtyP->termios->c_lflag & ECHONL ) | ||
542 | rio_dprintk (RIO_DEBUG_PARAM, "Enable echo newline\n"); | ||
543 | if ( TtyP->termios->c_lflag & NOFLSH ) | ||
544 | rio_dprintk (RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n"); | ||
545 | #ifdef TOSTOP | ||
546 | if ( TtyP->termios->c_lflag & TOSTOP ) | ||
547 | rio_dprintk (RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n"); | ||
548 | #endif | ||
549 | #ifdef XCLUDE | ||
550 | if ( TtyP->termios->c_lflag & XCLUDE ) | ||
551 | rio_dprintk (RIO_DEBUG_PARAM, "Exclusive use of this line\n"); | ||
552 | #endif | ||
553 | if ( TtyP->termios->c_iflag & IUCLC ) | ||
554 | rio_dprintk (RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n"); | ||
555 | if ( TtyP->termios->c_oflag & OPOST ) | ||
556 | rio_dprintk (RIO_DEBUG_PARAM, "Enable output post-processing\n"); | ||
557 | if ( TtyP->termios->c_oflag & OLCUC ) | ||
558 | rio_dprintk (RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n"); | ||
559 | if ( TtyP->termios->c_oflag & ONOCR ) | ||
560 | rio_dprintk (RIO_DEBUG_PARAM, "No carriage return output at column 0\n"); | ||
561 | if ( TtyP->termios->c_oflag & ONLRET ) | ||
562 | rio_dprintk (RIO_DEBUG_PARAM, "Newline performs carriage return function\n"); | ||
563 | if ( TtyP->termios->c_oflag & OFILL ) | ||
564 | rio_dprintk (RIO_DEBUG_PARAM, "Use fill characters for delay\n"); | ||
565 | if ( TtyP->termios->c_oflag & OFDEL ) | ||
566 | rio_dprintk (RIO_DEBUG_PARAM, "Fill character is DEL\n"); | ||
567 | if ( TtyP->termios->c_oflag & NLDLY ) | ||
568 | rio_dprintk (RIO_DEBUG_PARAM, "Newline delay set\n"); | ||
569 | if ( TtyP->termios->c_oflag & CRDLY ) | ||
570 | rio_dprintk (RIO_DEBUG_PARAM, "Carriage return delay set\n"); | ||
571 | if ( TtyP->termios->c_oflag & TABDLY ) | ||
572 | rio_dprintk (RIO_DEBUG_PARAM, "Tab delay set\n"); | ||
573 | #if 0 | ||
574 | if ( TtyP->termios->c_oflag & BSDLY ) | ||
575 | rio_dprintk (RIO_DEBUG_PARAM, "Back-space delay set\n"); | ||
576 | if ( TtyP->termios->c_oflag & VTDLY ) | ||
577 | rio_dprintk (RIO_DEBUG_PARAM, "Vertical tab delay set\n"); | ||
578 | if ( TtyP->termios->c_oflag & FFDLY ) | ||
579 | rio_dprintk (RIO_DEBUG_PARAM, "Form-feed delay set\n"); | ||
580 | #endif | ||
581 | /* | ||
582 | ** These things are kind of useful in a later life! | ||
583 | */ | ||
584 | PortP->Cor2Copy = Cor2; | ||
585 | |||
586 | if ( PortP->State & RIO_DELETED ) { | ||
587 | rio_spin_unlock_irqrestore( &PortP->portSem, flags); | ||
588 | func_exit (); | ||
589 | |||
590 | return RIO_FAIL; | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | ** Actually write the info into the packet to be sent | ||
595 | */ | ||
596 | WBYTE(phb_param_ptr->Cmd, cmd); | ||
597 | WBYTE(phb_param_ptr->Cor1, Cor1); | ||
598 | WBYTE(phb_param_ptr->Cor2, Cor2); | ||
599 | WBYTE(phb_param_ptr->Cor4, Cor4); | ||
600 | WBYTE(phb_param_ptr->Cor5, Cor5); | ||
601 | WBYTE(phb_param_ptr->TxXon, TxXon); | ||
602 | WBYTE(phb_param_ptr->RxXon, RxXon); | ||
603 | WBYTE(phb_param_ptr->TxXoff, TxXoff); | ||
604 | WBYTE(phb_param_ptr->RxXoff, RxXoff); | ||
605 | WBYTE(phb_param_ptr->LNext, LNext); | ||
606 | WBYTE(phb_param_ptr->TxBaud, TxBaud); | ||
607 | WBYTE(phb_param_ptr->RxBaud, RxBaud); | ||
608 | |||
609 | /* | ||
610 | ** Set the length/command field | ||
611 | */ | ||
612 | WBYTE(PacketP->len , 12 | PKT_CMD_BIT); | ||
613 | |||
614 | /* | ||
615 | ** The packet is formed - now, whack it off | ||
616 | ** to its final destination: | ||
617 | */ | ||
618 | add_transmit(PortP); | ||
619 | /* | ||
620 | ** Count characters transmitted for port statistics reporting | ||
621 | */ | ||
622 | if (PortP->statsGather) | ||
623 | PortP->txchars += 12; | ||
624 | |||
625 | rio_spin_unlock_irqrestore( &PortP->portSem, flags); | ||
626 | |||
627 | rio_dprintk (RIO_DEBUG_PARAM, "add_transmit returned.\n"); | ||
628 | /* | ||
629 | ** job done. | ||
630 | */ | ||
631 | func_exit (); | ||
632 | |||
633 | return RIO_SUCCESS; | ||
634 | } | ||
635 | |||
636 | |||
637 | /* | ||
638 | ** We can add another packet to a transmit queue if the packet pointer pointed | ||
639 | ** to by the TxAdd pointer has PKT_IN_USE clear in its address. | ||
640 | */ | ||
641 | int | ||
642 | can_add_transmit(PktP, PortP) | ||
643 | PKT **PktP; | ||
644 | struct Port *PortP; | ||
645 | { | ||
646 | register PKT *tp; | ||
647 | |||
648 | *PktP = tp = (PKT *)RIO_PTR(PortP->Caddr,RWORD(*PortP->TxAdd)); | ||
649 | |||
650 | return !((uint)tp & PKT_IN_USE); | ||
651 | } | ||
652 | |||
653 | /* | ||
654 | ** To add a packet to the queue, you set the PKT_IN_USE bit in the address, | ||
655 | ** and then move the TxAdd pointer along one position to point to the next | ||
656 | ** packet pointer. You must wrap the pointer from the end back to the start. | ||
657 | */ | ||
658 | void | ||
659 | add_transmit(PortP) | ||
660 | struct Port *PortP; | ||
661 | { | ||
662 | if (RWORD(*PortP->TxAdd) & PKT_IN_USE) { | ||
663 | rio_dprintk (RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!"); | ||
664 | } | ||
665 | WWORD( *(ushort *)PortP->TxAdd, RWORD(*PortP->TxAdd) | PKT_IN_USE); | ||
666 | PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : | ||
667 | PortP->TxAdd + 1; | ||
668 | WWORD( PortP->PhbP->tx_add , RIO_OFF(PortP->Caddr,PortP->TxAdd) ); | ||
669 | } | ||
670 | |||
671 | /**************************************** | ||
672 | * Put a packet onto the end of the | ||
673 | * free list | ||
674 | ****************************************/ | ||
675 | void | ||
676 | put_free_end(HostP, PktP) | ||
677 | struct Host *HostP; | ||
678 | PKT *PktP; | ||
679 | { | ||
680 | FREE_LIST *tmp_pointer; | ||
681 | ushort old_end, new_end; | ||
682 | unsigned long flags; | ||
683 | |||
684 | rio_spin_lock_irqsave(&HostP->HostLock, flags); | ||
685 | |||
686 | /************************************************* | ||
687 | * Put a packet back onto the back of the free list | ||
688 | * | ||
689 | ************************************************/ | ||
690 | |||
691 | rio_dprintk (RIO_DEBUG_PFE, "put_free_end(PktP=%x)\n",(int)PktP); | ||
692 | |||
693 | if ((old_end=RWORD(HostP->ParmMapP->free_list_end)) != TPNULL) { | ||
694 | new_end = RIO_OFF(HostP->Caddr,PktP); | ||
695 | tmp_pointer = (FREE_LIST *)RIO_PTR(HostP->Caddr,old_end); | ||
696 | WWORD(tmp_pointer->next , new_end ); | ||
697 | WWORD(((FREE_LIST *)PktP)->prev , old_end); | ||
698 | WWORD(((FREE_LIST *)PktP)->next , TPNULL); | ||
699 | WWORD(HostP->ParmMapP->free_list_end, new_end); | ||
700 | } | ||
701 | else { /* First packet on the free list this should never happen! */ | ||
702 | rio_dprintk (RIO_DEBUG_PFE, "put_free_end(): This should never happen\n"); | ||
703 | WWORD(HostP->ParmMapP->free_list_end , RIO_OFF(HostP->Caddr,PktP)); | ||
704 | tmp_pointer = (FREE_LIST *)PktP; | ||
705 | WWORD(tmp_pointer->prev , TPNULL); | ||
706 | WWORD(tmp_pointer->next , TPNULL); | ||
707 | } | ||
708 | rio_dprintk (RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock); | ||
709 | rio_spin_unlock_irqrestore(&HostP->HostLock, flags); | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | ** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set | ||
714 | ** for the next packet on the queue. It will also set PktP to point to the | ||
715 | ** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear, | ||
716 | ** then can_remove_receive() returns 0. | ||
717 | */ | ||
718 | int | ||
719 | can_remove_receive(PktP, PortP) | ||
720 | PKT **PktP; | ||
721 | struct Port *PortP; | ||
722 | { | ||
723 | if ( RWORD(*PortP->RxRemove) & PKT_IN_USE) { | ||
724 | *PktP = (PKT *)RIO_PTR(PortP->Caddr, | ||
725 | RWORD(*PortP->RxRemove) & ~PKT_IN_USE); | ||
726 | return 1; | ||
727 | } | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | /* | ||
732 | ** To remove a packet from the receive queue you clear its PKT_IN_USE bit, | ||
733 | ** and then bump the pointers. Once the pointers get to the end, they must | ||
734 | ** be wrapped back to the start. | ||
735 | */ | ||
736 | void | ||
737 | remove_receive(PortP) | ||
738 | struct Port *PortP; | ||
739 | { | ||
740 | WWORD( *PortP->RxRemove, RWORD(*PortP->RxRemove) & ~PKT_IN_USE ); | ||
741 | PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : | ||
742 | PortP->RxRemove + 1; | ||
743 | WWORD( PortP->PhbP->rx_remove , RIO_OFF(PortP->Caddr, PortP->RxRemove) ); | ||
744 | } | ||
diff --git a/drivers/char/rio/riopcicopy.c b/drivers/char/rio/riopcicopy.c new file mode 100644 index 000000000000..2ea99a60aa32 --- /dev/null +++ b/drivers/char/rio/riopcicopy.c | |||
@@ -0,0 +1,8 @@ | |||
1 | |||
2 | /* Yeah. We have copyright on this one. Sure. */ | ||
3 | |||
4 | void rio_pcicopy( char *from, char *to, int amount) | ||
5 | { | ||
6 | while ( amount-- ) | ||
7 | *to++ = *from++; | ||
8 | } | ||
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c new file mode 100644 index 000000000000..106b31f48a21 --- /dev/null +++ b/drivers/char/rio/rioroute.c | |||
@@ -0,0 +1,1238 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : rioroute.c | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 10:33:46 | ||
26 | ** Retrieved : 11/6/98 10:33:50 | ||
27 | ** | ||
28 | ** ident @(#)rioroute.c 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | #ifdef SCCS_LABELS | ||
33 | static char *_rioroute_c_sccs_ = "@(#)rioroute.c 1.3"; | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/errno.h> | ||
39 | #include <asm/io.h> | ||
40 | #include <asm/system.h> | ||
41 | #include <asm/string.h> | ||
42 | #include <asm/semaphore.h> | ||
43 | #include <asm/uaccess.h> | ||
44 | |||
45 | #include <linux/termios.h> | ||
46 | #include <linux/serial.h> | ||
47 | |||
48 | #include <linux/generic_serial.h> | ||
49 | |||
50 | |||
51 | #include "linux_compat.h" | ||
52 | #include "rio_linux.h" | ||
53 | #include "typdef.h" | ||
54 | #include "pkt.h" | ||
55 | #include "daemon.h" | ||
56 | #include "rio.h" | ||
57 | #include "riospace.h" | ||
58 | #include "top.h" | ||
59 | #include "cmdpkt.h" | ||
60 | #include "map.h" | ||
61 | #include "riotypes.h" | ||
62 | #include "rup.h" | ||
63 | #include "port.h" | ||
64 | #include "riodrvr.h" | ||
65 | #include "rioinfo.h" | ||
66 | #include "func.h" | ||
67 | #include "errors.h" | ||
68 | #include "pci.h" | ||
69 | |||
70 | #include "parmmap.h" | ||
71 | #include "unixrup.h" | ||
72 | #include "board.h" | ||
73 | #include "host.h" | ||
74 | #include "error.h" | ||
75 | #include "phb.h" | ||
76 | #include "link.h" | ||
77 | #include "cmdblk.h" | ||
78 | #include "route.h" | ||
79 | #include "control.h" | ||
80 | #include "cirrus.h" | ||
81 | #include "rioioctl.h" | ||
82 | #include "param.h" | ||
83 | #include "list.h" | ||
84 | #include "sam.h" | ||
85 | |||
86 | static int RIOCheckIsolated(struct rio_info *, struct Host *, uint); | ||
87 | static int RIOIsolate(struct rio_info *, struct Host *, uint); | ||
88 | static int RIOCheck(struct Host *, uint); | ||
89 | static void RIOConCon(struct rio_info *, struct Host *, uint, uint, uint, uint, int); | ||
90 | |||
91 | |||
92 | /* | ||
93 | ** Incoming on the ROUTE_RUP | ||
94 | ** I wrote this while I was tired. Forgive me. | ||
95 | */ | ||
96 | int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP ) | ||
97 | { | ||
98 | struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data; | ||
99 | struct PktCmd_M *PktReplyP; | ||
100 | struct CmdBlk *CmdBlkP; | ||
101 | struct Port *PortP; | ||
102 | struct Map *MapP; | ||
103 | struct Top *TopP; | ||
104 | int ThisLink, ThisLinkMin, ThisLinkMax; | ||
105 | int port; | ||
106 | int Mod, Mod1, Mod2; | ||
107 | ushort RtaType; | ||
108 | uint RtaUniq; | ||
109 | uint ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */ | ||
110 | uint OldUnit, NewUnit, OldLink, NewLink; | ||
111 | char *MyType, *MyName; | ||
112 | int Lies; | ||
113 | unsigned long flags; | ||
114 | |||
115 | #ifdef STACK | ||
116 | RIOStackCheck("RIORouteRup"); | ||
117 | #endif | ||
118 | #ifdef CHECK | ||
119 | CheckPacketP(PacketP); | ||
120 | CheckHostP(HostP); | ||
121 | CheckRup(Rup); | ||
122 | CheckHost(Host); | ||
123 | #endif | ||
124 | /* | ||
125 | ** Is this unit telling us it's current link topology? | ||
126 | */ | ||
127 | if ( RBYTE(PktCmdP->Command) == ROUTE_TOPOLOGY ) | ||
128 | { | ||
129 | MapP = HostP->Mapping; | ||
130 | |||
131 | /* | ||
132 | ** The packet can be sent either by the host or by an RTA. | ||
133 | ** If it comes from the host, then we need to fill in the | ||
134 | ** Topology array in the host structure. If it came in | ||
135 | ** from an RTA then we need to fill in the Mapping structure's | ||
136 | ** Topology array for the unit. | ||
137 | */ | ||
138 | if ( Rup >= (ushort)MAX_RUP ) | ||
139 | { | ||
140 | ThisUnit = HOST_ID; | ||
141 | TopP = HostP->Topology; | ||
142 | MyType = "Host"; | ||
143 | MyName = HostP->Name; | ||
144 | ThisLinkMin = ThisLinkMax = Rup - MAX_RUP; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | ThisUnit = Rup+1; | ||
149 | TopP = HostP->Mapping[Rup].Topology; | ||
150 | MyType = "RTA"; | ||
151 | MyName = HostP->Mapping[Rup].Name; | ||
152 | ThisLinkMin = 0; | ||
153 | ThisLinkMax = LINKS_PER_UNIT - 1; | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | ** Lies will not be tolerated. | ||
158 | ** If any pair of links claim to be connected to the same | ||
159 | ** place, then ignore this packet completely. | ||
160 | */ | ||
161 | Lies = 0; | ||
162 | for ( ThisLink=ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) | ||
163 | { | ||
164 | /* | ||
165 | ** it won't lie about network interconnect, total disconnects | ||
166 | ** and no-IDs. (or at least, it doesn't *matter* if it does) | ||
167 | */ | ||
168 | if ( RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) > (ushort)MAX_RUP ) | ||
169 | continue; | ||
170 | |||
171 | for ( NewLink=ThisLinkMin; NewLink < ThisLink; NewLink++ ) | ||
172 | { | ||
173 | if ( (RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) == | ||
174 | RBYTE(PktCmdP->RouteTopology[NewLink].Unit)) && | ||
175 | (RBYTE(PktCmdP->RouteTopology[ThisLink].Link) == | ||
176 | RBYTE(PktCmdP->RouteTopology[NewLink].Link)) ) | ||
177 | { | ||
178 | Lies++; | ||
179 | } | ||
180 | } | ||
181 | } | ||
182 | |||
183 | if ( Lies ) | ||
184 | { | ||
185 | rio_dprintk (RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n",Lies); | ||
186 | rio_dprintk (RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n", | ||
187 | RBYTE(PktCmdP->RouteTopology[0].Unit), | ||
188 | 'A'+RBYTE(PktCmdP->RouteTopology[0].Link), | ||
189 | RBYTE(PktCmdP->RouteTopology[1].Unit), | ||
190 | 'A'+RBYTE(PktCmdP->RouteTopology[1].Link), | ||
191 | RBYTE(PktCmdP->RouteTopology[2].Unit), | ||
192 | 'A'+RBYTE(PktCmdP->RouteTopology[2].Link), | ||
193 | RBYTE(PktCmdP->RouteTopology[3].Unit), | ||
194 | 'A'+RBYTE(PktCmdP->RouteTopology[3].Link)); | ||
195 | return TRUE; | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | ** now, process each link. | ||
200 | */ | ||
201 | for ( ThisLink=ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) | ||
202 | { | ||
203 | /* | ||
204 | ** this is what it was connected to | ||
205 | */ | ||
206 | OldUnit = TopP[ThisLink].Unit; | ||
207 | OldLink = TopP[ThisLink].Link; | ||
208 | |||
209 | /* | ||
210 | ** this is what it is now connected to | ||
211 | */ | ||
212 | NewUnit = RBYTE(PktCmdP->RouteTopology[ThisLink].Unit); | ||
213 | NewLink = RBYTE(PktCmdP->RouteTopology[ThisLink].Link); | ||
214 | |||
215 | if ( OldUnit != NewUnit || OldLink != NewLink ) | ||
216 | { | ||
217 | /* | ||
218 | ** something has changed! | ||
219 | */ | ||
220 | |||
221 | if ( NewUnit > MAX_RUP && | ||
222 | NewUnit != ROUTE_DISCONNECT && | ||
223 | NewUnit != ROUTE_NO_ID && | ||
224 | NewUnit != ROUTE_INTERCONNECT ) | ||
225 | { | ||
226 | rio_dprintk (RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", | ||
227 | MyType, | ||
228 | MyName, | ||
229 | NewUnit, | ||
230 | NewLink); | ||
231 | } | ||
232 | else | ||
233 | { | ||
234 | /* | ||
235 | ** put the new values in | ||
236 | */ | ||
237 | TopP[ThisLink].Unit = NewUnit; | ||
238 | TopP[ThisLink].Link = NewLink; | ||
239 | |||
240 | RIOSetChange(p); | ||
241 | |||
242 | if ( OldUnit <= MAX_RUP ) | ||
243 | { | ||
244 | /* | ||
245 | ** If something has become bust, then re-enable them messages | ||
246 | */ | ||
247 | if (! p->RIONoMessage) | ||
248 | RIOConCon(p,HostP,ThisUnit,ThisLink,OldUnit,OldLink,DISCONNECT); | ||
249 | } | ||
250 | |||
251 | if ( ( NewUnit <= MAX_RUP ) && !p->RIONoMessage ) | ||
252 | RIOConCon(p,HostP,ThisUnit,ThisLink,NewUnit,NewLink,CONNECT); | ||
253 | |||
254 | if ( NewUnit == ROUTE_NO_ID ) | ||
255 | rio_dprintk (RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", | ||
256 | MyType,MyName,'A'+ThisLink); | ||
257 | |||
258 | if ( NewUnit == ROUTE_INTERCONNECT ) | ||
259 | { | ||
260 | if (! p->RIONoMessage) | ||
261 | cprintf("%s '%s' (%c) is connected to another network.\n", MyType,MyName,'A'+ThisLink); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | ** perform an update for 'the other end', so that these messages | ||
266 | ** only appears once. Only disconnect the other end if it is pointing | ||
267 | ** at us! | ||
268 | */ | ||
269 | if ( OldUnit == HOST_ID ) | ||
270 | { | ||
271 | if ( HostP->Topology[OldLink].Unit == ThisUnit && | ||
272 | HostP->Topology[OldLink].Link == ThisLink ) | ||
273 | { | ||
274 | rio_dprintk (RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink+'A'); | ||
275 | HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT; | ||
276 | HostP->Topology[OldLink].Link = NO_LINK; | ||
277 | } | ||
278 | else | ||
279 | { | ||
280 | rio_dprintk (RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", | ||
281 | OldLink+'A',HostP->Mapping[ThisUnit-1].Name,ThisLink+'A'); | ||
282 | } | ||
283 | } | ||
284 | else if ( OldUnit <= MAX_RUP ) | ||
285 | { | ||
286 | if ( HostP->Mapping[OldUnit-1].Topology[OldLink].Unit == ThisUnit && | ||
287 | HostP->Mapping[OldUnit-1].Topology[OldLink].Link == ThisLink ) | ||
288 | { | ||
289 | rio_dprintk (RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", | ||
290 | HostP->Mapping[OldUnit-1].Name,OldLink+'A'); | ||
291 | HostP->Mapping[OldUnit-1].Topology[OldLink].Unit=ROUTE_DISCONNECT; | ||
292 | HostP->Mapping[OldUnit-1].Topology[OldLink].Link=NO_LINK; | ||
293 | } | ||
294 | else | ||
295 | { | ||
296 | rio_dprintk (RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", | ||
297 | HostP->Mapping[OldUnit-1].Name,OldLink+'A', | ||
298 | HostP->Mapping[ThisUnit-1].Name,ThisLink+'A'); | ||
299 | } | ||
300 | } | ||
301 | if ( NewUnit == HOST_ID ) | ||
302 | { | ||
303 | rio_dprintk (RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", | ||
304 | NewLink+'A',MyName,ThisLink+'A'); | ||
305 | HostP->Topology[NewLink].Unit = ThisUnit; | ||
306 | HostP->Topology[NewLink].Link = ThisLink; | ||
307 | } | ||
308 | else if ( NewUnit <= MAX_RUP ) | ||
309 | { | ||
310 | rio_dprintk (RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", | ||
311 | HostP->Mapping[NewUnit-1].Name,NewLink+'A',MyName,ThisLink+'A'); | ||
312 | HostP->Mapping[NewUnit-1].Topology[NewLink].Unit=ThisUnit; | ||
313 | HostP->Mapping[NewUnit-1].Topology[NewLink].Link=ThisLink; | ||
314 | } | ||
315 | } | ||
316 | RIOSetChange(p); | ||
317 | RIOCheckIsolated(p, HostP, OldUnit ); | ||
318 | } | ||
319 | } | ||
320 | return TRUE; | ||
321 | } | ||
322 | |||
323 | /* | ||
324 | ** The only other command we recognise is a route_request command | ||
325 | */ | ||
326 | if ( RBYTE(PktCmdP->Command) != ROUTE_REQUEST ) | ||
327 | { | ||
328 | rio_dprintk (RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %d ROUTE_RUP\n", | ||
329 | RBYTE(PktCmdP->Command),Rup,(int)HostP); | ||
330 | return TRUE; | ||
331 | } | ||
332 | |||
333 | RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) + | ||
334 | (RBYTE(PktCmdP->UniqNum[1]) << 8) + | ||
335 | (RBYTE(PktCmdP->UniqNum[2]) << 16) + | ||
336 | (RBYTE(PktCmdP->UniqNum[3]) << 24); | ||
337 | |||
338 | /* | ||
339 | ** Determine if 8 or 16 port RTA | ||
340 | */ | ||
341 | RtaType = GetUnitType(RtaUniq); | ||
342 | |||
343 | rio_dprintk (RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq); | ||
344 | |||
345 | Mod = RBYTE(PktCmdP->ModuleTypes); | ||
346 | Mod1 = LONYBLE(Mod); | ||
347 | if (RtaType == TYPE_RTA16) | ||
348 | { | ||
349 | /* | ||
350 | ** Only one ident is set for a 16 port RTA. To make compatible | ||
351 | ** with 8 port, set 2nd ident in Mod2 to the same as Mod1. | ||
352 | */ | ||
353 | Mod2 = Mod1; | ||
354 | rio_dprintk (RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", | ||
355 | p->RIOModuleTypes[Mod1].Name); | ||
356 | } | ||
357 | else | ||
358 | { | ||
359 | Mod2 = HINYBLE(Mod); | ||
360 | rio_dprintk (RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", | ||
361 | p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name); | ||
362 | } | ||
363 | |||
364 | if ( RtaUniq == 0xffffffff ) | ||
365 | { | ||
366 | ShowPacket( DBG_SPECIAL, PacketP ); | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | ** try to unhook a command block from the command free list. | ||
371 | */ | ||
372 | if ( !(CmdBlkP = RIOGetCmdBlk()) ) | ||
373 | { | ||
374 | rio_dprintk (RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n"); | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | /* | ||
379 | ** Fill in the default info on the command block | ||
380 | */ | ||
381 | CmdBlkP->Packet.dest_unit = Rup; | ||
382 | CmdBlkP->Packet.dest_port = ROUTE_RUP; | ||
383 | CmdBlkP->Packet.src_unit = HOST_ID; | ||
384 | CmdBlkP->Packet.src_port = ROUTE_RUP; | ||
385 | CmdBlkP->Packet.len = PKT_CMD_BIT | 1; | ||
386 | CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL; | ||
387 | PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data; | ||
388 | |||
389 | if (! RIOBootOk(p, HostP, RtaUniq)) | ||
390 | { | ||
391 | rio_dprintk (RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", | ||
392 | RtaUniq); | ||
393 | PktReplyP->Command = ROUTE_FOAD; | ||
394 | HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7); | ||
395 | RIOQueueCmdBlk(HostP, Rup, CmdBlkP); | ||
396 | return TRUE; | ||
397 | } | ||
398 | |||
399 | /* | ||
400 | ** Check to see if the RTA is configured for this host | ||
401 | */ | ||
402 | for ( ThisUnit=0; ThisUnit<MAX_RUP; ThisUnit++ ) | ||
403 | { | ||
404 | rio_dprintk (RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n", | ||
405 | ThisUnit, | ||
406 | HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? | ||
407 | "Slot-In-Use":"Not In Use", | ||
408 | HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? | ||
409 | "Slot-Tentative":"Not Tentative", | ||
410 | HostP->Mapping[ThisUnit].RtaUniqueNum); | ||
411 | |||
412 | /* | ||
413 | ** We have an entry for it. | ||
414 | */ | ||
415 | if ( (HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && | ||
416 | (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq) ) | ||
417 | { | ||
418 | if (RtaType == TYPE_RTA16) | ||
419 | { | ||
420 | ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1; | ||
421 | rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", | ||
422 | RtaUniq,ThisUnit,ThisUnit2); | ||
423 | } | ||
424 | else | ||
425 | rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", | ||
426 | RtaUniq,ThisUnit); | ||
427 | /* | ||
428 | ** If we have no knowledge of booting it, then the host has | ||
429 | ** been re-booted, and so we must kill the RTA, so that it | ||
430 | ** will be booted again (potentially with new bins) | ||
431 | ** and it will then re-ask for an ID, which we will service. | ||
432 | */ | ||
433 | if ( (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && | ||
434 | !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED) ) | ||
435 | { | ||
436 | if ( !(HostP->Mapping[ThisUnit].Flags & MSG_DONE) ) | ||
437 | { | ||
438 | if ( !p->RIONoMessage ) | ||
439 | cprintf("RTA '%s' is being updated.\n",HostP->Mapping[ThisUnit].Name); | ||
440 | HostP->Mapping[ThisUnit].Flags |= MSG_DONE; | ||
441 | } | ||
442 | PktReplyP->Command = ROUTE_FOAD; | ||
443 | HostP->Copy("RT_FOAD",PktReplyP->CommandText,7); | ||
444 | RIOQueueCmdBlk(HostP, Rup, CmdBlkP); | ||
445 | return TRUE; | ||
446 | } | ||
447 | |||
448 | /* | ||
449 | ** Send the ID (entry) to this RTA. The ID number is implicit as | ||
450 | ** the offset into the table. It is worth noting at this stage | ||
451 | ** that offset zero in the table contains the entries for the | ||
452 | ** RTA with ID 1!!!! | ||
453 | */ | ||
454 | PktReplyP->Command = ROUTE_ALLOCATE; | ||
455 | PktReplyP->IDNum = ThisUnit+1; | ||
456 | if (RtaType == TYPE_RTA16) | ||
457 | { | ||
458 | if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) | ||
459 | /* | ||
460 | ** Adjust the phb and tx pkt dest_units for 2nd block of 8 | ||
461 | ** only if the RTA has ports associated (SLOT_IN_USE) | ||
462 | */ | ||
463 | RIOFixPhbs(p, HostP, ThisUnit2); | ||
464 | PktReplyP->IDNum2 = ThisUnit2+1; | ||
465 | rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", | ||
466 | HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2); | ||
467 | } | ||
468 | else | ||
469 | { | ||
470 | PktReplyP->IDNum2 = ROUTE_NO_ID; | ||
471 | rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", | ||
472 | HostP->Mapping[ThisUnit].Name,PktReplyP->IDNum); | ||
473 | } | ||
474 | HostP->Copy("RT_ALLOCAT",PktReplyP->CommandText,10); | ||
475 | |||
476 | RIOQueueCmdBlk( HostP, Rup, CmdBlkP); | ||
477 | |||
478 | /* | ||
479 | ** If this is a freshly booted RTA, then we need to re-open | ||
480 | ** the ports, if any where open, so that data may once more | ||
481 | ** flow around the system! | ||
482 | */ | ||
483 | if ( (HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && | ||
484 | (HostP->Mapping[ThisUnit].SysPort != NO_PORT) ) | ||
485 | { | ||
486 | /* | ||
487 | ** look at the ports associated with this beast and | ||
488 | ** see if any where open. If they was, then re-open | ||
489 | ** them, using the info from the tty flags. | ||
490 | */ | ||
491 | for ( port=0; port<PORTS_PER_RTA; port++ ) | ||
492 | { | ||
493 | PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]; | ||
494 | if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) | ||
495 | { | ||
496 | rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n"); | ||
497 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
498 | PortP->MagicFlags |= MAGIC_REBOOT; | ||
499 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
500 | } | ||
501 | } | ||
502 | if (RtaType == TYPE_RTA16) | ||
503 | { | ||
504 | for ( port=0; port<PORTS_PER_RTA; port++ ) | ||
505 | { | ||
506 | PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]; | ||
507 | if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) | ||
508 | { | ||
509 | rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n"); | ||
510 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
511 | PortP->MagicFlags |= MAGIC_REBOOT; | ||
512 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
513 | } | ||
514 | } | ||
515 | } | ||
516 | } | ||
517 | |||
518 | /* | ||
519 | ** keep a copy of the module types! | ||
520 | */ | ||
521 | HostP->UnixRups[ThisUnit].ModTypes = Mod; | ||
522 | if (RtaType == TYPE_RTA16) | ||
523 | HostP->UnixRups[ThisUnit2].ModTypes = Mod; | ||
524 | |||
525 | /* | ||
526 | ** If either of the modules on this unit is read-only or write-only | ||
527 | ** or none-xprint, then we need to transfer that info over to the | ||
528 | ** relevant ports. | ||
529 | */ | ||
530 | if ( HostP->Mapping[ThisUnit].SysPort != NO_PORT ) | ||
531 | { | ||
532 | for ( port=0; port<PORTS_PER_MODULE; port++ ) | ||
533 | { | ||
534 | p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK; | ||
535 | p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config |= | ||
536 | p->RIOModuleTypes[Mod1].Flags[port]; | ||
537 | p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK; | ||
538 | p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port]; | ||
539 | } | ||
540 | if (RtaType == TYPE_RTA16) | ||
541 | { | ||
542 | for ( port=0; port<PORTS_PER_MODULE; port++ ) | ||
543 | { | ||
544 | p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK; | ||
545 | p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port]; | ||
546 | p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK; | ||
547 | p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port]; | ||
548 | } | ||
549 | } | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | ** Job done, get on with the interrupts! | ||
554 | */ | ||
555 | return TRUE; | ||
556 | } | ||
557 | } | ||
558 | /* | ||
559 | ** There is no table entry for this RTA at all. | ||
560 | ** | ||
561 | ** Lets check to see if we actually booted this unit - if not, | ||
562 | ** then we reset it and it will go round the loop of being booted | ||
563 | ** we can then worry about trying to fit it into the table. | ||
564 | */ | ||
565 | for ( ThisUnit=0; ThisUnit<HostP->NumExtraBooted; ThisUnit++ ) | ||
566 | if ( HostP->ExtraUnits[ThisUnit] == RtaUniq ) | ||
567 | break; | ||
568 | if ( ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS ) | ||
569 | { | ||
570 | /* | ||
571 | ** if the unit wasn't in the table, and the table wasn't full, then | ||
572 | ** we reset the unit, because we didn't boot it. | ||
573 | ** However, if the table is full, it could be that we did boot | ||
574 | ** this unit, and so we won't reboot it, because it isn't really | ||
575 | ** all that disasterous to keep the old bins in most cases. This | ||
576 | ** is a rather tacky feature, but we are on the edge of reallity | ||
577 | ** here, because the implication is that someone has connected | ||
578 | ** 16+MAX_EXTRA_UNITS onto one host. | ||
579 | */ | ||
580 | static int UnknownMesgDone = 0; | ||
581 | |||
582 | if ( !UnknownMesgDone ) | ||
583 | { | ||
584 | if (! p->RIONoMessage) | ||
585 | cprintf("One or more unknown RTAs are being updated.\n"); | ||
586 | UnknownMesgDone = 1; | ||
587 | } | ||
588 | |||
589 | PktReplyP->Command = ROUTE_FOAD; | ||
590 | HostP->Copy("RT_FOAD",PktReplyP->CommandText,7); | ||
591 | } | ||
592 | else | ||
593 | { | ||
594 | /* | ||
595 | ** we did boot it (as an extra), and there may now be a table | ||
596 | ** slot free (because of a delete), so we will try to make | ||
597 | ** a tentative entry for it, so that the configurator can see it | ||
598 | ** and fill in the details for us. | ||
599 | */ | ||
600 | if (RtaType == TYPE_RTA16) | ||
601 | { | ||
602 | if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) | ||
603 | { | ||
604 | RIODefaultName(p, HostP, ThisUnit); | ||
605 | FillSlot(ThisUnit, ThisUnit2, RtaUniq, HostP); | ||
606 | } | ||
607 | } | ||
608 | else | ||
609 | { | ||
610 | if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) | ||
611 | { | ||
612 | RIODefaultName(p, HostP, ThisUnit); | ||
613 | FillSlot(ThisUnit, 0, RtaUniq, HostP); | ||
614 | } | ||
615 | } | ||
616 | PktReplyP->Command = ROUTE_USED; | ||
617 | HostP->Copy("RT_USED",PktReplyP->CommandText,7); | ||
618 | } | ||
619 | RIOQueueCmdBlk( HostP, Rup, CmdBlkP); | ||
620 | return TRUE; | ||
621 | } | ||
622 | |||
623 | |||
624 | void | ||
625 | RIOFixPhbs(p, HostP, unit) | ||
626 | struct rio_info *p; | ||
627 | struct Host *HostP; | ||
628 | uint unit; | ||
629 | { | ||
630 | ushort link, port; | ||
631 | struct Port *PortP; | ||
632 | unsigned long flags; | ||
633 | int PortN = HostP->Mapping[unit].SysPort; | ||
634 | |||
635 | rio_dprintk (RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN); | ||
636 | |||
637 | if (PortN != -1) { | ||
638 | ushort dest_unit = HostP->Mapping[unit].ID2; | ||
639 | |||
640 | /* | ||
641 | ** Get the link number used for the 1st 8 phbs on this unit. | ||
642 | */ | ||
643 | PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort]; | ||
644 | |||
645 | link = RWORD(PortP->PhbP->link); | ||
646 | |||
647 | for (port = 0; port < PORTS_PER_RTA; port++, PortN++) { | ||
648 | ushort dest_port = port + 8; | ||
649 | #if 0 | ||
650 | uint PktInt; | ||
651 | #endif | ||
652 | WORD *TxPktP; | ||
653 | PKT *Pkt; | ||
654 | |||
655 | PortP = p->RIOPortp[PortN]; | ||
656 | |||
657 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
658 | /* | ||
659 | ** If RTA is not powered on, the tx packets will be | ||
660 | ** unset, so go no further. | ||
661 | */ | ||
662 | if (PortP->TxStart == 0) { | ||
663 | rio_dprintk (RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n"); | ||
664 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
665 | break; | ||
666 | } | ||
667 | |||
668 | /* | ||
669 | ** For the second slot of a 16 port RTA, the driver needs to | ||
670 | ** sort out the phb to port mappings. The dest_unit for this | ||
671 | ** group of 8 phbs is set to the dest_unit of the accompanying | ||
672 | ** 8 port block. The dest_port of the second unit is set to | ||
673 | ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port | ||
674 | ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6 | ||
675 | ** (being the second map ID) will be sent to dest_unit 5, port | ||
676 | ** 14. When this RTA is deleted, dest_unit for ID 6 will be | ||
677 | ** restored, and the dest_port will be reduced by 8. | ||
678 | ** Transmit packets also have a destination field which needs | ||
679 | ** adjusting in the same manner. | ||
680 | ** Note that the unit/port bytes in 'dest' are swapped. | ||
681 | ** We also need to adjust the phb and rup link numbers for the | ||
682 | ** second block of 8 ttys. | ||
683 | */ | ||
684 | for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) { | ||
685 | /* | ||
686 | ** *TxPktP is the pointer to the transmit packet on the host | ||
687 | ** card. This needs to be translated into a 32 bit pointer | ||
688 | ** so it can be accessed from the driver. | ||
689 | */ | ||
690 | Pkt = (PKT *) RIO_PTR(HostP->Caddr,RINDW(TxPktP)); | ||
691 | |||
692 | /* | ||
693 | ** If the packet is used, reset it. | ||
694 | */ | ||
695 | Pkt = (PKT *)((uint)Pkt & ~PKT_IN_USE); | ||
696 | WBYTE(Pkt->dest_unit, dest_unit); | ||
697 | WBYTE(Pkt->dest_port, dest_port); | ||
698 | } | ||
699 | rio_dprintk (RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", | ||
700 | RWORD(PortP->PhbP->destination) & 0xff, | ||
701 | (RWORD(PortP->PhbP->destination) >> 8) & 0xff, | ||
702 | dest_unit, dest_port); | ||
703 | WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8)); | ||
704 | WWORD(PortP->PhbP->link, link); | ||
705 | |||
706 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
707 | } | ||
708 | /* | ||
709 | ** Now make sure the range of ports to be serviced includes | ||
710 | ** the 2nd 8 on this 16 port RTA. | ||
711 | */ | ||
712 | if (link > 3) return; | ||
713 | if (((unit * 8) + 7) > RWORD(HostP->LinkStrP[link].last_port)) { | ||
714 | rio_dprintk (RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7); | ||
715 | WWORD(HostP->LinkStrP[link].last_port, (unit * 8) + 7); | ||
716 | } | ||
717 | } | ||
718 | } | ||
719 | |||
720 | /* | ||
721 | ** Check to see if the new disconnection has isolated this unit. | ||
722 | ** If it has, then invalidate all its link information, and tell | ||
723 | ** the world about it. This is done to ensure that the configurator | ||
724 | ** only gets up-to-date information about what is going on. | ||
725 | */ | ||
726 | static int | ||
727 | RIOCheckIsolated(p, HostP, UnitId) | ||
728 | struct rio_info * p; | ||
729 | struct Host *HostP; | ||
730 | uint UnitId; | ||
731 | { | ||
732 | unsigned long flags; | ||
733 | rio_spin_lock_irqsave(&HostP->HostLock, flags); | ||
734 | |||
735 | #ifdef CHECK | ||
736 | CheckHostP( HostP ); | ||
737 | CheckUnitId( UnitId ); | ||
738 | #endif | ||
739 | if ( RIOCheck( HostP, UnitId ) ) { | ||
740 | rio_dprintk (RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId); | ||
741 | rio_spin_unlock_irqrestore(&HostP->HostLock, flags); | ||
742 | return(0); | ||
743 | } | ||
744 | |||
745 | RIOIsolate(p, HostP, UnitId ); | ||
746 | RIOSetChange(p); | ||
747 | rio_spin_unlock_irqrestore(&HostP->HostLock, flags); | ||
748 | return 1; | ||
749 | } | ||
750 | |||
751 | /* | ||
752 | ** Invalidate all the link interconnectivity of this unit, and of | ||
753 | ** all the units attached to it. This will mean that the entire | ||
754 | ** subnet will re-introduce itself. | ||
755 | */ | ||
756 | static int | ||
757 | RIOIsolate(p, HostP, UnitId) | ||
758 | struct rio_info * p; | ||
759 | struct Host * HostP; | ||
760 | uint UnitId; | ||
761 | { | ||
762 | uint link, unit; | ||
763 | |||
764 | #ifdef CHECK | ||
765 | CheckHostP( HostP ); | ||
766 | CheckUnitId( UnitId ); | ||
767 | #endif | ||
768 | UnitId--; /* this trick relies on the Unit Id being UNSIGNED! */ | ||
769 | |||
770 | if ( UnitId >= MAX_RUP ) /* dontcha just lurv unsigned maths! */ | ||
771 | return(0); | ||
772 | |||
773 | if ( HostP->Mapping[UnitId].Flags & BEEN_HERE ) | ||
774 | return(0); | ||
775 | |||
776 | HostP->Mapping[UnitId].Flags |= BEEN_HERE; | ||
777 | |||
778 | if ( p->RIOPrintDisabled == DO_PRINT ) | ||
779 | rio_dprintk (RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name); | ||
780 | |||
781 | for ( link=0; link<LINKS_PER_UNIT; link++) { | ||
782 | unit = HostP->Mapping[UnitId].Topology[link].Unit; | ||
783 | HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT; | ||
784 | HostP->Mapping[UnitId].Topology[link].Link = NO_LINK; | ||
785 | RIOIsolate(p, HostP, unit ); | ||
786 | } | ||
787 | HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; | ||
788 | return 1; | ||
789 | } | ||
790 | |||
791 | static int | ||
792 | RIOCheck(HostP, UnitId) | ||
793 | struct Host *HostP; | ||
794 | uint UnitId; | ||
795 | { | ||
796 | unsigned char link; | ||
797 | |||
798 | #ifdef CHECK | ||
799 | CheckHostP( HostP ); | ||
800 | CheckUnitId( UnitId ); | ||
801 | #endif | ||
802 | /* rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */ | ||
803 | rio_dprintk (RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId); | ||
804 | |||
805 | if ( UnitId == HOST_ID ) { | ||
806 | /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */ | ||
807 | return 1; | ||
808 | } | ||
809 | |||
810 | UnitId--; | ||
811 | |||
812 | if ( UnitId >= MAX_RUP ) { | ||
813 | /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */ | ||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | for ( link=0; link<LINKS_PER_UNIT; link++ ) { | ||
818 | if ( HostP->Mapping[UnitId].Topology[link].Unit==HOST_ID ) { | ||
819 | /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", | ||
820 | UnitId, 'A'+link)); */ | ||
821 | return 1; | ||
822 | } | ||
823 | } | ||
824 | |||
825 | if ( HostP->Mapping[UnitId].Flags & BEEN_HERE ) { | ||
826 | /* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */ | ||
827 | return 0; | ||
828 | } | ||
829 | |||
830 | HostP->Mapping[UnitId].Flags |= BEEN_HERE; | ||
831 | |||
832 | for ( link=0; link < LINKS_PER_UNIT; link++ ) { | ||
833 | /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */ | ||
834 | if ( RIOCheck( HostP, HostP->Mapping[UnitId].Topology[link].Unit ) ) { | ||
835 | /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */ | ||
836 | HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; | ||
837 | return 1; | ||
838 | } | ||
839 | } | ||
840 | |||
841 | HostP->Mapping[UnitId].Flags &= ~BEEN_HERE; | ||
842 | |||
843 | /* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */ | ||
844 | |||
845 | return 0; | ||
846 | } | ||
847 | |||
848 | /* | ||
849 | ** Returns the type of unit (host, 16/8 port RTA) | ||
850 | */ | ||
851 | |||
852 | uint | ||
853 | GetUnitType(Uniq) | ||
854 | uint Uniq; | ||
855 | { | ||
856 | switch ( (Uniq >> 28) & 0xf) | ||
857 | { | ||
858 | case RIO_AT: | ||
859 | case RIO_MCA: | ||
860 | case RIO_EISA: | ||
861 | case RIO_PCI: | ||
862 | rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Host\n"); | ||
863 | return(TYPE_HOST); | ||
864 | case RIO_RTA_16: | ||
865 | rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n"); | ||
866 | return(TYPE_RTA16); | ||
867 | case RIO_RTA: | ||
868 | rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n"); | ||
869 | return(TYPE_RTA8); | ||
870 | default : | ||
871 | rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n"); | ||
872 | return(99); | ||
873 | } | ||
874 | } | ||
875 | |||
876 | int | ||
877 | RIOSetChange(p) | ||
878 | struct rio_info * p; | ||
879 | { | ||
880 | if ( p->RIOQuickCheck != NOT_CHANGED ) | ||
881 | return(0); | ||
882 | p->RIOQuickCheck = CHANGED; | ||
883 | if ( p->RIOSignalProcess ) { | ||
884 | rio_dprintk (RIO_DEBUG_ROUTE, "Send SIG-HUP"); | ||
885 | /* | ||
886 | psignal( RIOSignalProcess, SIGHUP ); | ||
887 | */ | ||
888 | } | ||
889 | return(0); | ||
890 | } | ||
891 | |||
892 | static void | ||
893 | RIOConCon(p, HostP, FromId, FromLink, ToId, ToLink, Change) | ||
894 | struct rio_info * p; | ||
895 | struct Host *HostP; | ||
896 | uint FromId; | ||
897 | uint FromLink; | ||
898 | uint ToId; | ||
899 | uint ToLink; | ||
900 | int Change; | ||
901 | { | ||
902 | char *FromName; | ||
903 | char *FromType; | ||
904 | char *ToName; | ||
905 | char *ToType; | ||
906 | unsigned int tp; | ||
907 | |||
908 | /* | ||
909 | ** 15.10.1998 ARG - ESIL 0759 | ||
910 | ** (Part) fix for port being trashed when opened whilst RTA "disconnected" | ||
911 | ** | ||
912 | ** What's this doing in here anyway ? | ||
913 | ** It was causing the port to be 'unmapped' if opened whilst RTA "disconnected" | ||
914 | ** | ||
915 | ** 09.12.1998 ARG - ESIL 0776 - part fix | ||
916 | ** Okay, We've found out what this was all about now ! | ||
917 | ** Someone had botched this to use RIOHalted to indicated the number of RTAs | ||
918 | ** 'disconnected'. The value in RIOHalted was then being used in the | ||
919 | ** 'RIO_QUICK_CHECK' ioctl. A none zero value indicating that a least one RTA | ||
920 | ** is 'disconnected'. The change was put in to satisfy a customer's needs. | ||
921 | ** Having taken this bit of code out 'RIO_QUICK_CHECK' now no longer works for | ||
922 | ** the customer. | ||
923 | ** | ||
924 | if (Change == CONNECT) { | ||
925 | if (p->RIOHalted) p->RIOHalted --; | ||
926 | } | ||
927 | else { | ||
928 | p->RIOHalted ++; | ||
929 | } | ||
930 | ** | ||
931 | ** So - we need to implement it slightly differently - a new member of the | ||
932 | ** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA | ||
933 | ** connections and disconnections. | ||
934 | */ | ||
935 | if (Change == CONNECT) { | ||
936 | if (p->RIORtaDisCons) p->RIORtaDisCons--; | ||
937 | } | ||
938 | else { | ||
939 | p->RIORtaDisCons++; | ||
940 | } | ||
941 | |||
942 | if ( p->RIOPrintDisabled == DONT_PRINT ) | ||
943 | return; | ||
944 | |||
945 | if ( FromId > ToId ) { | ||
946 | tp = FromId; | ||
947 | FromId = ToId; | ||
948 | ToId = tp; | ||
949 | tp = FromLink; | ||
950 | FromLink = ToLink; | ||
951 | ToLink = tp; | ||
952 | } | ||
953 | |||
954 | FromName = FromId ? HostP->Mapping[FromId-1].Name : HostP->Name; | ||
955 | FromType = FromId ? "RTA" : "HOST"; | ||
956 | ToName = ToId ? HostP->Mapping[ToId-1].Name : HostP->Name; | ||
957 | ToType = ToId ? "RTA" : "HOST"; | ||
958 | |||
959 | rio_dprintk (RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", | ||
960 | FromType, FromName, 'A'+FromLink, | ||
961 | ToType, ToName, 'A'+ToLink, | ||
962 | (Change==CONNECT) ? "established" : "disconnected"); | ||
963 | cprintf("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", | ||
964 | FromType, FromName, 'A'+FromLink, | ||
965 | ToType, ToName, 'A'+ToLink, | ||
966 | (Change==CONNECT) ? "established" : "disconnected"); | ||
967 | } | ||
968 | |||
969 | /* | ||
970 | ** RIORemoveFromSavedTable : | ||
971 | ** | ||
972 | ** Delete and RTA entry from the saved table given to us | ||
973 | ** by the configuration program. | ||
974 | */ | ||
975 | static int | ||
976 | RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap) | ||
977 | { | ||
978 | int entry; | ||
979 | |||
980 | /* | ||
981 | ** We loop for all entries even after finding an entry and | ||
982 | ** zeroing it because we may have two entries to delete if | ||
983 | ** it's a 16 port RTA. | ||
984 | */ | ||
985 | for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) | ||
986 | { | ||
987 | if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) | ||
988 | { | ||
989 | bzero((caddr_t)&p->RIOSavedTable[entry], sizeof(struct Map)); | ||
990 | } | ||
991 | } | ||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | |||
996 | /* | ||
997 | ** RIOCheckDisconnected : | ||
998 | ** | ||
999 | ** Scan the unit links to and return zero if the unit is completely | ||
1000 | ** disconnected. | ||
1001 | */ | ||
1002 | static int | ||
1003 | RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit) | ||
1004 | { | ||
1005 | int link; | ||
1006 | |||
1007 | |||
1008 | rio_dprintk (RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit); | ||
1009 | /* | ||
1010 | ** If the slot is tentative and does not belong to the | ||
1011 | ** second half of a 16 port RTA then scan to see if | ||
1012 | ** is disconnected. | ||
1013 | */ | ||
1014 | for (link = 0; link < LINKS_PER_UNIT; link++) | ||
1015 | { | ||
1016 | if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT) | ||
1017 | break; | ||
1018 | } | ||
1019 | |||
1020 | /* | ||
1021 | ** If not all links are disconnected then we can forget about it. | ||
1022 | */ | ||
1023 | if (link < LINKS_PER_UNIT) | ||
1024 | return 1; | ||
1025 | |||
1026 | #if NEED_TO_FIX_THIS | ||
1027 | /* Ok so all the links are disconnected. But we may have only just | ||
1028 | ** made this slot tentative and not yet received a topology update. | ||
1029 | ** Lets check how long ago we made it tentative. | ||
1030 | */ | ||
1031 | rio_dprintk (RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit); | ||
1032 | if (drv_getparm(LBOLT, (ulong_t *) ¤t_time)) | ||
1033 | rio_dprintk (RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n"); | ||
1034 | |||
1035 | elapse_time = current_time - TentTime[unit]; | ||
1036 | rio_dprintk (RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", | ||
1037 | elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time)); | ||
1038 | if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) | ||
1039 | { | ||
1040 | rio_dprintk (RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", | ||
1041 | unit, drv_hztousec(elapse_time)); | ||
1042 | return 1; | ||
1043 | } | ||
1044 | #endif | ||
1045 | |||
1046 | /* | ||
1047 | ** We have found an usable slot. | ||
1048 | ** If it is half of a 16 port RTA then delete the other half. | ||
1049 | */ | ||
1050 | if (HostP->Mapping[unit].ID2 != 0) | ||
1051 | { | ||
1052 | int nOther = (HostP->Mapping[unit].ID2) -1; | ||
1053 | |||
1054 | rio_dprintk (RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther); | ||
1055 | bzero((caddr_t)&HostP->Mapping[nOther], sizeof(struct Map)); | ||
1056 | } | ||
1057 | RIORemoveFromSavedTable(p, &HostP->Mapping[unit]); | ||
1058 | |||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | /* | ||
1064 | ** RIOFindFreeID : | ||
1065 | ** | ||
1066 | ** This function scans the given host table for either one | ||
1067 | ** or two free unit ID's. | ||
1068 | */ | ||
1069 | int | ||
1070 | RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2) | ||
1071 | { | ||
1072 | int unit,tempID; | ||
1073 | |||
1074 | /* | ||
1075 | ** Initialise the ID's to MAX_RUP. | ||
1076 | ** We do this to make the loop for setting the ID's as simple as | ||
1077 | ** possible. | ||
1078 | */ | ||
1079 | *pID1 = MAX_RUP; | ||
1080 | if (pID2 != NULL) | ||
1081 | *pID2 = MAX_RUP; | ||
1082 | |||
1083 | /* | ||
1084 | ** Scan all entries of the host mapping table for free slots. | ||
1085 | ** We scan for free slots first and then if that is not successful | ||
1086 | ** we start all over again looking for tentative slots we can re-use. | ||
1087 | */ | ||
1088 | for (unit = 0; unit < MAX_RUP; unit++) | ||
1089 | { | ||
1090 | rio_dprintk (RIO_DEBUG_ROUTE, "Scanning unit %d\n",unit); | ||
1091 | /* | ||
1092 | ** If the flags are zero then the slot is empty. | ||
1093 | */ | ||
1094 | if (HostP->Mapping[unit].Flags == 0) | ||
1095 | { | ||
1096 | rio_dprintk (RIO_DEBUG_ROUTE, " This slot is empty.\n"); | ||
1097 | /* | ||
1098 | ** If we haven't allocated the first ID then do it now. | ||
1099 | */ | ||
1100 | if (*pID1 == MAX_RUP) | ||
1101 | { | ||
1102 | rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit); | ||
1103 | *pID1 = unit; | ||
1104 | |||
1105 | /* | ||
1106 | ** If the second ID is not needed then we can return | ||
1107 | ** now. | ||
1108 | */ | ||
1109 | if (pID2 == NULL) | ||
1110 | return 0; | ||
1111 | } | ||
1112 | else | ||
1113 | { | ||
1114 | /* | ||
1115 | ** Allocate the second slot and return. | ||
1116 | */ | ||
1117 | rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit); | ||
1118 | *pID2 = unit; | ||
1119 | return 0; | ||
1120 | } | ||
1121 | } | ||
1122 | } | ||
1123 | |||
1124 | /* | ||
1125 | ** If we manage to come out of the free slot loop then we | ||
1126 | ** need to start all over again looking for tentative slots | ||
1127 | ** that we can re-use. | ||
1128 | */ | ||
1129 | rio_dprintk (RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n"); | ||
1130 | for (unit = 0; unit < MAX_RUP; unit++) | ||
1131 | { | ||
1132 | if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || | ||
1133 | (HostP->Mapping[unit].Flags == 0)) && ! | ||
1134 | (HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT )) | ||
1135 | { | ||
1136 | rio_dprintk (RIO_DEBUG_ROUTE, " Slot %d looks promising.\n",unit); | ||
1137 | |||
1138 | if(unit == *pID1) | ||
1139 | { | ||
1140 | rio_dprintk (RIO_DEBUG_ROUTE, " No it isn't, its the 1st half\n"); | ||
1141 | continue; | ||
1142 | } | ||
1143 | |||
1144 | /* | ||
1145 | ** Slot is Tentative or Empty, but not a tentative second | ||
1146 | ** slot of a 16 porter. | ||
1147 | ** Attempt to free up this slot (and its parnter if | ||
1148 | ** it is a 16 port slot. The second slot will become | ||
1149 | ** empty after a call to RIOFreeDisconnected so thats why | ||
1150 | ** we look for empty slots above as well). | ||
1151 | */ | ||
1152 | if (HostP->Mapping[unit].Flags != 0) | ||
1153 | if (RIOFreeDisconnected(p, HostP, unit) != 0) | ||
1154 | continue; | ||
1155 | /* | ||
1156 | ** If we haven't allocated the first ID then do it now. | ||
1157 | */ | ||
1158 | if (*pID1 == MAX_RUP) | ||
1159 | { | ||
1160 | rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit); | ||
1161 | *pID1 = unit; | ||
1162 | |||
1163 | /* | ||
1164 | ** Clear out this slot now that we intend to use it. | ||
1165 | */ | ||
1166 | bzero(&HostP->Mapping[unit], sizeof(struct Map)); | ||
1167 | |||
1168 | /* | ||
1169 | ** If the second ID is not needed then we can return | ||
1170 | ** now. | ||
1171 | */ | ||
1172 | if (pID2 == NULL) | ||
1173 | return 0; | ||
1174 | } | ||
1175 | else | ||
1176 | { | ||
1177 | /* | ||
1178 | ** Allocate the second slot and return. | ||
1179 | */ | ||
1180 | rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative/empty entry for second unit %d\n", | ||
1181 | unit); | ||
1182 | *pID2 = unit; | ||
1183 | |||
1184 | /* | ||
1185 | ** Clear out this slot now that we intend to use it. | ||
1186 | */ | ||
1187 | bzero(&HostP->Mapping[unit], sizeof(struct Map)); | ||
1188 | |||
1189 | /* At this point under the right(wrong?) conditions | ||
1190 | ** we may have a first unit ID being higher than the | ||
1191 | ** second unit ID. This is a bad idea if we are about | ||
1192 | ** to fill the slots with a 16 port RTA. | ||
1193 | ** Better check and swap them over. | ||
1194 | */ | ||
1195 | |||
1196 | if (*pID1 > *pID2) | ||
1197 | { | ||
1198 | rio_dprintk (RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2); | ||
1199 | tempID = *pID1; | ||
1200 | *pID1 = *pID2; | ||
1201 | *pID2 = tempID; | ||
1202 | } | ||
1203 | return 0; | ||
1204 | } | ||
1205 | } | ||
1206 | } | ||
1207 | |||
1208 | /* | ||
1209 | ** If we manage to get to the end of the second loop then we | ||
1210 | ** can give up and return a failure. | ||
1211 | */ | ||
1212 | return 1; | ||
1213 | } | ||
1214 | |||
1215 | |||
1216 | /* | ||
1217 | ** The link switch scenario. | ||
1218 | ** | ||
1219 | ** Rta Wun (A) is connected to Tuw (A). | ||
1220 | ** The tables are all up to date, and the system is OK. | ||
1221 | ** | ||
1222 | ** If Wun (A) is now moved to Wun (B) before Wun (A) can | ||
1223 | ** become disconnected, then the follow happens: | ||
1224 | ** | ||
1225 | ** Tuw (A) spots the change of unit:link at the other end | ||
1226 | ** of its link and Tuw sends a topology packet reflecting | ||
1227 | ** the change: Tuw (A) now disconnected from Wun (A), and | ||
1228 | ** this is closely followed by a packet indicating that | ||
1229 | ** Tuw (A) is now connected to Wun (B). | ||
1230 | ** | ||
1231 | ** Wun (B) will spot that it has now become connected, and | ||
1232 | ** Wun will send a topology packet, which indicates that | ||
1233 | ** both Wun (A) and Wun (B) is connected to Tuw (A). | ||
1234 | ** | ||
1235 | ** Eventually Wun (A) realises that it is now disconnected | ||
1236 | ** and Wun will send out a topology packet indicating that | ||
1237 | ** Wun (A) is now disconnected. | ||
1238 | */ | ||
diff --git a/drivers/char/rio/riospace.h b/drivers/char/rio/riospace.h new file mode 100644 index 000000000000..32b09b0f23aa --- /dev/null +++ b/drivers/char/rio/riospace.h | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : riospace.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:13 | ||
26 | ** Retrieved : 11/6/98 11:34:22 | ||
27 | ** | ||
28 | ** ident @(#)riospace.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_riospace_h__ | ||
34 | #define __rio_riospace_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_riospace_h_sccs_ = "@(#)riospace.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | #define RIO_LOCATOR_LEN 16 | ||
41 | #define MAX_RIO_BOARDS 4 | ||
42 | |||
43 | /* | ||
44 | ** DONT change this file. At all. Unless you can rebuild the entire | ||
45 | ** device driver, which you probably can't, then the rest of the | ||
46 | ** driver won't see any changes you make here. So don't make any. | ||
47 | ** In particular, it won't be able to see changes to RIO_SLOTS | ||
48 | */ | ||
49 | |||
50 | struct Conf | ||
51 | { | ||
52 | char Locator[24]; | ||
53 | unsigned int StartupTime; | ||
54 | unsigned int SlowCook; | ||
55 | unsigned int IntrPollTime; | ||
56 | unsigned int BreakInterval; | ||
57 | unsigned int Timer; | ||
58 | unsigned int RtaLoadBase; | ||
59 | unsigned int HostLoadBase; | ||
60 | unsigned int XpHz; | ||
61 | unsigned int XpCps; | ||
62 | char *XpOn; | ||
63 | char *XpOff; | ||
64 | unsigned int MaxXpCps; | ||
65 | unsigned int MinXpCps; | ||
66 | unsigned int SpinCmds; | ||
67 | unsigned int FirstAddr; | ||
68 | unsigned int LastAddr; | ||
69 | unsigned int BufferSize; | ||
70 | unsigned int LowWater; | ||
71 | unsigned int LineLength; | ||
72 | unsigned int CmdTime; | ||
73 | }; | ||
74 | |||
75 | /* | ||
76 | ** Board types - these MUST correspond to product codes! | ||
77 | */ | ||
78 | #define RIO_EMPTY 0x0 | ||
79 | #define RIO_EISA 0x3 | ||
80 | #define RIO_RTA_16 0x9 | ||
81 | #define RIO_AT 0xA | ||
82 | #define RIO_MCA 0xB | ||
83 | #define RIO_PCI 0xD | ||
84 | #define RIO_RTA 0xE | ||
85 | |||
86 | /* | ||
87 | ** Board data structure. This is used for configuration info | ||
88 | */ | ||
89 | struct Brd | ||
90 | { | ||
91 | unsigned char Type; /* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */ | ||
92 | unsigned char Ivec; /* POLLED or ivec number */ | ||
93 | unsigned char Mode; /* Control stuff, see below */ | ||
94 | }; | ||
95 | |||
96 | struct Board | ||
97 | { | ||
98 | char Locator[RIO_LOCATOR_LEN]; | ||
99 | int NumSlots; | ||
100 | struct Brd Boards[MAX_RIO_BOARDS]; | ||
101 | }; | ||
102 | |||
103 | #define BOOT_FROM_LINK 0x00 | ||
104 | #define BOOT_FROM_RAM 0x01 | ||
105 | #define EXTERNAL_BUS_OFF 0x00 | ||
106 | #define EXTERNAL_BUS_ON 0x02 | ||
107 | #define INTERRUPT_DISABLE 0x00 | ||
108 | #define INTERRUPT_ENABLE 0x04 | ||
109 | #define BYTE_OPERATION 0x00 | ||
110 | #define WORD_OPERATION 0x08 | ||
111 | #define POLLED INTERRUPT_DISABLE | ||
112 | #define IRQ_15 (0x00 | INTERRUPT_ENABLE) | ||
113 | #define IRQ_12 (0x10 | INTERRUPT_ENABLE) | ||
114 | #define IRQ_11 (0x20 | INTERRUPT_ENABLE) | ||
115 | #define IRQ_9 (0x30 | INTERRUPT_ENABLE) | ||
116 | #define SLOW_LINKS 0x00 | ||
117 | #define FAST_LINKS 0x40 | ||
118 | #define SLOW_AT_BUS 0x00 | ||
119 | #define FAST_AT_BUS 0x80 | ||
120 | #define SLOW_PCI_TP 0x00 | ||
121 | #define FAST_PCI_TP 0x80 | ||
122 | /* | ||
123 | ** Debug levels | ||
124 | */ | ||
125 | #define DBG_NONE 0x00000000 | ||
126 | |||
127 | #define DBG_INIT 0x00000001 | ||
128 | #define DBG_OPEN 0x00000002 | ||
129 | #define DBG_CLOSE 0x00000004 | ||
130 | #define DBG_IOCTL 0x00000008 | ||
131 | |||
132 | #define DBG_READ 0x00000010 | ||
133 | #define DBG_WRITE 0x00000020 | ||
134 | #define DBG_INTR 0x00000040 | ||
135 | #define DBG_PROC 0x00000080 | ||
136 | |||
137 | #define DBG_PARAM 0x00000100 | ||
138 | #define DBG_CMD 0x00000200 | ||
139 | #define DBG_XPRINT 0x00000400 | ||
140 | #define DBG_POLL 0x00000800 | ||
141 | |||
142 | #define DBG_DAEMON 0x00001000 | ||
143 | #define DBG_FAIL 0x00002000 | ||
144 | #define DBG_MODEM 0x00004000 | ||
145 | #define DBG_LIST 0x00008000 | ||
146 | |||
147 | #define DBG_ROUTE 0x00010000 | ||
148 | #define DBG_UTIL 0x00020000 | ||
149 | #define DBG_BOOT 0x00040000 | ||
150 | #define DBG_BUFFER 0x00080000 | ||
151 | |||
152 | #define DBG_MON 0x00100000 | ||
153 | #define DBG_SPECIAL 0x00200000 | ||
154 | #define DBG_VPIX 0x00400000 | ||
155 | #define DBG_FLUSH 0x00800000 | ||
156 | |||
157 | #define DBG_QENABLE 0x01000000 | ||
158 | |||
159 | #define DBG_ALWAYS 0x80000000 | ||
160 | |||
161 | #endif /* __rio_riospace_h__ */ | ||
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c new file mode 100644 index 000000000000..8fb26ad2aa12 --- /dev/null +++ b/drivers/char/rio/riotable.c | |||
@@ -0,0 +1,1044 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : riotable.c | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 10:33:47 | ||
26 | ** Retrieved : 11/6/98 10:33:50 | ||
27 | ** | ||
28 | ** ident @(#)riotable.c 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | #ifdef SCCS_LABELS | ||
33 | static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2"; | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/errno.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/string.h> | ||
41 | |||
42 | #include <asm/io.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/string.h> | ||
45 | #include <asm/semaphore.h> | ||
46 | #include <asm/uaccess.h> | ||
47 | |||
48 | #include <linux/termios.h> | ||
49 | #include <linux/serial.h> | ||
50 | |||
51 | #include <linux/generic_serial.h> | ||
52 | |||
53 | |||
54 | #include "linux_compat.h" | ||
55 | #include "rio_linux.h" | ||
56 | #include "typdef.h" | ||
57 | #include "pkt.h" | ||
58 | #include "daemon.h" | ||
59 | #include "rio.h" | ||
60 | #include "riospace.h" | ||
61 | #include "top.h" | ||
62 | #include "cmdpkt.h" | ||
63 | #include "map.h" | ||
64 | #include "riotypes.h" | ||
65 | #include "rup.h" | ||
66 | #include "port.h" | ||
67 | #include "riodrvr.h" | ||
68 | #include "rioinfo.h" | ||
69 | #include "func.h" | ||
70 | #include "errors.h" | ||
71 | #include "pci.h" | ||
72 | |||
73 | #include "parmmap.h" | ||
74 | #include "unixrup.h" | ||
75 | #include "board.h" | ||
76 | #include "host.h" | ||
77 | #include "error.h" | ||
78 | #include "phb.h" | ||
79 | #include "link.h" | ||
80 | #include "cmdblk.h" | ||
81 | #include "route.h" | ||
82 | #include "control.h" | ||
83 | #include "cirrus.h" | ||
84 | #include "rioioctl.h" | ||
85 | #include "param.h" | ||
86 | #include "list.h" | ||
87 | #include "sam.h" | ||
88 | #include "protsts.h" | ||
89 | |||
90 | /* | ||
91 | ** A configuration table has been loaded. It is now up to us | ||
92 | ** to sort it out and use the information contained therein. | ||
93 | */ | ||
94 | int | ||
95 | RIONewTable(p) | ||
96 | struct rio_info * p; | ||
97 | { | ||
98 | int Host, Host1, Host2, NameIsUnique, Entry, SubEnt; | ||
99 | struct Map *MapP; | ||
100 | struct Map *HostMapP; | ||
101 | struct Host *HostP; | ||
102 | |||
103 | char *cptr; | ||
104 | |||
105 | /* | ||
106 | ** We have been sent a new table to install. We need to break | ||
107 | ** it down into little bits and spread it around a bit to see | ||
108 | ** what we have got. | ||
109 | */ | ||
110 | /* | ||
111 | ** Things to check: | ||
112 | ** (things marked 'xx' aren't checked any more!) | ||
113 | ** (1) That there are no booted Hosts/RTAs out there. | ||
114 | ** (2) That the names are properly formed | ||
115 | ** (3) That blank entries really are. | ||
116 | ** xx (4) That hosts mentioned in the table actually exist. xx | ||
117 | ** (5) That the IDs are unique (per host). | ||
118 | ** (6) That host IDs are zero | ||
119 | ** (7) That port numbers are valid | ||
120 | ** (8) That port numbers aren't duplicated | ||
121 | ** (9) That names aren't duplicated | ||
122 | ** xx (10) That hosts that actually exist are mentioned in the table. xx | ||
123 | */ | ||
124 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n"); | ||
125 | if ( p->RIOSystemUp ) { /* (1) */ | ||
126 | p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED; | ||
127 | return -EBUSY; | ||
128 | } | ||
129 | |||
130 | p->RIOError.Error = NOTHING_WRONG_AT_ALL; | ||
131 | p->RIOError.Entry = -1; | ||
132 | p->RIOError.Other = -1; | ||
133 | |||
134 | for ( Entry=0; Entry<TOTAL_MAP_ENTRIES; Entry++ ) { | ||
135 | MapP = &p->RIOConnectTable[Entry]; | ||
136 | if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) { | ||
137 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n"); | ||
138 | cptr = MapP->Name; /* (2) */ | ||
139 | cptr[MAX_NAME_LEN-1]='\0'; | ||
140 | if ( cptr[0]=='\0' ) { | ||
141 | bcopy(MapP->RtaUniqueNum?"RTA NN":"HOST NN",MapP->Name,8); | ||
142 | MapP->Name[5] = '0'+Entry/10; | ||
143 | MapP->Name[6] = '0'+Entry%10; | ||
144 | } | ||
145 | while ( *cptr ) { | ||
146 | if ( *cptr<' ' || *cptr>'~' ) { | ||
147 | p->RIOError.Error = BAD_CHARACTER_IN_NAME; | ||
148 | p->RIOError.Entry = Entry; | ||
149 | return -ENXIO; | ||
150 | } | ||
151 | cptr++; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | ** If the entry saved was a tentative entry then just forget | ||
157 | ** about it. | ||
158 | */ | ||
159 | if ( MapP->Flags & SLOT_TENTATIVE ) { | ||
160 | MapP->HostUniqueNum = 0; | ||
161 | MapP->RtaUniqueNum = 0; | ||
162 | continue; | ||
163 | } | ||
164 | |||
165 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n"); | ||
166 | if ( !MapP->RtaUniqueNum && !MapP->HostUniqueNum ) { /* (3) */ | ||
167 | if ( MapP->ID || MapP->SysPort || MapP->Flags ) { | ||
168 | rio_dprintk (RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n",MapP->Name); | ||
169 | p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL; | ||
170 | p->RIOError.Entry = Entry; | ||
171 | return -ENXIO; | ||
172 | } | ||
173 | rio_dprintk (RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n"); | ||
174 | continue; | ||
175 | } | ||
176 | |||
177 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n"); | ||
178 | for ( Host=0; Host<p->RIONumHosts; Host++ ) { /* (4) */ | ||
179 | if ( p->RIOHosts[Host].UniqueNum==MapP->HostUniqueNum ) { | ||
180 | HostP = &p->RIOHosts[Host]; | ||
181 | /* | ||
182 | ** having done the lookup, we don't really want to do | ||
183 | ** it again, so hang the host number in a safe place | ||
184 | */ | ||
185 | MapP->Topology[0].Unit = Host; | ||
186 | break; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | if ( Host >= p->RIONumHosts ) { | ||
191 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", | ||
192 | MapP->Name, MapP->HostUniqueNum); | ||
193 | MapP->HostUniqueNum = 0; | ||
194 | /* MapP->RtaUniqueNum = 0; */ | ||
195 | /* MapP->ID = 0; */ | ||
196 | /* MapP->Flags = 0; */ | ||
197 | /* MapP->SysPort = 0; */ | ||
198 | /* MapP->Name[0] = 0; */ | ||
199 | continue; | ||
200 | } | ||
201 | |||
202 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n"); | ||
203 | if ( MapP->RtaUniqueNum ) { /* (5) */ | ||
204 | if ( !MapP->ID ) { | ||
205 | rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", | ||
206 | MapP->Name); | ||
207 | p->RIOError.Error = ZERO_RTA_ID; | ||
208 | p->RIOError.Entry = Entry; | ||
209 | return -ENXIO; | ||
210 | } | ||
211 | if ( MapP->ID > MAX_RUP ) { | ||
212 | rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", | ||
213 | MapP->Name, MapP->ID); | ||
214 | p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; | ||
215 | p->RIOError.Entry = Entry; | ||
216 | return -ENXIO; | ||
217 | } | ||
218 | for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) { | ||
219 | if ( MapP->HostUniqueNum == | ||
220 | p->RIOConnectTable[SubEnt].HostUniqueNum && | ||
221 | MapP->ID == p->RIOConnectTable[SubEnt].ID ) { | ||
222 | rio_dprintk (RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", | ||
223 | MapP->Name, p->RIOConnectTable[SubEnt].Name); | ||
224 | p->RIOError.Error = DUPLICATED_RTA_ID; | ||
225 | p->RIOError.Entry = Entry; | ||
226 | p->RIOError.Other = SubEnt; | ||
227 | return -ENXIO; | ||
228 | } | ||
229 | /* | ||
230 | ** If the RtaUniqueNum is the same, it may be looking at both | ||
231 | ** entries for a 16 port RTA, so check the ids | ||
232 | */ | ||
233 | if ((MapP->RtaUniqueNum == | ||
234 | p->RIOConnectTable[SubEnt].RtaUniqueNum) | ||
235 | && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) { | ||
236 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n",MapP->Name); | ||
237 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", | ||
238 | p->RIOConnectTable[SubEnt].Name); | ||
239 | p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER; | ||
240 | p->RIOError.Entry = Entry; | ||
241 | p->RIOError.Other = SubEnt; | ||
242 | return -ENXIO; | ||
243 | } | ||
244 | } | ||
245 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n"); | ||
246 | /* (7a) */ | ||
247 | if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort % PORTS_PER_RTA)) { | ||
248 | rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", | ||
249 | (int)MapP->SysPort,MapP->Name, PORTS_PER_RTA); | ||
250 | p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; | ||
251 | p->RIOError.Entry = Entry; | ||
252 | return -ENXIO; | ||
253 | } | ||
254 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n"); | ||
255 | /* (7b) */ | ||
256 | if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort >= RIO_PORTS)) { | ||
257 | rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", | ||
258 | (int)MapP->SysPort, MapP->Name); | ||
259 | p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; | ||
260 | p->RIOError.Entry = Entry; | ||
261 | return -ENXIO; | ||
262 | } | ||
263 | for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) { | ||
264 | if ( p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT ) | ||
265 | continue; | ||
266 | if ( p->RIOConnectTable[SubEnt].RtaUniqueNum ) { | ||
267 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n"); | ||
268 | /* (8) */ | ||
269 | if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort == | ||
270 | p->RIOConnectTable[SubEnt].SysPort) ) { | ||
271 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", | ||
272 | MapP->Name, p->RIOConnectTable[SubEnt].Name, | ||
273 | (int)MapP->SysPort); | ||
274 | p->RIOError.Error = TTY_NUMBER_IN_USE; | ||
275 | p->RIOError.Entry = Entry; | ||
276 | p->RIOError.Other = SubEnt; | ||
277 | return -ENXIO; | ||
278 | } | ||
279 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n"); | ||
280 | if (strcmp(MapP->Name, | ||
281 | p->RIOConnectTable[SubEnt].Name)==0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */ | ||
282 | rio_dprintk (RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name); | ||
283 | p->RIOError.Error = NAME_USED_TWICE; | ||
284 | p->RIOError.Entry = Entry; | ||
285 | p->RIOError.Other = SubEnt; | ||
286 | return -ENXIO; | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | } | ||
291 | else { /* (6) */ | ||
292 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n"); | ||
293 | if ( MapP->ID ) { | ||
294 | rio_dprintk (RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", | ||
295 | MapP->Name); | ||
296 | p->RIOError.Error = HOST_ID_NOT_ZERO; | ||
297 | p->RIOError.Entry = Entry; | ||
298 | return -ENXIO; | ||
299 | } | ||
300 | if ( MapP->SysPort != NO_PORT ) { | ||
301 | rio_dprintk (RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", | ||
302 | MapP->Name); | ||
303 | p->RIOError.Error = HOST_SYSPORT_BAD; | ||
304 | p->RIOError.Entry = Entry; | ||
305 | return -ENXIO; | ||
306 | } | ||
307 | } | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | ** wow! if we get here then it's a goody! | ||
312 | */ | ||
313 | |||
314 | /* | ||
315 | ** Zero the (old) entries for each host... | ||
316 | */ | ||
317 | for ( Host=0; Host<RIO_HOSTS; Host++ ) { | ||
318 | for ( Entry=0; Entry<MAX_RUP; Entry++ ) { | ||
319 | bzero((caddr_t)&p->RIOHosts[Host].Mapping[Entry], | ||
320 | sizeof(struct Map)); | ||
321 | } | ||
322 | bzero((caddr_t)&p->RIOHosts[Host].Name[0], | ||
323 | sizeof(p->RIOHosts[Host].Name) ); | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | ** Copy in the new table entries | ||
328 | */ | ||
329 | for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) { | ||
330 | rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry); | ||
331 | MapP = &p->RIOConnectTable[Entry]; | ||
332 | |||
333 | /* | ||
334 | ** Now, if it is an empty slot ignore it! | ||
335 | */ | ||
336 | if ( MapP->HostUniqueNum==0 ) | ||
337 | continue; | ||
338 | |||
339 | /* | ||
340 | ** we saved the host number earlier, so grab it back | ||
341 | */ | ||
342 | HostP = &p->RIOHosts[MapP->Topology[0].Unit]; | ||
343 | |||
344 | /* | ||
345 | ** If it is a host, then we only need to fill in the name field. | ||
346 | */ | ||
347 | if ( MapP->ID==0 ) { | ||
348 | rio_dprintk (RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name); | ||
349 | bcopy(MapP->Name,HostP->Name,MAX_NAME_LEN); | ||
350 | continue; | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | ** Its an RTA entry, so fill in the host mapping entries for it | ||
355 | ** and the port mapping entries. Notice that entry zero is for | ||
356 | ** ID one. | ||
357 | */ | ||
358 | HostMapP = &HostP->Mapping[MapP->ID-1]; | ||
359 | |||
360 | if (MapP->Flags & SLOT_IN_USE) { | ||
361 | rio_dprintk (RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name); | ||
362 | /* | ||
363 | ** structure assign, then sort out the bits we shouldn't have done | ||
364 | */ | ||
365 | *HostMapP = *MapP; | ||
366 | |||
367 | HostMapP->Flags = SLOT_IN_USE; | ||
368 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
369 | HostMapP->Flags |= RTA16_SECOND_SLOT; | ||
370 | |||
371 | RIOReMapPorts(p, HostP, HostMapP ); | ||
372 | } | ||
373 | else { | ||
374 | rio_dprintk (RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) { | ||
379 | p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry]; | ||
380 | } | ||
381 | |||
382 | for ( Host=0; Host<p->RIONumHosts; Host++ ) { | ||
383 | for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) { | ||
384 | p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT; | ||
385 | p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK; | ||
386 | } | ||
387 | for ( Entry=0; Entry<MAX_RUP; Entry++ ) { | ||
388 | for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) { | ||
389 | p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = | ||
390 | ROUTE_DISCONNECT; | ||
391 | p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = | ||
392 | NO_LINK; | ||
393 | } | ||
394 | } | ||
395 | if ( !p->RIOHosts[Host].Name[0] ) { | ||
396 | bcopy("HOST 1",p->RIOHosts[Host].Name,7); | ||
397 | p->RIOHosts[Host].Name[5] += Host; | ||
398 | } | ||
399 | /* | ||
400 | ** Check that default name assigned is unique. | ||
401 | */ | ||
402 | Host1 = Host; | ||
403 | NameIsUnique = 0; | ||
404 | while (!NameIsUnique) { | ||
405 | NameIsUnique = 1; | ||
406 | for ( Host2=0; Host2<p->RIONumHosts; Host2++ ) { | ||
407 | if (Host2 == Host) | ||
408 | continue; | ||
409 | if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name) | ||
410 | == 0) { | ||
411 | NameIsUnique = 0; | ||
412 | Host1++; | ||
413 | if (Host1 >= p->RIONumHosts) | ||
414 | Host1 = 0; | ||
415 | p->RIOHosts[Host].Name[5] = '1' + Host1; | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | /* | ||
420 | ** Rename host if name already used. | ||
421 | */ | ||
422 | if (Host1 != Host) | ||
423 | { | ||
424 | rio_dprintk (RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name); | ||
425 | bcopy("HOST 1",p->RIOHosts[Host].Name,7); | ||
426 | p->RIOHosts[Host].Name[5] += Host1; | ||
427 | } | ||
428 | rio_dprintk (RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name); | ||
429 | } | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | /* | ||
434 | ** User process needs the config table - build it from first | ||
435 | ** principles. | ||
436 | */ | ||
437 | int | ||
438 | RIOApel(p) | ||
439 | struct rio_info * p; | ||
440 | { | ||
441 | int Host; | ||
442 | int link; | ||
443 | int Rup; | ||
444 | int Next = 0; | ||
445 | struct Map *MapP; | ||
446 | struct Host *HostP; | ||
447 | long oldspl; | ||
448 | |||
449 | disable(oldspl); /* strange but true! */ | ||
450 | |||
451 | rio_dprintk (RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n"); | ||
452 | |||
453 | bzero((caddr_t)&p->RIOConnectTable[0], | ||
454 | sizeof(struct Map) * TOTAL_MAP_ENTRIES ); | ||
455 | |||
456 | for ( Host=0; Host<RIO_HOSTS; Host++ ) { | ||
457 | rio_dprintk (RIO_DEBUG_TABLE, "Processing host %d\n", Host); | ||
458 | HostP = &p->RIOHosts[Host]; | ||
459 | MapP = &p->RIOConnectTable[Next++]; | ||
460 | MapP->HostUniqueNum = HostP->UniqueNum; | ||
461 | if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) | ||
462 | continue; | ||
463 | MapP->RtaUniqueNum = 0; | ||
464 | MapP->ID = 0; | ||
465 | MapP->Flags = SLOT_IN_USE; | ||
466 | MapP->SysPort = NO_PORT; | ||
467 | for ( link=0; link<LINKS_PER_UNIT; link++ ) | ||
468 | MapP->Topology[link] = HostP->Topology[link]; | ||
469 | bcopy(HostP->Name,MapP->Name,MAX_NAME_LEN); | ||
470 | for ( Rup=0; Rup<MAX_RUP; Rup++ ) { | ||
471 | if ( HostP->Mapping[Rup].Flags & (SLOT_IN_USE|SLOT_TENTATIVE) ) { | ||
472 | p->RIOConnectTable[Next] = HostP->Mapping[Rup]; | ||
473 | if ( HostP->Mapping[Rup].Flags & SLOT_IN_USE) | ||
474 | p->RIOConnectTable[Next].Flags |= SLOT_IN_USE; | ||
475 | if ( HostP->Mapping[Rup].Flags & SLOT_TENTATIVE) | ||
476 | p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE; | ||
477 | if ( HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT ) | ||
478 | p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT; | ||
479 | Next++; | ||
480 | } | ||
481 | } | ||
482 | } | ||
483 | restore(oldspl); | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | ** config.rio has taken a dislike to one of the gross maps entries. | ||
489 | ** if the entry is suitably inactive, then we can gob on it and remove | ||
490 | ** it from the table. | ||
491 | */ | ||
492 | int | ||
493 | RIODeleteRta(p, MapP) | ||
494 | struct rio_info *p; | ||
495 | struct Map *MapP; | ||
496 | { | ||
497 | int host, entry, port, link; | ||
498 | int SysPort; | ||
499 | struct Host *HostP; | ||
500 | struct Map *HostMapP; | ||
501 | struct Port *PortP; | ||
502 | int work_done = 0; | ||
503 | unsigned long lock_flags, sem_flags; | ||
504 | |||
505 | rio_dprintk (RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", | ||
506 | MapP->HostUniqueNum, MapP->RtaUniqueNum); | ||
507 | |||
508 | for ( host=0; host < p->RIONumHosts; host++ ) { | ||
509 | HostP = &p->RIOHosts[host]; | ||
510 | |||
511 | rio_spin_lock_irqsave( &HostP->HostLock, lock_flags ); | ||
512 | |||
513 | if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) { | ||
514 | rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); | ||
515 | continue; | ||
516 | } | ||
517 | |||
518 | for ( entry=0; entry<MAX_RUP; entry++ ) { | ||
519 | if ( MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum ) { | ||
520 | HostMapP = &HostP->Mapping[entry]; | ||
521 | rio_dprintk (RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", | ||
522 | entry, HostP->Name); | ||
523 | |||
524 | /* | ||
525 | ** Check all four links of the unit are disconnected | ||
526 | */ | ||
527 | for ( link=0; link< LINKS_PER_UNIT; link++ ) { | ||
528 | if ( HostMapP->Topology[link].Unit != ROUTE_DISCONNECT ) { | ||
529 | rio_dprintk (RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n"); | ||
530 | p->RIOError.Error = UNIT_IS_IN_USE; | ||
531 | rio_spin_unlock_irqrestore( &HostP->HostLock, lock_flags); | ||
532 | return -EBUSY; | ||
533 | } | ||
534 | } | ||
535 | /* | ||
536 | ** Slot has been allocated, BUT not booted/routed/ | ||
537 | ** connected/selected or anything else-ed | ||
538 | */ | ||
539 | SysPort = HostMapP->SysPort; | ||
540 | |||
541 | if ( SysPort != NO_PORT ) { | ||
542 | for (port=SysPort; port < SysPort+PORTS_PER_RTA; port++) { | ||
543 | PortP = p->RIOPortp[port]; | ||
544 | rio_dprintk (RIO_DEBUG_TABLE, "Unmap port\n"); | ||
545 | |||
546 | rio_spin_lock_irqsave( &PortP->portSem, sem_flags ); | ||
547 | |||
548 | PortP->Mapped = 0; | ||
549 | |||
550 | if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) { | ||
551 | |||
552 | rio_dprintk (RIO_DEBUG_TABLE, "Gob on port\n"); | ||
553 | PortP->TxBufferIn = PortP->TxBufferOut = 0; | ||
554 | /* What should I do | ||
555 | wakeup( &PortP->TxBufferIn ); | ||
556 | wakeup( &PortP->TxBufferOut); | ||
557 | */ | ||
558 | PortP->InUse = NOT_INUSE; | ||
559 | /* What should I do | ||
560 | wakeup( &PortP->InUse ); | ||
561 | signal(PortP->TtyP->t_pgrp,SIGKILL); | ||
562 | ttyflush(PortP->TtyP,(FREAD|FWRITE)); | ||
563 | */ | ||
564 | PortP->State |= RIO_CLOSING | RIO_DELETED; | ||
565 | } | ||
566 | |||
567 | /* | ||
568 | ** For the second slot of a 16 port RTA, the | ||
569 | ** driver needs to reset the changes made to | ||
570 | ** the phb to port mappings in RIORouteRup. | ||
571 | */ | ||
572 | if (PortP->SecondBlock) { | ||
573 | ushort dest_unit = HostMapP->ID; | ||
574 | ushort dest_port = port - SysPort; | ||
575 | WORD *TxPktP; | ||
576 | PKT *Pkt; | ||
577 | |||
578 | for (TxPktP = PortP->TxStart; | ||
579 | TxPktP <= PortP->TxEnd; TxPktP++) { | ||
580 | /* | ||
581 | ** *TxPktP is the pointer to the | ||
582 | ** transmit packet on the host card. | ||
583 | ** This needs to be translated into | ||
584 | ** a 32 bit pointer so it can be | ||
585 | ** accessed from the driver. | ||
586 | */ | ||
587 | Pkt = (PKT *) RIO_PTR(HostP->Caddr, | ||
588 | RWORD(*TxPktP)); | ||
589 | rio_dprintk (RIO_DEBUG_TABLE, | ||
590 | "Tx packet (%x) destination: Old %x:%x New %x:%x\n", | ||
591 | *TxPktP, Pkt->dest_unit, | ||
592 | Pkt->dest_port, dest_unit, dest_port); | ||
593 | WWORD(Pkt->dest_unit, dest_unit); | ||
594 | WWORD(Pkt->dest_port, dest_port); | ||
595 | } | ||
596 | rio_dprintk (RIO_DEBUG_TABLE, | ||
597 | "Port %d phb destination: Old %x:%x New %x:%x\n", | ||
598 | port, PortP->PhbP->destination & 0xff, | ||
599 | (PortP->PhbP->destination >> 8) & 0xff, | ||
600 | dest_unit, dest_port); | ||
601 | WWORD(PortP->PhbP->destination, | ||
602 | dest_unit + (dest_port << 8)); | ||
603 | } | ||
604 | rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags); | ||
605 | } | ||
606 | } | ||
607 | rio_dprintk (RIO_DEBUG_TABLE, "Entry nulled.\n"); | ||
608 | bzero((char *)HostMapP,sizeof(struct Map)); | ||
609 | work_done++; | ||
610 | } | ||
611 | } | ||
612 | rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags); | ||
613 | } | ||
614 | |||
615 | /* XXXXX lock me up */ | ||
616 | for ( entry=0; entry< TOTAL_MAP_ENTRIES; entry++ ) { | ||
617 | if ( p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) { | ||
618 | bzero((char *)&p->RIOSavedTable[entry],sizeof(struct Map)); | ||
619 | work_done++; | ||
620 | } | ||
621 | if ( p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) { | ||
622 | bzero((char *)&p->RIOConnectTable[entry],sizeof(struct Map)); | ||
623 | work_done++; | ||
624 | } | ||
625 | } | ||
626 | if ( work_done ) | ||
627 | return 0; | ||
628 | |||
629 | rio_dprintk (RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n"); | ||
630 | p->RIOError.Error = COULDNT_FIND_ENTRY; | ||
631 | return -ENXIO; | ||
632 | } | ||
633 | |||
634 | int RIOAssignRta( struct rio_info *p, struct Map *MapP ) | ||
635 | { | ||
636 | int host; | ||
637 | struct Map *HostMapP; | ||
638 | char *sptr; | ||
639 | int link; | ||
640 | |||
641 | |||
642 | rio_dprintk (RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", | ||
643 | MapP->HostUniqueNum,MapP->RtaUniqueNum, | ||
644 | MapP->ID, (int)MapP->SysPort); | ||
645 | |||
646 | if ((MapP->ID != (ushort)-1) && | ||
647 | ((int)MapP->ID < (int)1 || (int)MapP->ID > MAX_RUP )) | ||
648 | { | ||
649 | rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); | ||
650 | p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; | ||
651 | return -EINVAL; | ||
652 | } | ||
653 | if (MapP->RtaUniqueNum == 0) | ||
654 | { | ||
655 | rio_dprintk (RIO_DEBUG_TABLE, "Rta Unique number zero!\n"); | ||
656 | p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO; | ||
657 | return -EINVAL; | ||
658 | } | ||
659 | if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA) ) | ||
660 | { | ||
661 | rio_dprintk (RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n",(int)MapP->SysPort,PORTS_PER_RTA); | ||
662 | p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; | ||
663 | return -EINVAL; | ||
664 | } | ||
665 | if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS) ) | ||
666 | { | ||
667 | rio_dprintk (RIO_DEBUG_TABLE, "Port %d not valid!\n",(int)MapP->SysPort); | ||
668 | p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE; | ||
669 | return -EINVAL; | ||
670 | } | ||
671 | |||
672 | /* | ||
673 | ** Copy the name across to the map entry. | ||
674 | */ | ||
675 | MapP->Name[MAX_NAME_LEN-1] = '\0'; | ||
676 | sptr = MapP->Name; | ||
677 | while ( *sptr ) | ||
678 | { | ||
679 | if ( *sptr<' ' || *sptr>'~' ) | ||
680 | { | ||
681 | rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); | ||
682 | p->RIOError.Error = BAD_CHARACTER_IN_NAME; | ||
683 | return -EINVAL; | ||
684 | } | ||
685 | sptr++; | ||
686 | } | ||
687 | |||
688 | for ( host=0; host < p->RIONumHosts; host++ ) | ||
689 | { | ||
690 | if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum ) | ||
691 | { | ||
692 | if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING ) | ||
693 | { | ||
694 | p->RIOError.Error = HOST_NOT_RUNNING; | ||
695 | return -ENXIO; | ||
696 | } | ||
697 | |||
698 | /* | ||
699 | ** Now we have a host we need to allocate an ID | ||
700 | ** if the entry does not already have one. | ||
701 | */ | ||
702 | if (MapP->ID == (ushort)-1) | ||
703 | { | ||
704 | int nNewID; | ||
705 | |||
706 | rio_dprintk (RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", | ||
707 | MapP->Name); | ||
708 | /* | ||
709 | ** The idea here is to allow RTA's to be assigned | ||
710 | ** before they actually appear on the network. | ||
711 | ** This allows the addition of RTA's without having | ||
712 | ** to plug them in. | ||
713 | ** What we do is: | ||
714 | ** - Find a free ID and allocate it to the RTA. | ||
715 | ** - If this map entry is the second half of a | ||
716 | ** 16 port entry then find the other half and | ||
717 | ** make sure the 2 cross reference each other. | ||
718 | */ | ||
719 | if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) | ||
720 | { | ||
721 | p->RIOError.Error = COULDNT_FIND_ENTRY; | ||
722 | return -EBUSY; | ||
723 | } | ||
724 | MapP->ID = (ushort)nNewID + 1; | ||
725 | rio_dprintk (RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID); | ||
726 | HostMapP = &p->RIOHosts[host].Mapping[nNewID]; | ||
727 | HostMapP->RtaUniqueNum = MapP->RtaUniqueNum; | ||
728 | HostMapP->HostUniqueNum = MapP->HostUniqueNum; | ||
729 | HostMapP->ID = MapP->ID; | ||
730 | for (link = 0; link < LINKS_PER_UNIT; link++) | ||
731 | { | ||
732 | HostMapP->Topology[link].Unit = ROUTE_DISCONNECT; | ||
733 | HostMapP->Topology[link].Link = NO_LINK; | ||
734 | } | ||
735 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
736 | { | ||
737 | int unit; | ||
738 | |||
739 | for (unit = 0; unit < MAX_RUP; unit++) | ||
740 | if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == | ||
741 | MapP->RtaUniqueNum) | ||
742 | break; | ||
743 | if (unit == MAX_RUP) | ||
744 | { | ||
745 | p->RIOError.Error = COULDNT_FIND_ENTRY; | ||
746 | return -EBUSY; | ||
747 | } | ||
748 | HostMapP->Flags |= RTA16_SECOND_SLOT; | ||
749 | HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID; | ||
750 | p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID; | ||
751 | rio_dprintk (RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", | ||
752 | MapP->ID, | ||
753 | p->RIOHosts[host].Mapping[unit].ID); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1]; | ||
758 | |||
759 | if ( HostMapP->Flags & SLOT_IN_USE ) | ||
760 | { | ||
761 | rio_dprintk (RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID); | ||
762 | p->RIOError.Error = ID_ALREADY_IN_USE; | ||
763 | return -EBUSY; | ||
764 | } | ||
765 | |||
766 | /* | ||
767 | ** Assign the sys ports and the name, and mark the slot as | ||
768 | ** being in use. | ||
769 | */ | ||
770 | HostMapP->SysPort = MapP->SysPort; | ||
771 | if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) | ||
772 | CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN ); | ||
773 | HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED; | ||
774 | #if NEED_TO_FIX | ||
775 | RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID-1]); | ||
776 | #endif | ||
777 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
778 | HostMapP->Flags |= RTA16_SECOND_SLOT; | ||
779 | |||
780 | RIOReMapPorts( p, &p->RIOHosts[host], HostMapP ); | ||
781 | /* | ||
782 | ** Adjust 2nd block of 8 phbs | ||
783 | */ | ||
784 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
785 | RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1); | ||
786 | |||
787 | if ( HostMapP->SysPort != NO_PORT ) | ||
788 | { | ||
789 | if ( HostMapP->SysPort < p->RIOFirstPortsBooted ) | ||
790 | p->RIOFirstPortsBooted = HostMapP->SysPort; | ||
791 | if ( HostMapP->SysPort > p->RIOLastPortsBooted ) | ||
792 | p->RIOLastPortsBooted = HostMapP->SysPort; | ||
793 | } | ||
794 | if (MapP->Flags & RTA16_SECOND_SLOT) | ||
795 | rio_dprintk (RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", | ||
796 | p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name); | ||
797 | else | ||
798 | rio_dprintk (RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name); | ||
799 | return 0; | ||
800 | } | ||
801 | } | ||
802 | p->RIOError.Error = UNKNOWN_HOST_NUMBER; | ||
803 | rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum); | ||
804 | return -ENXIO; | ||
805 | } | ||
806 | |||
807 | |||
808 | int | ||
809 | RIOReMapPorts(p, HostP, HostMapP) | ||
810 | struct rio_info * p; | ||
811 | struct Host *HostP; | ||
812 | struct Map *HostMapP; | ||
813 | { | ||
814 | register struct Port *PortP; | ||
815 | uint SubEnt; | ||
816 | uint HostPort; | ||
817 | uint SysPort; | ||
818 | ushort RtaType; | ||
819 | unsigned long flags; | ||
820 | |||
821 | #ifdef CHECK | ||
822 | CheckHostP( HostP ); | ||
823 | CheckHostMapP( HostMapP ); | ||
824 | #endif | ||
825 | |||
826 | rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int)HostMapP->SysPort, HostMapP->ID); | ||
827 | |||
828 | /* | ||
829 | ** We need to tell the UnixRups which sysport the rup corresponds to | ||
830 | */ | ||
831 | HostP->UnixRups[HostMapP->ID-1].BaseSysPort = HostMapP->SysPort; | ||
832 | |||
833 | if ( HostMapP->SysPort == NO_PORT ) | ||
834 | return(0); | ||
835 | |||
836 | RtaType = GetUnitType(HostMapP->RtaUniqueNum); | ||
837 | rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", | ||
838 | (int)HostMapP->SysPort, (int)HostMapP->SysPort+PORTS_PER_RTA-1); | ||
839 | |||
840 | /* | ||
841 | ** now map each of its eight ports | ||
842 | */ | ||
843 | for ( SubEnt=0; SubEnt<PORTS_PER_RTA; SubEnt++) { | ||
844 | rio_dprintk (RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", | ||
845 | SubEnt, (int)HostMapP->SysPort); | ||
846 | SysPort = HostMapP->SysPort+SubEnt; /* portnumber within system */ | ||
847 | /* portnumber on host */ | ||
848 | |||
849 | HostPort = (HostMapP->ID-1)*PORTS_PER_RTA+SubEnt; | ||
850 | |||
851 | rio_dprintk (RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp); | ||
852 | PortP = p->RIOPortp[SysPort]; | ||
853 | #if 0 | ||
854 | PortP->TtyP = &p->channel[SysPort]; | ||
855 | #endif | ||
856 | rio_dprintk (RIO_DEBUG_TABLE, "Map port\n"); | ||
857 | |||
858 | /* | ||
859 | ** Point at all the real neat data structures | ||
860 | */ | ||
861 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
862 | PortP->HostP = HostP; | ||
863 | PortP->Caddr = HostP->Caddr; | ||
864 | |||
865 | /* | ||
866 | ** The PhbP cannot be filled in yet | ||
867 | ** unless the host has been booted | ||
868 | */ | ||
869 | if ((HostP->Flags & RUN_STATE) == RC_RUNNING) { | ||
870 | struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort]; | ||
871 | PortP->TxAdd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_add)); | ||
872 | PortP->TxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_start)); | ||
873 | PortP->TxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_end)); | ||
874 | PortP->RxRemove=(WORD *)RIO_PTR(HostP->Caddr, | ||
875 | RWORD(PhbP->rx_remove)); | ||
876 | PortP->RxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_start)); | ||
877 | PortP->RxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_end)); | ||
878 | } | ||
879 | else | ||
880 | PortP->PhbP = NULL; | ||
881 | |||
882 | /* | ||
883 | ** port related flags | ||
884 | */ | ||
885 | PortP->HostPort = HostPort; | ||
886 | /* | ||
887 | ** For each part of a 16 port RTA, RupNum is ID - 1. | ||
888 | */ | ||
889 | PortP->RupNum = HostMapP->ID - 1; | ||
890 | if (HostMapP->Flags & RTA16_SECOND_SLOT) { | ||
891 | PortP->ID2 = HostMapP->ID2 - 1; | ||
892 | PortP->SecondBlock = TRUE; | ||
893 | } | ||
894 | else { | ||
895 | PortP->ID2 = 0; | ||
896 | PortP->SecondBlock = FALSE; | ||
897 | } | ||
898 | PortP->RtaUniqueNum = HostMapP->RtaUniqueNum; | ||
899 | |||
900 | /* | ||
901 | ** If the port was already mapped then thats all we need to do. | ||
902 | */ | ||
903 | if (PortP->Mapped) { | ||
904 | rio_spin_unlock_irqrestore( &PortP->portSem, flags); | ||
905 | continue; | ||
906 | } | ||
907 | else HostMapP->Flags &= ~RTA_NEWBOOT; | ||
908 | |||
909 | PortP->State = 0; | ||
910 | PortP->Config = 0; | ||
911 | /* | ||
912 | ** Check out the module type - if it is special (read only etc.) | ||
913 | ** then we need to set flags in the PortP->Config. | ||
914 | ** Note: For 16 port RTA, all ports are of the same type. | ||
915 | */ | ||
916 | if (RtaType == TYPE_RTA16) { | ||
917 | PortP->Config |= p->RIOModuleTypes[HostP->UnixRups | ||
918 | [HostMapP->ID-1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE]; | ||
919 | } else { | ||
920 | if ( SubEnt < PORTS_PER_MODULE ) | ||
921 | PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups | ||
922 | [HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE]; | ||
923 | else | ||
924 | PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups | ||
925 | [HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE]; | ||
926 | } | ||
927 | |||
928 | /* | ||
929 | ** more port related flags | ||
930 | */ | ||
931 | PortP->PortState = 0; | ||
932 | PortP->ModemLines = 0; | ||
933 | PortP->ModemState = 0; | ||
934 | PortP->CookMode = COOK_WELL; | ||
935 | PortP->ParamSem = 0; | ||
936 | PortP->FlushCmdBodge= 0; | ||
937 | PortP->WflushFlag = 0; | ||
938 | PortP->MagicFlags = 0; | ||
939 | PortP->Lock = 0; | ||
940 | PortP->Store = 0; | ||
941 | PortP->FirstOpen = 1; | ||
942 | |||
943 | /* | ||
944 | ** Buffers 'n things | ||
945 | */ | ||
946 | PortP->RxDataStart = 0; | ||
947 | PortP->Cor2Copy = 0; | ||
948 | PortP->Name = &HostMapP->Name[0]; | ||
949 | #ifdef STATS | ||
950 | bzero( (caddr_t)&PortP->Stat, sizeof(struct RIOStats) ); | ||
951 | #endif | ||
952 | PortP->statsGather = 0; | ||
953 | PortP->txchars = 0; | ||
954 | PortP->rxchars = 0; | ||
955 | PortP->opens = 0; | ||
956 | PortP->closes = 0; | ||
957 | PortP->ioctls = 0; | ||
958 | if ( PortP->TxRingBuffer ) | ||
959 | bzero( PortP->TxRingBuffer, p->RIOBufferSize ); | ||
960 | else if ( p->RIOBufferSize ) { | ||
961 | PortP->TxRingBuffer = sysbrk(p->RIOBufferSize); | ||
962 | bzero( PortP->TxRingBuffer, p->RIOBufferSize ); | ||
963 | } | ||
964 | PortP->TxBufferOut = 0; | ||
965 | PortP->TxBufferIn = 0; | ||
966 | PortP->Debug = 0; | ||
967 | /* | ||
968 | ** LastRxTgl stores the state of the rx toggle bit for this | ||
969 | ** port, to be compared with the state of the next pkt received. | ||
970 | ** If the same, we have received the same rx pkt from the RTA | ||
971 | ** twice. Initialise to a value not equal to PHB_RX_TGL or 0. | ||
972 | */ | ||
973 | PortP->LastRxTgl = ~(uchar)PHB_RX_TGL; | ||
974 | |||
975 | /* | ||
976 | ** and mark the port as usable | ||
977 | */ | ||
978 | PortP->Mapped = 1; | ||
979 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
980 | } | ||
981 | if ( HostMapP->SysPort < p->RIOFirstPortsMapped ) | ||
982 | p->RIOFirstPortsMapped = HostMapP->SysPort; | ||
983 | if ( HostMapP->SysPort > p->RIOLastPortsMapped ) | ||
984 | p->RIOLastPortsMapped = HostMapP->SysPort; | ||
985 | |||
986 | return 0; | ||
987 | } | ||
988 | |||
989 | int | ||
990 | RIOChangeName(p, MapP) | ||
991 | struct rio_info *p; | ||
992 | struct Map* MapP; | ||
993 | { | ||
994 | int host; | ||
995 | struct Map *HostMapP; | ||
996 | char *sptr; | ||
997 | |||
998 | rio_dprintk (RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", | ||
999 | MapP->HostUniqueNum,MapP->RtaUniqueNum, | ||
1000 | MapP->ID, (int)MapP->SysPort); | ||
1001 | |||
1002 | if ( MapP->ID > MAX_RUP ) { | ||
1003 | rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n"); | ||
1004 | p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE; | ||
1005 | return -EINVAL; | ||
1006 | } | ||
1007 | |||
1008 | MapP->Name[MAX_NAME_LEN-1] = '\0'; | ||
1009 | sptr = MapP->Name; | ||
1010 | |||
1011 | while ( *sptr ) { | ||
1012 | if ( *sptr<' ' || *sptr>'~' ) { | ||
1013 | rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n"); | ||
1014 | p->RIOError.Error = BAD_CHARACTER_IN_NAME; | ||
1015 | return -EINVAL; | ||
1016 | } | ||
1017 | sptr++; | ||
1018 | } | ||
1019 | |||
1020 | for ( host=0; host < p->RIONumHosts; host++ ) { | ||
1021 | if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum ) { | ||
1022 | if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING ) { | ||
1023 | p->RIOError.Error = HOST_NOT_RUNNING; | ||
1024 | return -ENXIO; | ||
1025 | } | ||
1026 | if ( MapP->ID==0 ) { | ||
1027 | CCOPY( MapP->Name, p->RIOHosts[host].Name, MAX_NAME_LEN ); | ||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1]; | ||
1032 | |||
1033 | if ( HostMapP->RtaUniqueNum != MapP->RtaUniqueNum ) { | ||
1034 | p->RIOError.Error = RTA_NUMBER_WRONG; | ||
1035 | return -ENXIO; | ||
1036 | } | ||
1037 | CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN ); | ||
1038 | return 0; | ||
1039 | } | ||
1040 | } | ||
1041 | p->RIOError.Error = UNKNOWN_HOST_NUMBER; | ||
1042 | rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum); | ||
1043 | return -ENXIO; | ||
1044 | } | ||
diff --git a/drivers/char/rio/riotime.h b/drivers/char/rio/riotime.h new file mode 100644 index 000000000000..66d52bc0549b --- /dev/null +++ b/drivers/char/rio/riotime.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* T I M E | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | |||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | |||
28 | Version : 0.01 | ||
29 | |||
30 | |||
31 | Mods | ||
32 | ---------------------------------------------------------------------------- | ||
33 | Date By Description | ||
34 | ---------------------------------------------------------------------------- | ||
35 | |||
36 | ***************************************************************************/ | ||
37 | |||
38 | #ifndef _riotime_h | ||
39 | #define _riotime_h 1 | ||
40 | |||
41 | #ifndef lint | ||
42 | #ifdef SCCS | ||
43 | static char *_rio_riotime_h_sccs = "@(#)riotime.h 1.1" ; | ||
44 | #endif | ||
45 | #endif | ||
46 | |||
47 | #define TWO_POWER_FIFTEEN (ushort)32768 | ||
48 | #define RioTime() riotime | ||
49 | #define RioTimeAfter(time1,time2) ((ushort)time1 - (ushort)time2) < TWO_POWER_FIFTEEN | ||
50 | #define RioTimePlus(time1,time2) ((ushort)time1 + (ushort)time2) | ||
51 | |||
52 | /************************************** | ||
53 | * Convert a RIO tick (1/10th second) | ||
54 | * into transputer low priority ticks | ||
55 | *************************************/ | ||
56 | #define RioTimeToLow(time) (time*(100000 / 64)) | ||
57 | #define RioLowToTime(time) ((time*64)/100000) | ||
58 | |||
59 | #define RIOTENTHSECOND (ushort)1 | ||
60 | #define RIOSECOND (ushort)(RIOTENTHSECOND * 10) | ||
61 | #endif | ||
62 | |||
63 | /*********** end of file ***********/ | ||
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c new file mode 100644 index 000000000000..db655002671f --- /dev/null +++ b/drivers/char/rio/riotty.c | |||
@@ -0,0 +1,1376 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : riotty.c | ||
24 | ** SID : 1.3 | ||
25 | ** Last Modified : 11/6/98 10:33:47 | ||
26 | ** Retrieved : 11/6/98 10:33:50 | ||
27 | ** | ||
28 | ** ident @(#)riotty.c 1.3 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | #ifdef SCCS_LABELS | ||
33 | static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3"; | ||
34 | #endif | ||
35 | |||
36 | |||
37 | #define __EXPLICIT_DEF_H__ | ||
38 | |||
39 | #include <linux/module.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/errno.h> | ||
42 | #include <linux/tty.h> | ||
43 | #include <linux/string.h> | ||
44 | #include <asm/io.h> | ||
45 | #include <asm/system.h> | ||
46 | #include <asm/string.h> | ||
47 | #include <asm/semaphore.h> | ||
48 | #include <asm/uaccess.h> | ||
49 | |||
50 | #include <linux/termios.h> | ||
51 | |||
52 | #include <linux/serial.h> | ||
53 | |||
54 | #include <linux/generic_serial.h> | ||
55 | |||
56 | |||
57 | #include "linux_compat.h" | ||
58 | #include "rio_linux.h" | ||
59 | #include "typdef.h" | ||
60 | #include "pkt.h" | ||
61 | #include "daemon.h" | ||
62 | #include "rio.h" | ||
63 | #include "riospace.h" | ||
64 | #include "top.h" | ||
65 | #include "cmdpkt.h" | ||
66 | #include "map.h" | ||
67 | #include "riotypes.h" | ||
68 | #include "rup.h" | ||
69 | #include "port.h" | ||
70 | #include "riodrvr.h" | ||
71 | #include "rioinfo.h" | ||
72 | #include "func.h" | ||
73 | #include "errors.h" | ||
74 | #include "pci.h" | ||
75 | |||
76 | #include "parmmap.h" | ||
77 | #include "unixrup.h" | ||
78 | #include "board.h" | ||
79 | #include "host.h" | ||
80 | #include "error.h" | ||
81 | #include "phb.h" | ||
82 | #include "link.h" | ||
83 | #include "cmdblk.h" | ||
84 | #include "route.h" | ||
85 | #include "control.h" | ||
86 | #include "cirrus.h" | ||
87 | #include "rioioctl.h" | ||
88 | #include "param.h" | ||
89 | #include "list.h" | ||
90 | #include "sam.h" | ||
91 | |||
92 | #if 0 | ||
93 | static void ttyseth_pv(struct Port *, struct ttystatics *, | ||
94 | struct termios *sg, int); | ||
95 | #endif | ||
96 | |||
97 | static void RIOClearUp(struct Port *PortP); | ||
98 | int RIOShortCommand(struct rio_info *p, struct Port *PortP, | ||
99 | int command, int len, int arg); | ||
100 | |||
101 | #if 0 | ||
102 | static int RIOCookMode(struct ttystatics *); | ||
103 | #endif | ||
104 | |||
105 | extern int conv_vb[]; /* now defined in ttymgr.c */ | ||
106 | extern int conv_bv[]; /* now defined in ttymgr.c */ | ||
107 | |||
108 | /* | ||
109 | ** 16.09.1998 ARG - Fix to build riotty.k.o for Modular Kernel Support | ||
110 | ** | ||
111 | ** ep.def.h is necessary for Modular Kernel Support | ||
112 | ** DO NOT place any kernel 'extern's after this line | ||
113 | ** or this source file will not build riotty.k.o | ||
114 | */ | ||
115 | #ifdef uLYNX | ||
116 | #include <ep.def.h> | ||
117 | #endif | ||
118 | |||
119 | #ifdef NEED_THIS2 | ||
120 | static struct old_sgttyb | ||
121 | default_sg = | ||
122 | { | ||
123 | B19200, B19200, /* input and output speed */ | ||
124 | 'H' - '@', /* erase char */ | ||
125 | -1, /* 2nd erase char */ | ||
126 | 'U' - '@', /* kill char */ | ||
127 | ECHO | CRMOD, /* mode */ | ||
128 | 'C' - '@', /* interrupt character */ | ||
129 | '\\' - '@', /* quit char */ | ||
130 | 'Q' - '@', /* start char */ | ||
131 | 'S' - '@', /* stop char */ | ||
132 | 'D' - '@', /* EOF */ | ||
133 | -1, /* brk */ | ||
134 | (LCRTBS | LCRTERA | LCRTKIL | LCTLECH), /* local mode word */ | ||
135 | 'Z' - '@', /* process stop */ | ||
136 | 'Y' - '@', /* delayed stop */ | ||
137 | 'R' - '@', /* reprint line */ | ||
138 | 'O' - '@', /* flush output */ | ||
139 | 'W' - '@', /* word erase */ | ||
140 | 'V' - '@' /* literal next char */ | ||
141 | }; | ||
142 | #endif | ||
143 | |||
144 | |||
145 | extern struct rio_info *p; | ||
146 | |||
147 | |||
148 | int | ||
149 | riotopen(struct tty_struct * tty, struct file * filp) | ||
150 | { | ||
151 | register uint SysPort; | ||
152 | int Modem; | ||
153 | int repeat_this = 250; | ||
154 | struct Port *PortP; /* pointer to the port structure */ | ||
155 | unsigned long flags; | ||
156 | int retval = 0; | ||
157 | |||
158 | func_enter (); | ||
159 | |||
160 | /* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close | ||
161 | is going to oops. | ||
162 | */ | ||
163 | tty->driver_data = NULL; | ||
164 | |||
165 | SysPort = rio_minor(tty); | ||
166 | Modem = rio_ismodem(tty); | ||
167 | |||
168 | if ( p->RIOFailed ) { | ||
169 | rio_dprintk (RIO_DEBUG_TTY, "System initialisation failed\n"); | ||
170 | pseterr(ENXIO); | ||
171 | func_exit (); | ||
172 | return -ENXIO; | ||
173 | } | ||
174 | |||
175 | rio_dprintk (RIO_DEBUG_TTY, "port open SysPort %d (%s) (mapped:%d)\n", | ||
176 | SysPort, Modem ? "Modem" : "tty", | ||
177 | p->RIOPortp[SysPort]->Mapped); | ||
178 | |||
179 | /* | ||
180 | ** Validate that we have received a legitimate request. | ||
181 | ** Currently, just check that we are opening a port on | ||
182 | ** a host card that actually exists, and that the port | ||
183 | ** has been mapped onto a host. | ||
184 | */ | ||
185 | if (SysPort >= RIO_PORTS) { /* out of range ? */ | ||
186 | rio_dprintk (RIO_DEBUG_TTY, "Illegal port number %d\n",SysPort); | ||
187 | pseterr(ENXIO); | ||
188 | func_exit(); | ||
189 | return -ENXIO; | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | ** Grab pointer to the port stucture | ||
194 | */ | ||
195 | PortP = p->RIOPortp[SysPort]; /* Get control struc */ | ||
196 | rio_dprintk (RIO_DEBUG_TTY, "PortP: %p\n", PortP); | ||
197 | if ( !PortP->Mapped ) { /* we aren't mapped yet! */ | ||
198 | /* | ||
199 | ** The system doesn't know which RTA this port | ||
200 | ** corresponds to. | ||
201 | */ | ||
202 | rio_dprintk (RIO_DEBUG_TTY, "port not mapped into system\n"); | ||
203 | func_exit (); | ||
204 | pseterr(ENXIO); | ||
205 | return -ENXIO; | ||
206 | } | ||
207 | |||
208 | tty->driver_data = PortP; | ||
209 | |||
210 | PortP->gs.tty = tty; | ||
211 | PortP->gs.count++; | ||
212 | |||
213 | rio_dprintk (RIO_DEBUG_TTY, "%d bytes in tx buffer\n", | ||
214 | PortP->gs.xmit_cnt); | ||
215 | |||
216 | retval = gs_init_port (&PortP->gs); | ||
217 | if (retval) { | ||
218 | PortP->gs.count--; | ||
219 | return -ENXIO; | ||
220 | } | ||
221 | /* | ||
222 | ** If the host hasn't been booted yet, then | ||
223 | ** fail | ||
224 | */ | ||
225 | if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) { | ||
226 | rio_dprintk (RIO_DEBUG_TTY, "Host not running\n"); | ||
227 | pseterr(ENXIO); | ||
228 | func_exit (); | ||
229 | return -ENXIO; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | ** If the RTA has not booted yet and the user has choosen to block | ||
234 | ** until the RTA is present then we must spin here waiting for | ||
235 | ** the RTA to boot. | ||
236 | */ | ||
237 | #if 0 | ||
238 | if (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) { | ||
239 | if (PortP->WaitUntilBooted) { | ||
240 | rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot\n"); | ||
241 | do { | ||
242 | if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { | ||
243 | rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n"); | ||
244 | func_exit (); | ||
245 | return -EINTR; | ||
246 | } | ||
247 | if (repeat_this -- <= 0) { | ||
248 | rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n"); | ||
249 | RIOPreemptiveCmd(p, PortP, FCLOSE ); | ||
250 | pseterr(EINTR); | ||
251 | func_exit (); | ||
252 | return -EIO; | ||
253 | } | ||
254 | } while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)); | ||
255 | rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n"); | ||
256 | } else { | ||
257 | rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n"); | ||
258 | pseterr(ENXIO); | ||
259 | func_exit (); | ||
260 | return 0; | ||
261 | } | ||
262 | } | ||
263 | #else | ||
264 | /* I find the above code a bit hairy. I find the below code | ||
265 | easier to read and shorter. Now, if it works too that would | ||
266 | be great... -- REW | ||
267 | */ | ||
268 | rio_dprintk (RIO_DEBUG_TTY, "Checking if RTA has booted... \n"); | ||
269 | while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) { | ||
270 | if (!PortP->WaitUntilBooted) { | ||
271 | rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n"); | ||
272 | func_exit (); | ||
273 | return -ENXIO; | ||
274 | } | ||
275 | |||
276 | /* Under Linux you'd normally use a wait instead of this | ||
277 | busy-waiting. I'll stick with the old implementation for | ||
278 | now. --REW | ||
279 | */ | ||
280 | if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { | ||
281 | rio_dprintk (RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n"); | ||
282 | func_exit (); | ||
283 | return -EINTR; | ||
284 | } | ||
285 | if (repeat_this -- <= 0) { | ||
286 | rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n"); | ||
287 | func_exit (); | ||
288 | return -EIO; | ||
289 | } | ||
290 | } | ||
291 | rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n"); | ||
292 | #endif | ||
293 | #if 0 | ||
294 | tp = PortP->TtyP; /* get tty struct */ | ||
295 | #endif | ||
296 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
297 | if ( p->RIOHalted ) { | ||
298 | goto bombout; | ||
299 | } | ||
300 | #if 0 | ||
301 | retval = gs_init_port(&PortP->gs); | ||
302 | if (retval){ | ||
303 | func_exit (); | ||
304 | return retval; | ||
305 | } | ||
306 | #endif | ||
307 | |||
308 | /* | ||
309 | ** If the port is in the final throws of being closed, | ||
310 | ** we should wait here (politely), waiting | ||
311 | ** for it to finish, so that it doesn't close us! | ||
312 | */ | ||
313 | while ( (PortP->State & RIO_CLOSING) && !p->RIOHalted ) { | ||
314 | rio_dprintk (RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n"); | ||
315 | if (repeat_this -- <= 0) { | ||
316 | rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); | ||
317 | RIOPreemptiveCmd(p, PortP, FCLOSE ); | ||
318 | retval = -EINTR; | ||
319 | goto bombout; | ||
320 | } | ||
321 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
322 | if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { | ||
323 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
324 | retval = -EINTR; | ||
325 | goto bombout; | ||
326 | } | ||
327 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
328 | } | ||
329 | |||
330 | if ( !PortP->Mapped ) { | ||
331 | rio_dprintk (RIO_DEBUG_TTY, "Port unmapped while closing!\n"); | ||
332 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
333 | retval = -ENXIO; | ||
334 | func_exit (); | ||
335 | return retval; | ||
336 | } | ||
337 | |||
338 | if ( p->RIOHalted ) { | ||
339 | goto bombout; | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | ** 15.10.1998 ARG - ESIL 0761 part fix | ||
344 | ** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure, | ||
345 | ** we need to make sure that the flags are clear when the port is opened. | ||
346 | */ | ||
347 | /* Uh? Suppose I turn these on and then another process opens | ||
348 | the port again? The flags get cleared! Not good. -- REW */ | ||
349 | if ( !(PortP->State & (RIO_LOPEN | RIO_MOPEN)) ) { | ||
350 | PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW); | ||
351 | } | ||
352 | |||
353 | if (!(PortP->firstOpen)) { /* First time ? */ | ||
354 | rio_dprintk (RIO_DEBUG_TTY, "First open for this port\n"); | ||
355 | |||
356 | |||
357 | PortP->firstOpen++; | ||
358 | PortP->CookMode = 0; /* XXX RIOCookMode(tp); */ | ||
359 | PortP->InUse = NOT_INUSE; | ||
360 | |||
361 | /* Tentative fix for bug PR27. Didn't work. */ | ||
362 | /* PortP->gs.xmit_cnt = 0; */ | ||
363 | |||
364 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
365 | #ifdef NEED_THIS | ||
366 | ttyseth(PortP, tp, (struct old_sgttyb *)&default_sg); | ||
367 | #endif | ||
368 | |||
369 | /* Someone explain to me why this delay/config is | ||
370 | here. If I read the docs correctly the "open" | ||
371 | command piggybacks the parameters immediately. | ||
372 | -- REW */ | ||
373 | RIOParam(PortP,OPEN,Modem,OK_TO_SLEEP); /* Open the port */ | ||
374 | #if 0 | ||
375 | /* This delay of 1 second was annoying. I removed it. -- REW */ | ||
376 | RIODelay(PortP, HUNDRED_MS*10); | ||
377 | RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); /* Config the port */ | ||
378 | #endif | ||
379 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
380 | |||
381 | /* | ||
382 | ** wait for the port to be not closed. | ||
383 | */ | ||
384 | while ( !(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted ) { | ||
385 | rio_dprintk (RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n",PortP->PortState); | ||
386 | /* | ||
387 | ** 15.10.1998 ARG - ESIL 0759 | ||
388 | ** (Part) fix for port being trashed when opened whilst RTA "disconnected" | ||
389 | ** Take out the limited wait - now wait for ever or until user | ||
390 | ** bangs us out. | ||
391 | ** | ||
392 | if (repeat_this -- <= 0) { | ||
393 | rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish timed out.\n")); | ||
394 | RIOPreemptiveCmd(p, PortP, FCLOSE ); | ||
395 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
396 | return -EINTR; | ||
397 | } | ||
398 | ** | ||
399 | */ | ||
400 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
401 | if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { | ||
402 | rio_dprintk (RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n"); | ||
403 | RIOPreemptiveCmd(p, PortP, FCLOSE ); | ||
404 | func_exit (); | ||
405 | return -EINTR; | ||
406 | } | ||
407 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
408 | } | ||
409 | |||
410 | if ( p->RIOHalted ) { | ||
411 | retval = -EIO; | ||
412 | bombout: | ||
413 | /* RIOClearUp( PortP ); */ | ||
414 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
415 | return retval; | ||
416 | } | ||
417 | rio_dprintk (RIO_DEBUG_TTY, "PORT_ISOPEN found\n"); | ||
418 | } | ||
419 | |||
420 | #ifdef MODEM_SUPPORT | ||
421 | if (Modem) { | ||
422 | rio_dprintk (RIO_DEBUG_TTY, "Modem - test for carrier\n"); | ||
423 | /* | ||
424 | ** ACTION | ||
425 | ** insert test for carrier here. -- ??? | ||
426 | ** I already see that test here. What's the deal? -- REW | ||
427 | */ | ||
428 | if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) | ||
429 | { | ||
430 | rio_dprintk (RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort); | ||
431 | /* | ||
432 | tp->tm.c_state |= CARR_ON; | ||
433 | wakeup((caddr_t) &tp->tm.c_canq); | ||
434 | */ | ||
435 | PortP->State |= RIO_CARR_ON; | ||
436 | wake_up_interruptible (&PortP->gs.open_wait); | ||
437 | } | ||
438 | else /* no carrier - wait for DCD */ | ||
439 | { | ||
440 | /* | ||
441 | while (!(PortP->gs.tty->termios->c_state & CARR_ON) && | ||
442 | !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted ) | ||
443 | */ | ||
444 | while (!(PortP->State & RIO_CARR_ON) && | ||
445 | !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted ) { | ||
446 | |||
447 | rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n",SysPort); | ||
448 | /* | ||
449 | PortP->gs.tty->termios->c_state |= WOPEN; | ||
450 | */ | ||
451 | PortP->State |= RIO_WOPEN; | ||
452 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
453 | if (RIODelay (PortP, HUNDRED_MS) == RIO_FAIL) | ||
454 | #if 0 | ||
455 | if ( sleep((caddr_t)&tp->tm.c_canqo, TTIPRI|PCATCH)) | ||
456 | #endif | ||
457 | { | ||
458 | /* | ||
459 | ** ACTION: verify that this is a good thing | ||
460 | ** to do here. -- ??? | ||
461 | ** I think it's OK. -- REW | ||
462 | */ | ||
463 | rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", | ||
464 | SysPort); | ||
465 | RIOPreemptiveCmd( p, PortP, FCLOSE ); | ||
466 | /* | ||
467 | tp->tm.c_state &= ~WOPEN; | ||
468 | */ | ||
469 | PortP->State &= ~RIO_WOPEN; | ||
470 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
471 | func_exit (); | ||
472 | return -EINTR; | ||
473 | } | ||
474 | } | ||
475 | PortP->State &= ~RIO_WOPEN; | ||
476 | } | ||
477 | if ( p->RIOHalted ) | ||
478 | goto bombout; | ||
479 | rio_dprintk (RIO_DEBUG_TTY, "Setting RIO_MOPEN\n"); | ||
480 | PortP->State |= RIO_MOPEN; | ||
481 | } | ||
482 | else | ||
483 | #endif | ||
484 | { | ||
485 | /* | ||
486 | ** ACTION | ||
487 | ** Direct line open - force carrier (will probably mean | ||
488 | ** that sleeping Modem line fubar) | ||
489 | */ | ||
490 | PortP->State |= RIO_LOPEN; | ||
491 | } | ||
492 | |||
493 | if ( p->RIOHalted ) { | ||
494 | goto bombout; | ||
495 | } | ||
496 | |||
497 | rio_dprintk (RIO_DEBUG_TTY, "high level open done\n"); | ||
498 | |||
499 | #ifdef STATS | ||
500 | PortP->Stat.OpenCnt++; | ||
501 | #endif | ||
502 | /* | ||
503 | ** Count opens for port statistics reporting | ||
504 | */ | ||
505 | if (PortP->statsGather) | ||
506 | PortP->opens++; | ||
507 | |||
508 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
509 | rio_dprintk (RIO_DEBUG_TTY, "Returning from open\n"); | ||
510 | func_exit (); | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | /* | ||
515 | ** RIOClose the port. | ||
516 | ** The operating system thinks that this is last close for the device. | ||
517 | ** As there are two interfaces to the port (Modem and tty), we need to | ||
518 | ** check that both are closed before we close the device. | ||
519 | */ | ||
520 | int | ||
521 | riotclose(void *ptr) | ||
522 | { | ||
523 | #if 0 | ||
524 | register uint SysPort = dev; | ||
525 | struct ttystatics *tp; /* pointer to our ttystruct */ | ||
526 | #endif | ||
527 | struct Port *PortP =ptr; /* pointer to the port structure */ | ||
528 | int deleted = 0; | ||
529 | int try = -1; /* Disable the timeouts by setting them to -1 */ | ||
530 | int repeat_this = -1; /* Congrats to those having 15 years of | ||
531 | uptime! (You get to break the driver.) */ | ||
532 | long end_time; | ||
533 | struct tty_struct * tty; | ||
534 | unsigned long flags; | ||
535 | int Modem; | ||
536 | int rv =0; | ||
537 | |||
538 | rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum); | ||
539 | |||
540 | /* PortP = p->RIOPortp[SysPort]; */ | ||
541 | rio_dprintk (RIO_DEBUG_TTY, "Port is at address 0x%x\n",(int)PortP); | ||
542 | /* tp = PortP->TtyP;*/ /* Get tty */ | ||
543 | tty = PortP->gs.tty; | ||
544 | rio_dprintk (RIO_DEBUG_TTY, "TTY is at address 0x%x\n",(int)tty); | ||
545 | |||
546 | if (PortP->gs.closing_wait) | ||
547 | end_time = jiffies + PortP->gs.closing_wait; | ||
548 | else | ||
549 | end_time = jiffies + MAX_SCHEDULE_TIMEOUT; | ||
550 | |||
551 | Modem = rio_ismodem(tty); | ||
552 | #if 0 | ||
553 | /* What F.CKING cache? Even then, a higly idle multiprocessor, | ||
554 | system with large caches this won't work . Better find out when | ||
555 | this doesn't work asap, and fix the cause. -- REW */ | ||
556 | |||
557 | RIODelay(PortP, HUNDRED_MS*10); /* To flush the cache */ | ||
558 | #endif | ||
559 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
560 | |||
561 | /* | ||
562 | ** Setting this flag will make any process trying to open | ||
563 | ** this port block until we are complete closing it. | ||
564 | */ | ||
565 | PortP->State |= RIO_CLOSING; | ||
566 | |||
567 | if ( (PortP->State & RIO_DELETED) ) { | ||
568 | rio_dprintk (RIO_DEBUG_TTY, "Close on deleted RTA\n"); | ||
569 | deleted = 1; | ||
570 | } | ||
571 | |||
572 | if ( p->RIOHalted ) { | ||
573 | RIOClearUp( PortP ); | ||
574 | rv = -EIO; | ||
575 | goto close_end; | ||
576 | } | ||
577 | |||
578 | rio_dprintk (RIO_DEBUG_TTY, "Clear bits\n"); | ||
579 | /* | ||
580 | ** clear the open bits for this device | ||
581 | */ | ||
582 | PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN); | ||
583 | PortP->State &= ~RIO_CARR_ON; | ||
584 | PortP->ModemState &= ~MSVR1_CD; | ||
585 | /* | ||
586 | ** If the device was open as both a Modem and a tty line | ||
587 | ** then we need to wimp out here, as the port has not really | ||
588 | ** been finally closed (gee, whizz!) The test here uses the | ||
589 | ** bit for the OTHER mode of operation, to see if THAT is | ||
590 | ** still active! | ||
591 | */ | ||
592 | if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) { | ||
593 | /* | ||
594 | ** The port is still open for the other task - | ||
595 | ** return, pretending that we are still active. | ||
596 | */ | ||
597 | rio_dprintk (RIO_DEBUG_TTY, "Channel %d still open !\n",PortP->PortNum); | ||
598 | PortP->State &= ~RIO_CLOSING; | ||
599 | if (PortP->firstOpen) | ||
600 | PortP->firstOpen--; | ||
601 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
602 | return -EIO; | ||
603 | } | ||
604 | |||
605 | rio_dprintk (RIO_DEBUG_TTY, "Closing down - everything must go!\n"); | ||
606 | |||
607 | PortP->State &= ~RIO_DYNOROD; | ||
608 | |||
609 | /* | ||
610 | ** This is where we wait for the port | ||
611 | ** to drain down before closing. Bye-bye.... | ||
612 | ** (We never meant to do this) | ||
613 | */ | ||
614 | rio_dprintk (RIO_DEBUG_TTY, "Timeout 1 starts\n"); | ||
615 | |||
616 | if (!deleted) | ||
617 | while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted && | ||
618 | (PortP->TxBufferIn != PortP->TxBufferOut) ) { | ||
619 | cprintf("Need to flush the ttyport\n"); | ||
620 | if (repeat_this -- <= 0) { | ||
621 | rv = -EINTR; | ||
622 | rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); | ||
623 | RIOPreemptiveCmd(p, PortP, FCLOSE ); | ||
624 | goto close_end; | ||
625 | } | ||
626 | rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n"); | ||
627 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
628 | if (RIODelay_ni(PortP, HUNDRED_MS*10) == RIO_FAIL) { | ||
629 | rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n"); | ||
630 | rv = -EINTR; | ||
631 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
632 | goto close_end; | ||
633 | } | ||
634 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
635 | } | ||
636 | |||
637 | PortP->TxBufferIn = PortP->TxBufferOut = 0; | ||
638 | repeat_this = 0xff; | ||
639 | |||
640 | PortP->InUse = 0; | ||
641 | if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) { | ||
642 | /* | ||
643 | ** The port has been re-opened for the other task - | ||
644 | ** return, pretending that we are still active. | ||
645 | */ | ||
646 | rio_dprintk (RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum); | ||
647 | PortP->State &= ~RIO_CLOSING; | ||
648 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
649 | if (PortP->firstOpen) | ||
650 | PortP->firstOpen--; | ||
651 | return -EIO; | ||
652 | } | ||
653 | |||
654 | if ( p->RIOHalted ) { | ||
655 | RIOClearUp( PortP ); | ||
656 | goto close_end; | ||
657 | } | ||
658 | |||
659 | |||
660 | |||
661 | /* Can't call RIOShortCommand with the port locked. */ | ||
662 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
663 | |||
664 | if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) { | ||
665 | RIOPreemptiveCmd(p, PortP,FCLOSE); | ||
666 | goto close_end; | ||
667 | } | ||
668 | |||
669 | if (!deleted) | ||
670 | while (try && (PortP->PortState & PORT_ISOPEN)) { | ||
671 | try--; | ||
672 | if (time_after (jiffies, end_time)) { | ||
673 | rio_dprintk (RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n" ); | ||
674 | RIOPreemptiveCmd(p, PortP,FCLOSE); | ||
675 | break; | ||
676 | } | ||
677 | rio_dprintk (RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", | ||
678 | PortP->PortState & PORT_ISOPEN); | ||
679 | |||
680 | if ( p->RIOHalted ) { | ||
681 | RIOClearUp( PortP ); | ||
682 | goto close_end; | ||
683 | } | ||
684 | if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { | ||
685 | rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n"); | ||
686 | RIOPreemptiveCmd(p, PortP,FCLOSE); | ||
687 | break; | ||
688 | } | ||
689 | } | ||
690 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
691 | rio_dprintk (RIO_DEBUG_TTY, "Close: try was %d on completion\n", try ); | ||
692 | |||
693 | /* RIOPreemptiveCmd(p, PortP, FCLOSE); */ | ||
694 | |||
695 | /* | ||
696 | ** 15.10.1998 ARG - ESIL 0761 part fix | ||
697 | ** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened. | ||
698 | */ | ||
699 | PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW); | ||
700 | |||
701 | |||
702 | #ifdef STATS | ||
703 | PortP->Stat.CloseCnt++; | ||
704 | #endif | ||
705 | /* | ||
706 | ** Count opens for port statistics reporting | ||
707 | */ | ||
708 | if (PortP->statsGather) | ||
709 | PortP->closes++; | ||
710 | |||
711 | close_end: | ||
712 | /* XXX: Why would a "DELETED" flag be reset here? I'd have | ||
713 | thought that a "deleted" flag means that the port was | ||
714 | permanently gone, but here we can make it reappear by it | ||
715 | being in close during the "deletion". | ||
716 | */ | ||
717 | PortP->State &= ~(RIO_CLOSING|RIO_DELETED); | ||
718 | if (PortP->firstOpen) | ||
719 | PortP->firstOpen--; | ||
720 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
721 | rio_dprintk (RIO_DEBUG_TTY, "Return from close\n"); | ||
722 | return rv; | ||
723 | } | ||
724 | |||
725 | |||
726 | /* | ||
727 | ** decide if we need to use the line discipline. | ||
728 | ** This routine can return one of three values: | ||
729 | ** COOK_RAW if no processing has to be done by the line discipline or the card | ||
730 | ** COOK_WELL if the line discipline must be used to do the processing | ||
731 | ** COOK_MEDIUM if the card can do all the processing necessary. | ||
732 | */ | ||
733 | #if 0 | ||
734 | static int | ||
735 | RIOCookMode(struct ttystatics *tp) | ||
736 | { | ||
737 | /* | ||
738 | ** We can't handle tm.c_mstate != 0 on SCO | ||
739 | ** We can't handle mapping | ||
740 | ** We can't handle non-ttwrite line disc. | ||
741 | ** We can't handle lflag XCASE | ||
742 | ** We can handle oflag OPOST & (OCRNL, ONLCR, TAB3) | ||
743 | */ | ||
744 | |||
745 | #ifdef CHECK | ||
746 | CheckTtyP( tp ); | ||
747 | #endif | ||
748 | if (!(tp->tm.c_oflag & OPOST)) /* No post processing */ | ||
749 | return COOK_RAW; /* Raw mode o/p */ | ||
750 | |||
751 | if ( tp->tm.c_lflag & XCASE ) | ||
752 | return COOK_WELL; /* Use line disc */ | ||
753 | |||
754 | if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3 ) ) | ||
755 | return COOK_WELL; /* Use line disc for strange modes */ | ||
756 | |||
757 | if ( tp->tm.c_oflag == OPOST ) /* If only OPOST is set, do RAW */ | ||
758 | return COOK_RAW; | ||
759 | |||
760 | /* | ||
761 | ** So, we need to output process! | ||
762 | */ | ||
763 | return COOK_MEDIUM; | ||
764 | } | ||
765 | #endif | ||
766 | |||
767 | static void | ||
768 | RIOClearUp(PortP) | ||
769 | struct Port *PortP; | ||
770 | { | ||
771 | rio_dprintk (RIO_DEBUG_TTY, "RIOHalted set\n"); | ||
772 | PortP->Config = 0; /* Direct semaphore */ | ||
773 | PortP->PortState = 0; | ||
774 | PortP->firstOpen = 0; | ||
775 | PortP->FlushCmdBodge = 0; | ||
776 | PortP->ModemState = PortP->CookMode = 0; | ||
777 | PortP->Mapped = 0; | ||
778 | PortP->WflushFlag = 0; | ||
779 | PortP->MagicFlags = 0; | ||
780 | PortP->RxDataStart = 0; | ||
781 | PortP->TxBufferIn = 0; | ||
782 | PortP->TxBufferOut = 0; | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | ** Put a command onto a port. | ||
787 | ** The PortPointer, command, length and arg are passed. | ||
788 | ** The len is the length *inclusive* of the command byte, | ||
789 | ** and so for a command that takes no data, len==1. | ||
790 | ** The arg is a single byte, and is only used if len==2. | ||
791 | ** Other values of len aren't allowed, and will cause | ||
792 | ** a panic. | ||
793 | */ | ||
794 | int RIOShortCommand(struct rio_info *p, struct Port *PortP, | ||
795 | int command, int len, int arg) | ||
796 | { | ||
797 | PKT *PacketP; | ||
798 | int retries = 20; /* at 10 per second -> 2 seconds */ | ||
799 | unsigned long flags; | ||
800 | |||
801 | rio_dprintk (RIO_DEBUG_TTY, "entering shortcommand.\n"); | ||
802 | #ifdef CHECK | ||
803 | CheckPortP( PortP ); | ||
804 | if ( len < 1 || len > 2 ) | ||
805 | cprintf(("STUPID LENGTH %d\n",len)); | ||
806 | #endif | ||
807 | |||
808 | if ( PortP->State & RIO_DELETED ) { | ||
809 | rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); | ||
810 | return RIO_FAIL; | ||
811 | } | ||
812 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
813 | |||
814 | /* | ||
815 | ** If the port is in use for pre-emptive command, then wait for it to | ||
816 | ** be free again. | ||
817 | */ | ||
818 | while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted ) { | ||
819 | rio_dprintk (RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", | ||
820 | retries); | ||
821 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
822 | if (retries-- <= 0) { | ||
823 | return RIO_FAIL; | ||
824 | } | ||
825 | if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) { | ||
826 | return RIO_FAIL; | ||
827 | } | ||
828 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
829 | } | ||
830 | if ( PortP->State & RIO_DELETED ) { | ||
831 | rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); | ||
832 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
833 | return RIO_FAIL; | ||
834 | } | ||
835 | |||
836 | while ( !can_add_transmit(&PacketP,PortP) && !p->RIOHalted ) { | ||
837 | rio_dprintk (RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries); | ||
838 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
839 | if (retries-- <= 0) { | ||
840 | rio_dprintk (RIO_DEBUG_TTY, "out of tries. Failing\n"); | ||
841 | return RIO_FAIL; | ||
842 | } | ||
843 | if ( RIODelay_ni(PortP, HUNDRED_MS)==RIO_FAIL ) { | ||
844 | return RIO_FAIL; | ||
845 | } | ||
846 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
847 | } | ||
848 | |||
849 | if ( p->RIOHalted ) { | ||
850 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
851 | return RIO_FAIL; | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | ** set the command byte and the argument byte | ||
856 | */ | ||
857 | WBYTE(PacketP->data[0] , command); | ||
858 | |||
859 | if ( len==2 ) | ||
860 | WBYTE(PacketP->data[1] , arg); | ||
861 | |||
862 | /* | ||
863 | ** set the length of the packet and set the command bit. | ||
864 | */ | ||
865 | WBYTE(PacketP->len , PKT_CMD_BIT | len); | ||
866 | |||
867 | add_transmit(PortP); | ||
868 | /* | ||
869 | ** Count characters transmitted for port statistics reporting | ||
870 | */ | ||
871 | if (PortP->statsGather) | ||
872 | PortP->txchars += len; | ||
873 | |||
874 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
875 | return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL; | ||
876 | } | ||
877 | |||
878 | |||
879 | #if 0 | ||
880 | /* | ||
881 | ** This is an ioctl interface. This is the twentieth century. You know what | ||
882 | ** its all about. | ||
883 | */ | ||
884 | int | ||
885 | riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg) | ||
886 | { | ||
887 | register struct Port *PortP; | ||
888 | register struct ttystatics *tp; | ||
889 | int current; | ||
890 | int ParamSemIncremented = 0; | ||
891 | int old_oflag, old_cflag, old_iflag, changed, oldcook; | ||
892 | int i; | ||
893 | unsigned char sio_regs[5]; /* Here be magic */ | ||
894 | short vpix_cflag; | ||
895 | short divisor; | ||
896 | int baud; | ||
897 | uint SysPort = rio_minor(tty); | ||
898 | int Modem = rio_ismodem(tty); | ||
899 | int ioctl_processed; | ||
900 | |||
901 | rio_dprintk (RIO_DEBUG_TTY, "port ioctl SysPort %d command 0x%x argument 0x%x %s\n", | ||
902 | SysPort, cmd, arg, Modem?"Modem":"tty") ; | ||
903 | |||
904 | if ( SysPort >= RIO_PORTS ) { | ||
905 | rio_dprintk (RIO_DEBUG_TTY, "Bad port number %d\n", SysPort); | ||
906 | return -ENXIO; | ||
907 | } | ||
908 | |||
909 | PortP = p->RIOPortp[SysPort]; | ||
910 | tp = PortP->TtyP; | ||
911 | |||
912 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
913 | |||
914 | #ifdef STATS | ||
915 | PortP->Stat.IoctlCnt++; | ||
916 | #endif | ||
917 | |||
918 | if ( PortP->State & RIO_DELETED ) { | ||
919 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
920 | return -EIO; | ||
921 | } | ||
922 | |||
923 | |||
924 | if ( p->RIOHalted ) { | ||
925 | RIOClearUp( PortP ); | ||
926 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
927 | return -EIO; | ||
928 | } | ||
929 | |||
930 | /* | ||
931 | ** Count ioctls for port statistics reporting | ||
932 | */ | ||
933 | if (PortP->statsGather) | ||
934 | PortP->ioctls++; | ||
935 | |||
936 | /* | ||
937 | ** Specialix RIO Ioctl calls | ||
938 | */ | ||
939 | switch (cmd) { | ||
940 | |||
941 | case TCRIOTRIAD: | ||
942 | if ( arg ) | ||
943 | PortP->State |= RIO_TRIAD_MODE; | ||
944 | else | ||
945 | PortP->State &= ~RIO_TRIAD_MODE; | ||
946 | /* | ||
947 | ** Normally, when istrip is set on a port, a config is | ||
948 | ** sent to the RTA instructing the CD1400 to do the | ||
949 | ** stripping. In TRIAD mode, the interrupt receive routine | ||
950 | ** must do the stripping instead, since it has to detect | ||
951 | ** an 8 bit function key sequence. If istrip is set with | ||
952 | ** TRIAD mode on(off), and 8 bit data is being read by | ||
953 | ** the port, the user then turns TRIAD mode off(on), the RTA | ||
954 | ** must be reconfigured (not) to do the stripping. | ||
955 | ** Hence we call RIOParam here. | ||
956 | */ | ||
957 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
958 | RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); | ||
959 | return 0; | ||
960 | |||
961 | case TCRIOTSTATE: | ||
962 | rio_dprintk (RIO_DEBUG_TTY, "tbusy/tstop monitoring %sabled\n", | ||
963 | arg ? "en" : "dis"); | ||
964 | /* MonitorTstate = 0 ;*/ | ||
965 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
966 | RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); | ||
967 | return 0; | ||
968 | |||
969 | case TCRIOSTATE: /* current state of Modem input pins */ | ||
970 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE\n"); | ||
971 | if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL) | ||
972 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE command failed\n"); | ||
973 | PortP->State |= RIO_BUSY; | ||
974 | current = PortP->ModemState; | ||
975 | if ( copyout((caddr_t)¤t, (int)arg, | ||
976 | sizeof(current))==COPYFAIL ) { | ||
977 | rio_dprintk (RIO_DEBUG_TTY, "Copyout failed\n"); | ||
978 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
979 | pseterr(EFAULT); | ||
980 | } | ||
981 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
982 | return 0; | ||
983 | |||
984 | case TCRIOMBIS: /* Set modem lines */ | ||
985 | case TCRIOMBIC: /* Clear modem lines */ | ||
986 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIS/TCRIOMBIC\n"); | ||
987 | if (cmd == TCRIOMBIS) { | ||
988 | uint state; | ||
989 | state = (uint)arg; | ||
990 | PortP->ModemState |= (ushort)state; | ||
991 | PortP->ModemLines = (ulong) arg; | ||
992 | if (RIOPreemptiveCmd(p, PortP, MBIS) == RIO_FAIL) | ||
993 | rio_dprintk (RIO_DEBUG_TTY, | ||
994 | "TCRIOMBIS command failed\n"); | ||
995 | } | ||
996 | else { | ||
997 | uint state; | ||
998 | |||
999 | state = (uint)arg; | ||
1000 | PortP->ModemState &= ~(ushort)state; | ||
1001 | PortP->ModemLines = (ulong) arg; | ||
1002 | if (RIOPreemptiveCmd(p, PortP, MBIC) == RIO_FAIL) | ||
1003 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIC command failed\n"); | ||
1004 | } | ||
1005 | PortP->State |= RIO_BUSY; | ||
1006 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1007 | return 0; | ||
1008 | |||
1009 | case TCRIOXPON: /* set Xprint ON string */ | ||
1010 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPON\n"); | ||
1011 | if ( copyin((int)arg, (caddr_t)PortP->Xprint.XpOn, | ||
1012 | MAX_XP_CTRL_LEN)==COPYFAIL ) { | ||
1013 | rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n"); | ||
1014 | PortP->Xprint.XpOn[0] = '\0'; | ||
1015 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1016 | pseterr(EFAULT); | ||
1017 | } | ||
1018 | PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0'; | ||
1019 | PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+ | ||
1020 | strlen(PortP->Xprint.XpOff); | ||
1021 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1022 | return 0; | ||
1023 | |||
1024 | case TCRIOXPOFF: /* set Xprint OFF string */ | ||
1025 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPOFF\n"); | ||
1026 | if ( copyin( (int)arg, (caddr_t)PortP->Xprint.XpOff, | ||
1027 | MAX_XP_CTRL_LEN)==COPYFAIL ) { | ||
1028 | rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n"); | ||
1029 | PortP->Xprint.XpOff[0] = '\0'; | ||
1030 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1031 | pseterr(EFAULT); | ||
1032 | } | ||
1033 | PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0'; | ||
1034 | PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+ | ||
1035 | strlen(PortP->Xprint.XpOff); | ||
1036 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1037 | return 0; | ||
1038 | |||
1039 | case TCRIOXPCPS: /* set Xprint CPS string */ | ||
1040 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPCPS\n"); | ||
1041 | if ( (uint)arg > p->RIOConf.MaxXpCps || | ||
1042 | (uint)arg < p->RIOConf.MinXpCps ) { | ||
1043 | rio_dprintk (RIO_DEBUG_TTY, "%d CPS out of range\n",arg); | ||
1044 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1045 | pseterr(EINVAL); | ||
1046 | return 0; | ||
1047 | } | ||
1048 | PortP->Xprint.XpCps = (uint)arg; | ||
1049 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1050 | return 0; | ||
1051 | |||
1052 | case TCRIOXPRINT: | ||
1053 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPRINT\n"); | ||
1054 | if ( copyout((caddr_t)&PortP->Xprint, (int)arg, | ||
1055 | sizeof(struct Xprint))==COPYFAIL ) { | ||
1056 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1057 | pseterr(EFAULT); | ||
1058 | } | ||
1059 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1060 | return 0; | ||
1061 | |||
1062 | case TCRIOIXANYON: | ||
1063 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYON\n"); | ||
1064 | PortP->Config |= RIO_IXANY; | ||
1065 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1066 | return 0; | ||
1067 | |||
1068 | case TCRIOIXANYOFF: | ||
1069 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYOFF\n"); | ||
1070 | PortP->Config &= ~RIO_IXANY; | ||
1071 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1072 | return 0; | ||
1073 | |||
1074 | case TCRIOIXONON: | ||
1075 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONON\n"); | ||
1076 | PortP->Config |= RIO_IXON; | ||
1077 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1078 | return 0; | ||
1079 | |||
1080 | case TCRIOIXONOFF: | ||
1081 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONOFF\n"); | ||
1082 | PortP->Config &= ~RIO_IXON; | ||
1083 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1084 | return 0; | ||
1085 | |||
1086 | /* | ||
1087 | ** 15.10.1998 ARG - ESIL 0761 part fix | ||
1088 | ** Added support for CTS and RTS flow control ioctls : | ||
1089 | */ | ||
1090 | case TCRIOCTSFLOWEN: | ||
1091 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWEN\n"); | ||
1092 | PortP->Config |= RIO_CTSFLOW; | ||
1093 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1094 | RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); | ||
1095 | return 0; | ||
1096 | |||
1097 | case TCRIOCTSFLOWDIS: | ||
1098 | rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWDIS\n"); | ||
1099 | PortP->Config &= ~RIO_CTSFLOW; | ||
1100 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1101 | RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); | ||
1102 | return 0; | ||
1103 | |||
1104 | case TCRIORTSFLOWEN: | ||
1105 | rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWEN\n"); | ||
1106 | PortP->Config |= RIO_RTSFLOW; | ||
1107 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1108 | RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); | ||
1109 | return 0; | ||
1110 | |||
1111 | case TCRIORTSFLOWDIS: | ||
1112 | rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWDIS\n"); | ||
1113 | PortP->Config &= ~RIO_RTSFLOW; | ||
1114 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1115 | RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); | ||
1116 | return 0; | ||
1117 | |||
1118 | /* end ESIL 0761 part fix */ | ||
1119 | |||
1120 | } | ||
1121 | |||
1122 | |||
1123 | /* Lynx IOCTLS */ | ||
1124 | switch (cmd) { | ||
1125 | case TIOCSETP: | ||
1126 | case TIOCSETN: | ||
1127 | case OTIOCSETP: | ||
1128 | case OTIOCSETN: | ||
1129 | ioctl_processed++; | ||
1130 | ttyseth(PortP, tp, (struct old_sgttyb *)arg); | ||
1131 | break; | ||
1132 | case TCSETA: | ||
1133 | case TCSETAW: | ||
1134 | case TCSETAF: | ||
1135 | ioctl_processed++; | ||
1136 | rio_dprintk (RIO_DEBUG_TTY, "NON POSIX ioctl\n"); | ||
1137 | ttyseth_pv(PortP, tp, (struct termios *)arg, 0); | ||
1138 | break; | ||
1139 | case TCSETAP: /* posix tcsetattr() */ | ||
1140 | case TCSETAWP: /* posix tcsetattr() */ | ||
1141 | case TCSETAFP: /* posix tcsetattr() */ | ||
1142 | rio_dprintk (RIO_DEBUG_TTY, "NON POSIX SYSV ioctl\n"); | ||
1143 | ttyseth_pv(PortP, tp, (struct termios *)arg, 1); | ||
1144 | ioctl_processed++; | ||
1145 | break; | ||
1146 | } | ||
1147 | |||
1148 | /* | ||
1149 | ** If its any of the commands that require the port to be in the | ||
1150 | ** non-busy state wait until all output has drained | ||
1151 | */ | ||
1152 | if (!ioctl_processed) | ||
1153 | switch(cmd) { | ||
1154 | case TCSETAW: | ||
1155 | case TCSETAF: | ||
1156 | case TCSETA: | ||
1157 | case TCSBRK: | ||
1158 | #define OLD_POSIX ('x' << 8) | ||
1159 | #define OLD_POSIX_SETA (OLD_POSIX | 2) | ||
1160 | #define OLD_POSIX_SETAW (OLD_POSIX | 3) | ||
1161 | #define OLD_POSIX_SETAF (OLD_POSIX | 4) | ||
1162 | #define NEW_POSIX (('i' << 24) | ('X' << 16)) | ||
1163 | #define NEW_POSIX_SETA (NEW_POSIX | 2) | ||
1164 | #define NEW_POSIX_SETAW (NEW_POSIX | 3) | ||
1165 | #define NEW_POSIX_SETAF (NEW_POSIX | 4) | ||
1166 | case OLD_POSIX_SETA: | ||
1167 | case OLD_POSIX_SETAW: | ||
1168 | case OLD_POSIX_SETAF: | ||
1169 | case NEW_POSIX_SETA: | ||
1170 | case NEW_POSIX_SETAW: | ||
1171 | case NEW_POSIX_SETAF: | ||
1172 | #ifdef TIOCSETP | ||
1173 | case TIOCSETP: | ||
1174 | #endif | ||
1175 | case TIOCSETD: | ||
1176 | case TIOCSETN: | ||
1177 | rio_dprintk (RIO_DEBUG_TTY, "wait for non-BUSY, semaphore set\n"); | ||
1178 | /* | ||
1179 | ** Wait for drain here, at least as far as the double buffer | ||
1180 | ** being empty. | ||
1181 | */ | ||
1182 | /* XXX Does the above comment mean that this has | ||
1183 | still to be implemented? -- REW */ | ||
1184 | /* XXX Is the locking OK together with locking | ||
1185 | in txenable? (Deadlock?) -- REW */ | ||
1186 | |||
1187 | RIOTxEnable((char *)PortP); | ||
1188 | break; | ||
1189 | default: | ||
1190 | break; | ||
1191 | } | ||
1192 | |||
1193 | old_cflag = tp->tm.c_cflag; | ||
1194 | old_iflag = tp->tm.c_iflag; | ||
1195 | old_oflag = tp->tm.c_oflag; | ||
1196 | oldcook = PortP->CookMode; | ||
1197 | |||
1198 | if ( p->RIOHalted ) { | ||
1199 | RIOClearUp( PortP ); | ||
1200 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1201 | pseterr(EIO); | ||
1202 | return 0; | ||
1203 | } | ||
1204 | |||
1205 | PortP->FlushCmdBodge = 0; | ||
1206 | |||
1207 | /* | ||
1208 | ** If the port is locked, and it is reconfigured, we want | ||
1209 | ** to restore the state of the tty structure so the change is NOT | ||
1210 | ** made. | ||
1211 | */ | ||
1212 | if (PortP->Lock) { | ||
1213 | tp->tm.c_iflag = PortP->StoredTty.iflag; | ||
1214 | tp->tm.c_oflag = PortP->StoredTty.oflag; | ||
1215 | tp->tm.c_cflag = PortP->StoredTty.cflag; | ||
1216 | tp->tm.c_lflag = PortP->StoredTty.lflag; | ||
1217 | tp->tm.c_line = PortP->StoredTty.line; | ||
1218 | for (i = 0; i < NCC + 1; i++) | ||
1219 | tp->tm.c_cc[i] = PortP->StoredTty.cc[i]; | ||
1220 | } | ||
1221 | else { | ||
1222 | /* | ||
1223 | ** If the port is set to store the parameters, and it is | ||
1224 | ** reconfigured, we want to save the current tty struct so it | ||
1225 | ** may be restored on the next open. | ||
1226 | */ | ||
1227 | if (PortP->Store) { | ||
1228 | PortP->StoredTty.iflag = tp->tm.c_iflag; | ||
1229 | PortP->StoredTty.oflag = tp->tm.c_oflag; | ||
1230 | PortP->StoredTty.cflag = tp->tm.c_cflag; | ||
1231 | PortP->StoredTty.lflag = tp->tm.c_lflag; | ||
1232 | PortP->StoredTty.line = tp->tm.c_line; | ||
1233 | for (i = 0; i < NCC + 1; i++) | ||
1234 | PortP->StoredTty.cc[i] = tp->tm.c_cc[i]; | ||
1235 | } | ||
1236 | } | ||
1237 | |||
1238 | changed = (tp->tm.c_cflag != old_cflag) || | ||
1239 | (tp->tm.c_iflag != old_iflag) || | ||
1240 | (tp->tm.c_oflag != old_oflag); | ||
1241 | |||
1242 | PortP->CookMode = RIOCookMode(tp); /* Set new cooking mode */ | ||
1243 | |||
1244 | rio_dprintk (RIO_DEBUG_TTY, "RIOIoctl changed %d newcook %d oldcook %d\n", | ||
1245 | changed,PortP->CookMode,oldcook); | ||
1246 | |||
1247 | #ifdef MODEM_SUPPORT | ||
1248 | /* | ||
1249 | ** kludge to force CARR_ON if CLOCAL set | ||
1250 | */ | ||
1251 | if ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) { | ||
1252 | tp->tm.c_state |= CARR_ON; | ||
1253 | wakeup ((caddr_t)&tp->tm.c_canq); | ||
1254 | } | ||
1255 | #endif | ||
1256 | |||
1257 | if ( p->RIOHalted ) { | ||
1258 | RIOClearUp( PortP ); | ||
1259 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1260 | pseterr(EIO); | ||
1261 | return 0; | ||
1262 | } | ||
1263 | /* | ||
1264 | ** Re-configure if modes or cooking have changed | ||
1265 | */ | ||
1266 | if (changed || oldcook != PortP->CookMode || (ioctl_processed)) { | ||
1267 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1268 | rio_dprintk (RIO_DEBUG_TTY, "Ioctl changing the PORT settings\n"); | ||
1269 | RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); | ||
1270 | rio_spin_lock_irqsave(&PortP->portSem, flags); | ||
1271 | } | ||
1272 | |||
1273 | if (p->RIOHalted) { | ||
1274 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1275 | RIOClearUp( PortP ); | ||
1276 | pseterr(EIO); | ||
1277 | return 0; | ||
1278 | } | ||
1279 | rio_spin_unlock_irqrestore(&PortP->portSem, flags); | ||
1280 | return 0; | ||
1281 | } | ||
1282 | |||
1283 | /* | ||
1284 | ttyseth -- set hardware dependent tty settings | ||
1285 | */ | ||
1286 | void | ||
1287 | ttyseth(PortP, s, sg) | ||
1288 | struct Port * PortP; | ||
1289 | struct ttystatics * s; | ||
1290 | struct old_sgttyb *sg; | ||
1291 | { | ||
1292 | struct old_sgttyb * tsg; | ||
1293 | struct termios *tp = &s->tm; | ||
1294 | |||
1295 | tsg = &s->sg; | ||
1296 | |||
1297 | if (sg->sg_flags & (EVENP|ODDP)) { | ||
1298 | tp->c_cflag &= PARENB; | ||
1299 | if (sg->sg_flags & EVENP) { | ||
1300 | if (sg->sg_flags & ODDP) { | ||
1301 | tp->c_cflag &= V_CS7; | ||
1302 | tp->c_cflag &= ~PARENB; | ||
1303 | } | ||
1304 | else { | ||
1305 | tp->c_cflag &= V_CS7; | ||
1306 | tp->c_cflag &= PARENB; | ||
1307 | tp->c_cflag &= PARODD; | ||
1308 | } | ||
1309 | } | ||
1310 | else if (sg->sg_flags & ODDP) { | ||
1311 | tp->c_cflag &= V_CS7; | ||
1312 | tp->c_cflag &= PARENB; | ||
1313 | tp->c_cflag &= PARODD; | ||
1314 | } | ||
1315 | else { | ||
1316 | tp->c_cflag &= V_CS7; | ||
1317 | tp->c_cflag &= PARENB; | ||
1318 | } | ||
1319 | } | ||
1320 | /* | ||
1321 | * Use ispeed as the desired speed. Most implementations don't handle | ||
1322 | * separate input and output speeds very well. If the RIO handles this, | ||
1323 | * I will have to use separate sets of flags to store them in the | ||
1324 | * Port structure. | ||
1325 | */ | ||
1326 | if ( !sg->sg_ospeed ) | ||
1327 | sg->sg_ospeed = sg->sg_ispeed; | ||
1328 | else | ||
1329 | sg->sg_ispeed = sg->sg_ospeed; | ||
1330 | if (sg->sg_ispeed > V_EXTB ) | ||
1331 | sg->sg_ispeed = V_EXTB; | ||
1332 | if (sg->sg_ispeed < V_B0) | ||
1333 | sg->sg_ispeed = V_B0; | ||
1334 | *tsg = *sg; | ||
1335 | tp->c_cflag = (tp->c_cflag & ~V_CBAUD) | conv_bv[(int)sg->sg_ispeed]; | ||
1336 | } | ||
1337 | |||
1338 | /* | ||
1339 | ttyseth_pv -- set hardware dependent tty settings using either the | ||
1340 | POSIX termios structure or the System V termio structure. | ||
1341 | sysv = 0 => (POSIX): struct termios *sg | ||
1342 | sysv != 0 => (System V): struct termio *sg | ||
1343 | */ | ||
1344 | static void | ||
1345 | ttyseth_pv(PortP, s, sg, sysv) | ||
1346 | struct Port *PortP; | ||
1347 | struct ttystatics *s; | ||
1348 | struct termios *sg; | ||
1349 | int sysv; | ||
1350 | { | ||
1351 | int speed; | ||
1352 | unsigned char csize; | ||
1353 | unsigned char cread; | ||
1354 | unsigned int lcr_flags; | ||
1355 | int ps; | ||
1356 | |||
1357 | if (sysv) { | ||
1358 | /* sg points to a System V termio structure */ | ||
1359 | csize = ((struct termio *)sg)->c_cflag & CSIZE; | ||
1360 | cread = ((struct termio *)sg)->c_cflag & CREAD; | ||
1361 | speed = conv_vb[((struct termio *)sg)->c_cflag & V_CBAUD]; | ||
1362 | } | ||
1363 | else { | ||
1364 | /* sg points to a POSIX termios structure */ | ||
1365 | csize = sg->c_cflag & CSIZE; | ||
1366 | cread = sg->c_cflag & CREAD; | ||
1367 | speed = conv_vb[sg->c_cflag & V_CBAUD]; | ||
1368 | } | ||
1369 | if (s->sg.sg_ispeed != speed || s->sg.sg_ospeed != speed) { | ||
1370 | s->sg.sg_ispeed = speed; | ||
1371 | s->sg.sg_ospeed = speed; | ||
1372 | s->tm.c_cflag = (s->tm.c_cflag & ~V_CBAUD) | | ||
1373 | conv_bv[(int)s->sg.sg_ispeed]; | ||
1374 | } | ||
1375 | } | ||
1376 | #endif | ||
diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h new file mode 100644 index 000000000000..1c7c42c638f0 --- /dev/null +++ b/drivers/char/rio/riotypes.h | |||
@@ -0,0 +1,135 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* R I O T Y P E S | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Jon Brawn | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _riotypes_h | ||
38 | #define _riotypes_h 1 | ||
39 | |||
40 | #ifdef SCCS_LABELS | ||
41 | #ifndef lint | ||
42 | /* static char *_rio_riotypes_h_sccs = "@(#)riotypes.h 1.10"; */ | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | #ifdef INKERNEL | ||
47 | |||
48 | #if !defined(MIPSAT) | ||
49 | typedef unsigned short NUMBER_ptr; | ||
50 | typedef unsigned short WORD_ptr; | ||
51 | typedef unsigned short BYTE_ptr; | ||
52 | typedef unsigned short char_ptr; | ||
53 | typedef unsigned short Channel_ptr; | ||
54 | typedef unsigned short FREE_LIST_ptr_ptr; | ||
55 | typedef unsigned short FREE_LIST_ptr; | ||
56 | typedef unsigned short LPB_ptr; | ||
57 | typedef unsigned short Process_ptr; | ||
58 | typedef unsigned short PHB_ptr; | ||
59 | typedef unsigned short PKT_ptr; | ||
60 | typedef unsigned short PKT_ptr_ptr; | ||
61 | typedef unsigned short Q_BUF_ptr; | ||
62 | typedef unsigned short Q_BUF_ptr_ptr; | ||
63 | typedef unsigned short ROUTE_STR_ptr; | ||
64 | typedef unsigned short RUP_ptr; | ||
65 | typedef unsigned short short_ptr; | ||
66 | typedef unsigned short u_short_ptr; | ||
67 | typedef unsigned short ushort_ptr; | ||
68 | #else | ||
69 | /* MIPSAT types */ | ||
70 | typedef char RIO_POINTER[8]; | ||
71 | typedef RIO_POINTER NUMBER_ptr; | ||
72 | typedef RIO_POINTER WORD_ptr; | ||
73 | typedef RIO_POINTER BYTE_ptr; | ||
74 | typedef RIO_POINTER char_ptr; | ||
75 | typedef RIO_POINTER Channel_ptr; | ||
76 | typedef RIO_POINTER FREE_LIST_ptr_ptr; | ||
77 | typedef RIO_POINTER FREE_LIST_ptr; | ||
78 | typedef RIO_POINTER LPB_ptr; | ||
79 | typedef RIO_POINTER Process_ptr; | ||
80 | typedef RIO_POINTER PHB_ptr; | ||
81 | typedef RIO_POINTER PKT_ptr; | ||
82 | typedef RIO_POINTER PKT_ptr_ptr; | ||
83 | typedef RIO_POINTER Q_BUF_ptr; | ||
84 | typedef RIO_POINTER Q_BUF_ptr_ptr; | ||
85 | typedef RIO_POINTER ROUTE_STR_ptr; | ||
86 | typedef RIO_POINTER RUP_ptr; | ||
87 | typedef RIO_POINTER short_ptr; | ||
88 | typedef RIO_POINTER u_short_ptr; | ||
89 | typedef RIO_POINTER ushort_ptr; | ||
90 | #endif | ||
91 | |||
92 | #else /* not INKERNEL */ | ||
93 | typedef unsigned char BYTE; | ||
94 | typedef unsigned short WORD; | ||
95 | typedef unsigned long DWORD; | ||
96 | typedef short NUMBER; | ||
97 | typedef short *NUMBER_ptr; | ||
98 | typedef unsigned short *WORD_ptr; | ||
99 | typedef unsigned char *BYTE_ptr; | ||
100 | typedef unsigned char uchar ; | ||
101 | typedef unsigned short ushort ; | ||
102 | typedef unsigned int uint ; | ||
103 | typedef unsigned long ulong ; | ||
104 | typedef unsigned char u_char ; | ||
105 | typedef unsigned short u_short ; | ||
106 | typedef unsigned int u_int ; | ||
107 | typedef unsigned long u_long ; | ||
108 | typedef unsigned short ERROR ; | ||
109 | typedef unsigned long ID ; | ||
110 | typedef char *char_ptr; | ||
111 | typedef Channel *Channel_ptr; | ||
112 | typedef struct FREE_LIST *FREE_LIST_ptr; | ||
113 | typedef struct FREE_LIST **FREE_LIST_ptr_ptr; | ||
114 | typedef struct LPB *LPB_ptr; | ||
115 | typedef struct Process *Process_ptr; | ||
116 | typedef struct PHB *PHB_ptr; | ||
117 | typedef struct PKT *PKT_ptr; | ||
118 | typedef struct PKT **PKT_ptr_ptr; | ||
119 | typedef struct Q_BUF *Q_BUF_ptr; | ||
120 | typedef struct Q_BUF **Q_BUF_ptr_ptr; | ||
121 | typedef struct ROUTE_STR *ROUTE_STR_ptr; | ||
122 | typedef struct RUP *RUP_ptr; | ||
123 | typedef short *short_ptr; | ||
124 | typedef u_short *u_short_ptr; | ||
125 | typedef ushort *ushort_ptr; | ||
126 | typedef struct PKT PKT; | ||
127 | typedef struct LPB LPB; | ||
128 | typedef struct RUP RUP; | ||
129 | #endif | ||
130 | |||
131 | |||
132 | #endif /* __riotypes__ */ | ||
133 | |||
134 | /*********** end of file ***********/ | ||
135 | |||
diff --git a/drivers/char/rio/riowinif.h b/drivers/char/rio/riowinif.h new file mode 100644 index 000000000000..18a4f147edc2 --- /dev/null +++ b/drivers/char/rio/riowinif.h | |||
@@ -0,0 +1,1335 @@ | |||
1 | /************************************************************************/ | ||
2 | /* */ | ||
3 | /* Title : RIO Shared Memory Window Inteface */ | ||
4 | /* */ | ||
5 | /* Author : N.P.Vassallo */ | ||
6 | /* */ | ||
7 | /* Creation : 7th June 1999 */ | ||
8 | /* */ | ||
9 | /* Version : 1.0.0 */ | ||
10 | /* */ | ||
11 | /* Copyright : (c) Specialix International Ltd. 1999 * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * */ | ||
26 | /* Description : Prototypes, structures and definitions */ | ||
27 | /* describing RIO host card shared memory */ | ||
28 | /* window interface structures: */ | ||
29 | /* PARMMAP */ | ||
30 | /* RUP */ | ||
31 | /* PHB */ | ||
32 | /* LPB */ | ||
33 | /* PKT */ | ||
34 | /* */ | ||
35 | /************************************************************************/ | ||
36 | |||
37 | /* History... | ||
38 | |||
39 | 1.0.0 07/06/99 NPV Creation. (based on PARMMAP.H) | ||
40 | |||
41 | */ | ||
42 | |||
43 | #ifndef _riowinif_h /* If RIOWINDIF.H not already defined */ | ||
44 | #define _riowinif_h 1 | ||
45 | |||
46 | /***************************************************************************** | ||
47 | ******************************** ********************************* | ||
48 | ******************************** General ********************************* | ||
49 | ******************************** ********************************* | ||
50 | *****************************************************************************/ | ||
51 | |||
52 | #define TPNULL ((_u16)(0x8000)) | ||
53 | |||
54 | /***************************************************************************** | ||
55 | ******************************** ******************************** | ||
56 | ******************************** PARM_MAP ******************************** | ||
57 | ******************************** ******************************** | ||
58 | *****************************************************************************/ | ||
59 | |||
60 | /* The PARM_MAP structure defines global values relating to the Host Card / RTA | ||
61 | and is the main structure from which all other structures are referenced. */ | ||
62 | |||
63 | typedef struct _PARM_MAP | ||
64 | { | ||
65 | _u16 phb_ptr; /* 0x00 Pointer to the PHB array */ | ||
66 | _u16 phb_num_ptr; /* 0x02 Ptr to Number of PHB's */ | ||
67 | _u16 free_list; /* 0x04 Free List pointer */ | ||
68 | _u16 free_list_end; /* 0x06 Free List End pointer */ | ||
69 | _u16 q_free_list_ptr; /* 0x08 Ptr to Q_BUF variable */ | ||
70 | _u16 unit_id_ptr; /* 0x0A Unit Id */ | ||
71 | _u16 link_str_ptr; /* 0x0C Link Structure Array */ | ||
72 | _u16 bootloader_1; /* 0x0E 1st Stage Boot Loader */ | ||
73 | _u16 bootloader_2; /* 0x10 2nd Stage Boot Loader */ | ||
74 | _u16 port_route_map_ptr; /* 0x12 Port Route Map */ | ||
75 | _u16 route_ptr; /* 0x14 Route Map */ | ||
76 | _u16 map_present; /* 0x16 Route Map present */ | ||
77 | _u16 pkt_num; /* 0x18 Total number of packets */ | ||
78 | _u16 q_num; /* 0x1A Total number of Q packets */ | ||
79 | _u16 buffers_per_port; /* 0x1C Number of buffers per port */ | ||
80 | _u16 heap_size; /* 0x1E Initial size of heap */ | ||
81 | _u16 heap_left; /* 0x20 Current Heap left */ | ||
82 | _u16 error; /* 0x22 Error code */ | ||
83 | _u16 tx_max; /* 0x24 Max number of tx pkts per phb */ | ||
84 | _u16 rx_max; /* 0x26 Max number of rx pkts per phb */ | ||
85 | _u16 rx_limit; /* 0x28 For high / low watermarks */ | ||
86 | _u16 links; /* 0x2A Links to use */ | ||
87 | _u16 timer; /* 0x2C Interrupts per second */ | ||
88 | _u16 rups; /* 0x2E Pointer to the RUPs */ | ||
89 | _u16 max_phb; /* 0x30 Mostly for debugging */ | ||
90 | _u16 living; /* 0x32 Just increments!! */ | ||
91 | _u16 init_done; /* 0x34 Initialisation over */ | ||
92 | _u16 booting_link; /* 0x36 */ | ||
93 | _u16 idle_count; /* 0x38 Idle time counter */ | ||
94 | _u16 busy_count; /* 0x3A Busy counter */ | ||
95 | _u16 idle_control; /* 0x3C Control Idle Process */ | ||
96 | _u16 tx_intr; /* 0x3E TX interrupt pending */ | ||
97 | _u16 rx_intr; /* 0x40 RX interrupt pending */ | ||
98 | _u16 rup_intr; /* 0x42 RUP interrupt pending */ | ||
99 | |||
100 | } PARM_MAP; | ||
101 | |||
102 | /* Same thing again, but defined as offsets... */ | ||
103 | |||
104 | #define PM_phb_ptr 0x00 /* 0x00 Pointer to the PHB array */ | ||
105 | #define PM_phb_num_ptr 0x02 /* 0x02 Ptr to Number of PHB's */ | ||
106 | #define PM_free_list 0x04 /* 0x04 Free List pointer */ | ||
107 | #define PM_free_list_end 0x06 /* 0x06 Free List End pointer */ | ||
108 | #define PM_q_free_list_ptr 0x08 /* 0x08 Ptr to Q_BUF variable */ | ||
109 | #define PM_unit_id_ptr 0x0A /* 0x0A Unit Id */ | ||
110 | #define PM_link_str_ptr 0x0C /* 0x0C Link Structure Array */ | ||
111 | #define PM_bootloader_1 0x0E /* 0x0E 1st Stage Boot Loader */ | ||
112 | #define PM_bootloader_2 0x10 /* 0x10 2nd Stage Boot Loader */ | ||
113 | #define PM_port_route_map_ptr 0x12 /* 0x12 Port Route Map */ | ||
114 | #define PM_route_ptr 0x14 /* 0x14 Route Map */ | ||
115 | #define PM_map_present 0x16 /* 0x16 Route Map present */ | ||
116 | #define PM_pkt_num 0x18 /* 0x18 Total number of packets */ | ||
117 | #define PM_q_num 0x1A /* 0x1A Total number of Q packets */ | ||
118 | #define PM_buffers_per_port 0x1C /* 0x1C Number of buffers per port */ | ||
119 | #define PM_heap_size 0x1E /* 0x1E Initial size of heap */ | ||
120 | #define PM_heap_left 0x20 /* 0x20 Current Heap left */ | ||
121 | #define PM_error 0x22 /* 0x22 Error code */ | ||
122 | #define PM_tx_max 0x24 /* 0x24 Max number of tx pkts per phb */ | ||
123 | #define PM_rx_max 0x26 /* 0x26 Max number of rx pkts per phb */ | ||
124 | #define PM_rx_limit 0x28 /* 0x28 For high / low watermarks */ | ||
125 | #define PM_links 0x2A /* 0x2A Links to use */ | ||
126 | #define PM_timer 0x2C /* 0x2C Interrupts per second */ | ||
127 | #define PM_rups 0x2E /* 0x2E Pointer to the RUPs */ | ||
128 | #define PM_max_phb 0x30 /* 0x30 Mostly for debugging */ | ||
129 | #define PM_living 0x32 /* 0x32 Just increments!! */ | ||
130 | #define PM_init_done 0x34 /* 0x34 Initialisation over */ | ||
131 | #define PM_booting_link 0x36 /* 0x36 */ | ||
132 | #define PM_idle_count 0x38 /* 0x38 Idle time counter */ | ||
133 | #define PM_busy_count 0x3A /* 0x3A Busy counter */ | ||
134 | #define PM_idle_control 0x3C /* 0x3C Control Idle Process */ | ||
135 | #define PM_tx_intr 0x3E /* 0x4E TX interrupt pending */ | ||
136 | #define PM_rx_intr 0x40 /* 0x40 RX interrupt pending */ | ||
137 | #define PM_rup_intr 0x42 /* 0x42 RUP interrupt pending */ | ||
138 | #define sizeof_PARM_MAP 0x44 /* structure size = 0x44 */ | ||
139 | |||
140 | /* PARM_MAP.error definitions... */ | ||
141 | #define E_NO_ERROR 0x00 | ||
142 | #define E_PROCESS_NOT_INIT 0x01 | ||
143 | #define E_LINK_TIMEOUT 0x02 | ||
144 | #define E_NO_ROUTE 0x03 | ||
145 | #define E_CONFUSED 0x04 | ||
146 | #define E_HOME 0x05 | ||
147 | #define E_CSUM_FAIL 0x06 | ||
148 | #define E_DISCONNECTED 0x07 | ||
149 | #define E_BAD_RUP 0x08 | ||
150 | #define E_NO_VIRGIN 0x09 | ||
151 | #define E_BOOT_RUP_BUSY 0x10 | ||
152 | #define E_CHANALLOC 0x80 | ||
153 | #define E_POLL_ALLOC 0x81 | ||
154 | #define E_LTTWAKE 0x82 | ||
155 | #define E_LTT_ALLOC 0x83 | ||
156 | #define E_LRT_ALLOC 0x84 | ||
157 | #define E_CIRRUS 0x85 | ||
158 | #define E_MONITOR 0x86 | ||
159 | #define E_PHB_ALLOC 0x87 | ||
160 | #define E_ARRAY_ALLOC 0x88 | ||
161 | #define E_QBUF_ALLOC 0x89 | ||
162 | #define E_PKT_ALLOC 0x8a | ||
163 | #define E_GET_TX_Q_BUF 0x8b | ||
164 | #define E_GET_RX_Q_BUF 0x8c | ||
165 | #define E_MEM_OUT 0x8d | ||
166 | #define E_MMU_INIT 0x8e | ||
167 | #define E_LTT_INIT 0x8f | ||
168 | #define E_LRT_INIT 0x90 | ||
169 | #define E_LINK_RUN 0x91 | ||
170 | #define E_MONITOR_ALLOC 0x92 | ||
171 | #define E_MONITOR_INIT 0x93 | ||
172 | #define E_POLL_INIT 0x94 | ||
173 | |||
174 | /* PARM_MAP.links definitions... */ | ||
175 | #define RIO_LINK_ENABLE 0x80FF | ||
176 | |||
177 | /***************************************************************************** | ||
178 | ********************************** *********************************** | ||
179 | ********************************** RUP *********************************** | ||
180 | ********************************** *********************************** | ||
181 | *****************************************************************************/ | ||
182 | |||
183 | /* The RUP (Remote Unit Port) structure relates to the Remote Terminal Adapters | ||
184 | attached to the system and there is normally an array of MAX_RUPS (=16) structures | ||
185 | in a host card, defined by PARM_MAP->rup. */ | ||
186 | |||
187 | typedef struct _RUP | ||
188 | { | ||
189 | _u16 txpkt; /* 0x00 Outgoing packet */ | ||
190 | _u16 rxpkt; /* 0x02 ncoming packet */ | ||
191 | _u16 link; /* 0x04 Which link to send packet down ? */ | ||
192 | _u8 rup_dest_unit[2]; /* 0x06 Destination Unit */ | ||
193 | _u16 handshake; /* 0x08 Handshaking */ | ||
194 | _u16 timeout; /* 0x0A Timeout */ | ||
195 | _u16 status; /* 0x0C Status */ | ||
196 | _u16 txcontrol; /* 0x0E Transmit control */ | ||
197 | _u16 rxcontrol; /* 0x10 Receive control */ | ||
198 | |||
199 | } RUP; | ||
200 | |||
201 | /* Same thing again, but defined as offsets... */ | ||
202 | |||
203 | #define RUP_txpkt 0x00 /* 0x00 Outgoing packet */ | ||
204 | #define RUP_rxpkt 0x02 /* 0x02 Incoming packet */ | ||
205 | #define RUP_link 0x04 /* 0x04 Which link to send packet down ? */ | ||
206 | #define RUP_rup_dest_unit 0x06 /* 0x06 Destination Unit */ | ||
207 | #define RUP_handshake 0x08 /* 0x08 Handshaking */ | ||
208 | #define RUP_timeout 0x0A /* 0x0A Timeout */ | ||
209 | #define RUP_status 0x0C /* 0x0C Status */ | ||
210 | #define RUP_txcontrol 0x0E /* 0x0E Transmit control */ | ||
211 | #define RUP_rxcontrol 0x10 /* 0x10 Receive control */ | ||
212 | #define sizeof_RUP 0x12 /* structure size = 0x12 */ | ||
213 | |||
214 | #define MAX_RUP 16 | ||
215 | |||
216 | /* RUP.txcontrol definitions... */ | ||
217 | #define TX_RUP_INACTIVE 0 /* Nothing to transmit */ | ||
218 | #define TX_PACKET_READY 1 /* Transmit packet ready */ | ||
219 | #define TX_LOCK_RUP 2 /* Transmit side locked */ | ||
220 | |||
221 | /* RUP.txcontrol definitions... */ | ||
222 | #define RX_RUP_INACTIVE 0 /* Nothing received */ | ||
223 | #define RX_PACKET_READY 1 /* Packet received */ | ||
224 | |||
225 | #define RUP_NO_OWNER 0xFF /* RUP not owned by any process */ | ||
226 | |||
227 | /***************************************************************************** | ||
228 | ********************************** *********************************** | ||
229 | ********************************** PHB *********************************** | ||
230 | ********************************** *********************************** | ||
231 | *****************************************************************************/ | ||
232 | |||
233 | /* The PHB (Port Header Block) structure relates to the serial ports attached | ||
234 | to the system and there is normally an array of MAX_PHBS (=128) structures | ||
235 | in a host card, defined by PARM_MAP->phb_ptr and PARM_MAP->phb_num_ptr. */ | ||
236 | |||
237 | typedef struct _PHB | ||
238 | { | ||
239 | _u16 source; /* 0x00 Location of the PHB in the host card */ | ||
240 | _u16 handshake; /* 0x02 Used to manage receive packet flow control */ | ||
241 | _u16 status; /* 0x04 Internal port transmit/receive status */ | ||
242 | _u16 timeout; /* 0x06 Time period to wait for an ACK */ | ||
243 | _u16 link; /* 0x08 The host link associated with the PHB */ | ||
244 | _u16 destination; /* 0x0A Location of the remote port on the network */ | ||
245 | |||
246 | _u16 tx_start; /* 0x0C first entry in the packet array for transmit packets */ | ||
247 | _u16 tx_end; /* 0x0E last entry in the packet array for transmit packets */ | ||
248 | _u16 tx_add; /* 0x10 position in the packet array for new transmit packets */ | ||
249 | _u16 tx_remove; /* 0x12 current position in the packet pointer array */ | ||
250 | |||
251 | _u16 rx_start; /* 0x14 first entry in the packet array for receive packets */ | ||
252 | _u16 rx_end; /* 0x16 last entry in the packet array for receive packets */ | ||
253 | _u16 rx_add; /* 0x18 position in the packet array for new receive packets */ | ||
254 | _u16 rx_remove; /* 0x1A current position in the packet pointer array */ | ||
255 | |||
256 | } PHB; | ||
257 | |||
258 | /* Same thing again, but defined as offsets... */ | ||
259 | |||
260 | #define PHB_source 0x00 /* 0x00 Location of the PHB in the host card */ | ||
261 | #define PHB_handshake 0x02 /* 0x02 Used to manage receive packet flow control */ | ||
262 | #define PHB_status 0x04 /* 0x04 Internal port transmit/receive status */ | ||
263 | #define PHB_timeout 0x06 /* 0x06 Time period to wait for an ACK */ | ||
264 | #define PHB_link 0x08 /* 0x08 The host link associated with the PHB */ | ||
265 | #define PHB_destination 0x0A /* 0x0A Location of the remote port on the network */ | ||
266 | #define PHB_tx_start 0x0C /* 0x0C first entry in the packet array for transmit packets */ | ||
267 | #define PHB_tx_end 0x0E /* 0x0E last entry in the packet array for transmit packets */ | ||
268 | #define PHB_tx_add 0x10 /* 0x10 position in the packet array for new transmit packets */ | ||
269 | #define PHB_tx_remove 0x12 /* 0x12 current position in the packet pointer array */ | ||
270 | #define PHB_rx_start 0x14 /* 0x14 first entry in the packet array for receive packets */ | ||
271 | #define PHB_rx_end 0x16 /* 0x16 last entry in the packet array for receive packets */ | ||
272 | #define PHB_rx_add 0x18 /* 0x18 position in the packet array for new receive packets */ | ||
273 | #define PHB_rx_remove 0x1A /* 0x1A current position in the packet pointer array */ | ||
274 | #define sizeof_PHB 0x1C /* structure size = 0x1C */ | ||
275 | |||
276 | /* PHB.handshake definitions... */ | ||
277 | #define PHB_HANDSHAKE_SET 0x0001 /* Set by LRT */ | ||
278 | #define PHB_HANDSHAKE_RESET 0x0002 /* Set by ISR / driver */ | ||
279 | #define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET|PHB_HANDSHAKE_SET) | ||
280 | /* Reset by ltt */ | ||
281 | |||
282 | #define MAX_PHB 128 /* range 0-127 */ | ||
283 | |||
284 | /***************************************************************************** | ||
285 | ********************************** *********************************** | ||
286 | ********************************** LPB *********************************** | ||
287 | ********************************** *********************************** | ||
288 | *****************************************************************************/ | ||
289 | |||
290 | /* The LPB (Link Parameter Block) structure relates to a RIO Network Link | ||
291 | and there is normally an array of MAX_LINKS (=4) structures in a host card, | ||
292 | defined by PARM_MAP->link_str_ptr. */ | ||
293 | |||
294 | typedef struct _LPB | ||
295 | { | ||
296 | _u16 link_number; /* 0x00 Link Number */ | ||
297 | _u16 in_ch; /* 0x02 Link In Channel */ | ||
298 | _u16 out_ch; /* 0x04 Link Out Channel */ | ||
299 | _u8 attached_serial[4]; /* 0x06 Attached serial number */ | ||
300 | _u8 attached_host_serial[4];/* 0x0A Serial number of Host who booted other end */ | ||
301 | _u16 descheduled; /* 0x0E Currently Descheduled */ | ||
302 | _u16 state; /* 0x10 Current state */ | ||
303 | _u16 send_poll; /* 0x12 Send a Poll Packet */ | ||
304 | _u16 ltt_p; /* 0x14 Process Descriptor */ | ||
305 | _u16 lrt_p; /* 0x16 Process Descriptor */ | ||
306 | _u16 lrt_status; /* 0x18 Current lrt status */ | ||
307 | _u16 ltt_status; /* 0x1A Current ltt status */ | ||
308 | _u16 timeout; /* 0x1C Timeout value */ | ||
309 | _u16 topology; /* 0x1E Topology bits */ | ||
310 | _u16 mon_ltt; /* 0x20 */ | ||
311 | _u16 mon_lrt; /* 0x22 */ | ||
312 | _u16 num_pkts; /* 0x24 */ | ||
313 | _u16 add_packet_list; /* 0x26 Add packets to here */ | ||
314 | _u16 remove_packet_list; /* 0x28 Send packets from here */ | ||
315 | |||
316 | _u16 lrt_fail_chan; /* 0x2A Lrt's failure channel */ | ||
317 | _u16 ltt_fail_chan; /* 0x2C Ltt's failure channel */ | ||
318 | |||
319 | RUP rup; /* 0x2E RUP structure for HOST to driver comms */ | ||
320 | RUP link_rup; /* 0x40 RUP for the link (POLL, topology etc.) */ | ||
321 | _u16 attached_link; /* 0x52 Number of attached link */ | ||
322 | _u16 csum_errors; /* 0x54 csum errors */ | ||
323 | _u16 num_disconnects; /* 0x56 number of disconnects */ | ||
324 | _u16 num_sync_rcvd; /* 0x58 # sync's received */ | ||
325 | _u16 num_sync_rqst; /* 0x5A # sync requests */ | ||
326 | _u16 num_tx; /* 0x5C Num pkts sent */ | ||
327 | _u16 num_rx; /* 0x5E Num pkts received */ | ||
328 | _u16 module_attached; /* 0x60 Module tpyes of attached */ | ||
329 | _u16 led_timeout; /* 0x62 LED timeout */ | ||
330 | _u16 first_port; /* 0x64 First port to service */ | ||
331 | _u16 last_port; /* 0x66 Last port to service */ | ||
332 | |||
333 | } LPB; | ||
334 | |||
335 | /* Same thing again, but defined as offsets... */ | ||
336 | |||
337 | #define LPB_link_number 0x00 /* 0x00 Link Number */ | ||
338 | #define LPB_in_ch 0x02 /* 0x02 Link In Channel */ | ||
339 | #define LPB_out_ch 0x04 /* 0x04 Link Out Channel */ | ||
340 | #define LPB_attached_serial 0x06 /* 0x06 Attached serial number */ | ||
341 | #define LPB_attached_host_serial 0x0A /* 0x0A Serial number of Host who booted other end */ | ||
342 | #define LPB_descheduled 0x0E /* 0x0E Currently Descheduled */ | ||
343 | #define LPB_state 0x10 /* 0x10 Current state */ | ||
344 | #define LPB_send_poll 0x12 /* 0x12 Send a Poll Packet */ | ||
345 | #define LPB_ltt_p 0x14 /* 0x14 Process Descriptor */ | ||
346 | #define LPB_lrt_p 0x16 /* 0x16 Process Descriptor */ | ||
347 | #define LPB_lrt_status 0x18 /* 0x18 Current lrt status */ | ||
348 | #define LPB_ltt_status 0x1A /* 0x1A Current ltt status */ | ||
349 | #define LPB_timeout 0x1C /* 0x1C Timeout value */ | ||
350 | #define LPB_topology 0x1E /* 0x1E Topology bits */ | ||
351 | #define LPB_mon_ltt 0x20 /* 0x20 */ | ||
352 | #define LPB_mon_lrt 0x22 /* 0x22 */ | ||
353 | #define LPB_num_pkts 0x24 /* 0x24 */ | ||
354 | #define LPB_add_packet_list 0x26 /* 0x26 Add packets to here */ | ||
355 | #define LPB_remove_packet_list 0x28 /* 0x28 Send packets from here */ | ||
356 | #define LPB_lrt_fail_chan 0x2A /* 0x2A Lrt's failure channel */ | ||
357 | #define LPB_ltt_fail_chan 0x2C /* 0x2C Ltt's failure channel */ | ||
358 | #define LPB_rup 0x2E /* 0x2E RUP structure for HOST to driver comms */ | ||
359 | #define LPB_link_rup 0x40 /* 0x40 RUP for the link (POLL, topology etc.) */ | ||
360 | #define LPB_attached_link 0x52 /* 0x52 Number of attached link */ | ||
361 | #define LPB_csum_errors 0x54 /* 0x54 csum errors */ | ||
362 | #define LPB_num_disconnects 0x56 /* 0x56 number of disconnects */ | ||
363 | #define LPB_num_sync_rcvd 0x58 /* 0x58 # sync's received */ | ||
364 | #define LPB_num_sync_rqst 0x5A /* 0x5A # sync requests */ | ||
365 | #define LPB_num_tx 0x5C /* 0x5C Num pkts sent */ | ||
366 | #define LPB_num_rx 0x5E /* 0x5E Num pkts received */ | ||
367 | #define LPB_module_attached 0x60 /* 0x60 Module tpyes of attached */ | ||
368 | #define LPB_led_timeout 0x62 /* 0x62 LED timeout */ | ||
369 | #define LPB_first_port 0x64 /* 0x64 First port to service */ | ||
370 | #define LPB_last_port 0x66 /* 0x66 Last port to service */ | ||
371 | #define sizeof_LPB 0x68 /* structure size = 0x68 */ | ||
372 | |||
373 | #define LINKS_PER_UNIT 4 /* number of links from a host */ | ||
374 | |||
375 | /***************************************************************************** | ||
376 | ******************************** ******************************* | ||
377 | ******************************** FREE_LIST ******************************* | ||
378 | ******************************** ******************************* | ||
379 | *****************************************************************************/ | ||
380 | |||
381 | /* Used to overlay packet headers when allocating/freeing packets from the free list */ | ||
382 | |||
383 | typedef struct _FREE_LIST | ||
384 | { | ||
385 | _u16 next; /* 0x00 offset of next list item */ | ||
386 | _u16 prev; /* 0x02 offset of previous list item */ | ||
387 | |||
388 | } FREE_LIST; | ||
389 | |||
390 | /* Same thing again, but defined as offsets... */ | ||
391 | |||
392 | #define FL_next 0x00 /* 0x00 offset of next list item */ | ||
393 | #define FL_prev 0x02 /* 0x02 offset of previous list item */ | ||
394 | |||
395 | /***************************************************************************** | ||
396 | ********************************** *********************************** | ||
397 | ********************************** PKT *********************************** | ||
398 | ********************************** *********************************** | ||
399 | *****************************************************************************/ | ||
400 | |||
401 | /* The PKT is the main unit of communication between Host Cards and RTAs across | ||
402 | the RIO network. */ | ||
403 | |||
404 | #define PKT_MAX_DATA_LEN 72 /* Size of packet data */ | ||
405 | |||
406 | typedef struct _PKT | ||
407 | { | ||
408 | _u8 dest_unit; /* 0x00 Destination Unit Id */ | ||
409 | _u8 dest_port; /* 0x01 Destination Port */ | ||
410 | _u8 src_unit; /* 0x02 Source Unit Id */ | ||
411 | _u8 src_port; /* 0x03 Source Port */ | ||
412 | _u8 len; /* 0x04 Length (in bytes) of data field */ | ||
413 | _u8 control; /* 0x05 */ | ||
414 | _u8 data[PKT_MAX_DATA_LEN]; /* 0x06 Actual data */ | ||
415 | _u16 csum; /* 0x4E C-SUM */ | ||
416 | |||
417 | } PKT; | ||
418 | |||
419 | /* Same thing again, but defined as offsets... */ | ||
420 | |||
421 | #define PKT_dest_unit 0x00 /* 0x00 Destination Unit Id */ | ||
422 | #define PKT_dest_port 0x01 /* 0x01 Destination Port */ | ||
423 | #define PKT_src_unit 0x02 /* 0x02 Source Unit Id */ | ||
424 | #define PKT_src_port 0x03 /* 0x03 Source Port */ | ||
425 | #define PKT_len 0x04 /* 0x04 Length (in bytes) of data field */ | ||
426 | #define PKT_control 0x05 /* 0x05 */ | ||
427 | #define PKT_data 0x06 /* 0x06 Actual data */ | ||
428 | #define PKT_csum 0x4E /* 0x4E C-SUM */ | ||
429 | #define sizeof_PKT 0x50 /* structure size = 0x50 */ | ||
430 | |||
431 | /* PKT.len definitions... */ | ||
432 | #define PKT_CMD_BIT 0x80 | ||
433 | #define PKT_CMD_DATA 0x80 | ||
434 | #define PKT_LEN_MASK 0x7F | ||
435 | |||
436 | /* PKT.control definitions... */ | ||
437 | #define PKT_ACK 0x40 | ||
438 | #define PKT_TGL 0x20 | ||
439 | #define DATA_WNDW 0x10 | ||
440 | #define PKT_TTL_MASK 0x0F | ||
441 | #define MAX_TTL 0x0F | ||
442 | |||
443 | /***************************************************************************** | ||
444 | ***************************** **************************** | ||
445 | ***************************** Control Packets **************************** | ||
446 | ***************************** **************************** | ||
447 | *****************************************************************************/ | ||
448 | |||
449 | /* The following definitions and structures define the control packets sent | ||
450 | between the driver and RIO Ports, RTAs and Host Cards. */ | ||
451 | |||
452 | #define PRE_EMPTIVE 0x80 /* Pre-emptive command (sent via port's RUP) */ | ||
453 | |||
454 | /* "in-band" and "pre-emptive" port commands... */ | ||
455 | #define OPEN 0x00 /* Driver->RIO Open a port */ | ||
456 | #define CONFIG 0x01 /* Driver->RIO Configure a port */ | ||
457 | #define MOPEN 0x02 /* Driver->RIO Modem open (wait for DCD) */ | ||
458 | #define CLOSE 0x03 /* Driver->RIO Close a port */ | ||
459 | #define WFLUSH (0x04|PRE_EMPTIVE) /* Driver->RIO Write flush */ | ||
460 | #define RFLUSH (0x05|PRE_EMPTIVE) /* Driver->RIO Read flush */ | ||
461 | #define RESUME (0x06|PRE_EMPTIVE) /* Driver->RIO Behave as if XON received */ | ||
462 | #define SBREAK 0x07 /* Driver->RIO Start break */ | ||
463 | #define EBREAK 0x08 /* Driver->RIO End break */ | ||
464 | #define SUSPEND (0x09|PRE_EMPTIVE) /* Driver->RIO Behave as if XOFF received */ | ||
465 | #define FCLOSE (0x0A|PRE_EMPTIVE) /* Driver->RIO Force close */ | ||
466 | #define XPRINT 0x0B /* Driver->RIO Xprint packet */ | ||
467 | #define MBIS (0x0C|PRE_EMPTIVE) /* Driver->RIO Set modem lines */ | ||
468 | #define MBIC (0x0D|PRE_EMPTIVE) /* Driver->RIO Clear modem lines */ | ||
469 | #define MSET (0x0E|PRE_EMPTIVE) /* Driver->RIO Set modem lines */ | ||
470 | #define PCLOSE 0x0F /* Driver->RIO Pseudo close */ | ||
471 | #define MGET (0x10|PRE_EMPTIVE) /* Driver->RIO Force update of modem status */ | ||
472 | #define MEMDUMP (0x11|PRE_EMPTIVE) /* Driver->RIO DEBUG request for RTA memory */ | ||
473 | #define READ_REGISTER (0x12|PRE_EMPTIVE) /* Driver->RIO DEBUG read CD1400 register */ | ||
474 | |||
475 | /* Remote Unit Port (RUP) packet definitions... (specified in PKT.dest_unit and PKT.src_unit) */ | ||
476 | #define SYNC_RUP 0xFF /* Download internal */ | ||
477 | #define COMMAND_RUP 0xFE /* Command ack/status */ | ||
478 | #define ERROR_RUP 0xFD /* Download internal */ | ||
479 | #define POLL_RUP 0xFC /* Download internal */ | ||
480 | #define BOOT_RUP 0xFB /* Used to boot RTAs */ | ||
481 | #define ROUTE_RUP 0xFA /* Used to specify routing/topology */ | ||
482 | #define STATUS_RUP 0xF9 /* Not used */ | ||
483 | #define POWER_RUP 0xF8 /* Download internal */ | ||
484 | |||
485 | /* COMMAND_RUP definitions... */ | ||
486 | #define COMPLETE (0x20|PRE_EMPTIVE) /* RIO->Driver Command complete */ | ||
487 | #define BREAK_RECEIVED (0x21|PRE_EMPTIVE) /* RIO->Driver Break received */ | ||
488 | #define MODEM_STATUS (0x22|PRE_EMPTIVE) /* RIO->Driver Modem status change */ | ||
489 | |||
490 | /* BOOT_RUP definitions... */ | ||
491 | #define BOOT_REQUEST 0x00 /* RIO->Driver Request for boot */ | ||
492 | #define BOOT_ABORT 0x01 /* Driver->RIO Abort a boot */ | ||
493 | #define BOOT_SEQUENCE 0x02 /* Driver->RIO Packet with firmware details */ | ||
494 | #define BOOT_COMPLETED 0x03 /* RIO->Driver Boot completed */ | ||
495 | #define IFOAD 0x2F /* Driver->RIO Shutdown/Reboot RTA (Fall Over And Die) */ | ||
496 | #define IDENTIFY 0x30 /* Driver->RIO Identify RTA */ | ||
497 | #define ZOMBIE 0x31 /* Driver->RIO Shutdown/Flash LEDs */ | ||
498 | #define UFOAD 0x32 /* Driver->RIO Shutdown/Reboot neighbouring RTA */ | ||
499 | #define IWAIT 0x33 /* Driver->RIO Pause booting process */ | ||
500 | |||
501 | /* ROUTE_RUP definitions... */ | ||
502 | #define ROUTE_REQUEST 0x00 /* RIO->Driver Request an ID */ | ||
503 | #define ROUTE_FOAD 0x01 /* Driver->RIO Shutdown/reboot RTA */ | ||
504 | #define ROUTE_ALREADY 0x02 /* Driver->RIO Not used */ | ||
505 | #define ROUTE_USED 0x03 /* Driver->RIO Not used */ | ||
506 | #define ROUTE_ALLOCATE 0x04 /* Driver->RIO Allocate RTA RUP numbers */ | ||
507 | #define ROUTE_REQ_TOP 0x05 /* Driver->RIO Not used */ | ||
508 | #define ROUTE_TOPOLOGY 0x06 /* RIO->Driver Route/Topology status */ | ||
509 | |||
510 | /***************************************************************************** | ||
511 | ********************************** ********************************** | ||
512 | ********************************** OPEN ********************************** | ||
513 | ********************************** ********************************** | ||
514 | *****************************************************************************/ | ||
515 | |||
516 | /* (Driver->RIO,in-band) | ||
517 | |||
518 | Sent to open a port. | ||
519 | Structure of configuration info used with OPEN, CONFIG and MOPEN packets... */ | ||
520 | |||
521 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
522 | #define PKT_Cor1 (PKT_Data+1) /* Channel Option Register 1 */ | ||
523 | #define PKT_Cor2 (PKT_Data+2) /* Channel Option Register 2 */ | ||
524 | #define PKT_Cor4 (PKT_Data+3) /* Channel Option Register 4 */ | ||
525 | #define PKT_Cor5 (PKT_Data+4) /* Channel Option Register 5 */ | ||
526 | #define PKT_TxXon (PKT_Data+5) /* Transmit XON character */ | ||
527 | #define PKT_TxXoff (PKT_Data+6) /* Transmit XOFF character */ | ||
528 | #define PKT_RxXon (PKT_Data+7) /* Receive XON character */ | ||
529 | #define PKT_RxXoff (PKT_Data+8) /* Receive XOFF character */ | ||
530 | #define PKT_Lnext (PKT_Data+9) /* Lnext character */ | ||
531 | #define PKT_TxBaud (PKT_Data+10) /* Transmit baud rate */ | ||
532 | #define PKT_RxBaud (PKT_Data+11) /* Receive baud rate */ | ||
533 | |||
534 | /* COR1 definitions... */ | ||
535 | #define COR1_PARITY 0xE0 /* Parity mask */ | ||
536 | #define COR1_NONE 0x00 /* No parity */ | ||
537 | #define COR1_SPACE 0x20 /* Space parity */ | ||
538 | #define COR1_EVEN 0x40 /* Even parity */ | ||
539 | #define COR1_MARK 0xA0 /* Mark parity */ | ||
540 | #define COR1_ODD 0xC0 /* Odd parity */ | ||
541 | |||
542 | #define COR1_STOPBITS 0x0C /* Stop bits mask */ | ||
543 | #define COR1_STOP1 0x00 /* 1 stop bit */ | ||
544 | #define COR1_STOP1_5 0x04 /* 1.5 stop bits */ | ||
545 | #define COR1_STOP2 0x08 /* 2 stop bits */ | ||
546 | |||
547 | #define COR1_DATABITS 0x03 /* Data bits mask */ | ||
548 | #define COR1_DATA5 0x00 /* 5 data bits */ | ||
549 | #define COR1_DATA6 0x01 /* 6 data bits */ | ||
550 | #define COR1_DATA7 0x02 /* 7 data bits */ | ||
551 | #define COR1_DATA8 0x03 /* 8 data bits */ | ||
552 | |||
553 | /* COR2 definitions... */ | ||
554 | #define COR2_XON_TXFLOW 0x40 /* XON/XOFF Transmit Flow */ | ||
555 | #define COR2_XANY_TXFLOW 0xC0 /* XON/XANY Transmit Flow */ | ||
556 | #define COR2_HUPCL 0x20 /* Hang Up On Close */ | ||
557 | #define COR2_DSR_TXFLOW 0x08 /* DSR Transmit Flow Control */ | ||
558 | #define COR2_RTS_RXFLOW 0x04 /* RTS Receive Flow Control */ | ||
559 | #define COR2_CTS_TXFLOW 0x02 /* CTS Transmit Flow Control */ | ||
560 | #define COR2_XON_RXFLOW 0x01 /* XON/XOFF Receive Flow */ | ||
561 | |||
562 | /* COR4 definition... */ | ||
563 | #define COR4_IGNCR 0x80 /* Discard received CR */ | ||
564 | #define COR4_ICRNL 0x40 /* Map received CR -> NL */ | ||
565 | #define COR4_INLCR 0x20 /* Map received NL -> CR */ | ||
566 | #define COR4_IGNBRK 0x10 /* Ignore Received Break */ | ||
567 | #define COR4_NBRKINT 0x08 /* No interrupt on rx Break */ | ||
568 | #define COR4_IGNPAR 0x04 /* ignore rx parity error chars */ | ||
569 | #define COR4_PARMRK 0x02 /* Mark rx parity error chars */ | ||
570 | #define COR4_RAISEMOD 0x01 /* Raise modem lines on !0 baud */ | ||
571 | |||
572 | /* COR5 definitions... */ | ||
573 | #define COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */ | ||
574 | #define COR5_LNE 0x40 /* Enable LNEXT processing */ | ||
575 | #define COR5_CMOE 0x20 /* Match good & error characters */ | ||
576 | #define COR5_TAB3 0x10 /* TAB3 mode */ | ||
577 | #define COR5_TSTATE_ON 0x08 /* Enable tbusy/tstop monitoring */ | ||
578 | #define COR5_TSTATE_OFF 0x04 /* Disable tbusy/tstop monitoring */ | ||
579 | #define COR5_ONLCR 0x02 /* NL -> CR NL on output */ | ||
580 | #define COR5_OCRNL 0x01 /* CR -> NL on output */ | ||
581 | |||
582 | /* RxBaud and TxBaud definitions... */ | ||
583 | #define RIO_B0 0x00 /* RTS / DTR signals dropped */ | ||
584 | #define RIO_B50 0x01 /* 50 baud */ | ||
585 | #define RIO_B75 0x02 /* 75 baud */ | ||
586 | #define RIO_B110 0x03 /* 110 baud */ | ||
587 | #define RIO_B134 0x04 /* 134.5 baud */ | ||
588 | #define RIO_B150 0x05 /* 150 baud */ | ||
589 | #define RIO_B200 0x06 /* 200 baud */ | ||
590 | #define RIO_B300 0x07 /* 300 baud */ | ||
591 | #define RIO_B600 0x08 /* 600 baud */ | ||
592 | #define RIO_B1200 0x09 /* 1200 baud */ | ||
593 | #define RIO_B1800 0x0A /* 1800 baud */ | ||
594 | #define RIO_B2400 0x0B /* 2400 baud */ | ||
595 | #define RIO_B4800 0x0C /* 4800 baud */ | ||
596 | #define RIO_B9600 0x0D /* 9600 baud */ | ||
597 | #define RIO_B19200 0x0E /* 19200 baud */ | ||
598 | #define RIO_B38400 0x0F /* 38400 baud */ | ||
599 | #define RIO_B56000 0x10 /* 56000 baud */ | ||
600 | #define RIO_B57600 0x11 /* 57600 baud */ | ||
601 | #define RIO_B64000 0x12 /* 64000 baud */ | ||
602 | #define RIO_B115200 0x13 /* 115200 baud */ | ||
603 | #define RIO_B2000 0x14 /* 2000 baud */ | ||
604 | |||
605 | /***************************************************************************** | ||
606 | ********************************* ********************************* | ||
607 | ********************************* CONFIG ********************************* | ||
608 | ********************************* ********************************* | ||
609 | *****************************************************************************/ | ||
610 | |||
611 | /* (Driver->RIO,in-band) | ||
612 | |||
613 | CONFIG is sent from the driver to configure an already opened port. | ||
614 | Packet structure is same as OPEN. */ | ||
615 | |||
616 | /***************************************************************************** | ||
617 | ********************************* ********************************** | ||
618 | ********************************* MOPEN ********************************** | ||
619 | ********************************* ********************************** | ||
620 | *****************************************************************************/ | ||
621 | |||
622 | /* (Driver->RIO,in-band) | ||
623 | |||
624 | MOPEN is sent from the driver to open a port attached to a modem. (in-band) | ||
625 | Packet structure is same as OPEN. */ | ||
626 | |||
627 | /***************************************************************************** | ||
628 | ********************************* ********************************** | ||
629 | ********************************* CLOSE ********************************** | ||
630 | ********************************* ********************************** | ||
631 | *****************************************************************************/ | ||
632 | |||
633 | /* (Driver->RIO,in-band) | ||
634 | |||
635 | CLOSE is sent from the driver to close a previously opened port. | ||
636 | No parameters. | ||
637 | */ | ||
638 | #if 0 | ||
639 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
640 | #endif | ||
641 | /***************************************************************************** | ||
642 | ********************************* ********************************* | ||
643 | ********************************* WFLUSH ********************************* | ||
644 | ********************************* ********************************* | ||
645 | *****************************************************************************/ | ||
646 | |||
647 | /* (Driver->RIO,pre-emptive) | ||
648 | |||
649 | WFLUSH is sent pre-emptively from the driver to flush the write buffers and | ||
650 | packets of a port. (pre-emptive) | ||
651 | |||
652 | WFLUSH is also sent in-band from the driver to a port as a marker to end | ||
653 | write flushing previously started by a pre-emptive WFLUSH packet. (in-band) | ||
654 | */ | ||
655 | #if 0 | ||
656 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
657 | #endif | ||
658 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
659 | |||
660 | /***************************************************************************** | ||
661 | ********************************* ********************************* | ||
662 | ********************************* RFLUSH ********************************* | ||
663 | ********************************* ********************************* | ||
664 | *****************************************************************************/ | ||
665 | |||
666 | /* (Driver->RIO,pre-emptive) | ||
667 | |||
668 | RFLUSH is sent pre-emptively from the driver to flush the read buffers and | ||
669 | packets of a port. | ||
670 | */ | ||
671 | #if 0 | ||
672 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
673 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
674 | #endif | ||
675 | |||
676 | /***************************************************************************** | ||
677 | ********************************* ********************************* | ||
678 | ********************************* RESUME ********************************* | ||
679 | ********************************* ********************************* | ||
680 | *****************************************************************************/ | ||
681 | |||
682 | /* (Driver->RIO,pre-emptive) | ||
683 | |||
684 | RESUME is sent pre-emptively from the driver to cause a port to resume | ||
685 | transmission of data if blocked by XOFF. (as if XON had been received) | ||
686 | */ | ||
687 | #if 0 | ||
688 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
689 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
690 | #endif | ||
691 | |||
692 | /***************************************************************************** | ||
693 | ********************************* ********************************* | ||
694 | ********************************* SBREAK ********************************* | ||
695 | ********************************* ********************************* | ||
696 | *****************************************************************************/ | ||
697 | |||
698 | /* (Driver->RIO,in-band) | ||
699 | |||
700 | SBREAK is sent in-band from the driver to a port to suspend data and start | ||
701 | break signal transmission. | ||
702 | |||
703 | If the break delay is 0, the break signal will be acknowledged with a | ||
704 | RUP_COMMAND, COMPLETE packet and continue until an EBREAK packet is received. | ||
705 | |||
706 | Otherwise, there is no acknowledgement and the break signal will last for the | ||
707 | specified number of mS. | ||
708 | */ | ||
709 | #if 0 | ||
710 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
711 | #endif | ||
712 | #define PKT_BreakDelay (PKT_Data+1) /* Break delay in mS */ | ||
713 | |||
714 | /***************************************************************************** | ||
715 | ********************************* ********************************* | ||
716 | ********************************* EBREAK ********************************* | ||
717 | ********************************* ********************************* | ||
718 | *****************************************************************************/ | ||
719 | |||
720 | /* (Driver->RIO,in-band) | ||
721 | |||
722 | EBREAK is sent in-band from the driver to a port to stop transmission of a | ||
723 | break signal. | ||
724 | |||
725 | No parameters. */ | ||
726 | |||
727 | /***************************************************************************** | ||
728 | ********************************* ******************************** | ||
729 | ********************************* SUSPEND ******************************** | ||
730 | ********************************* ******************************** | ||
731 | *****************************************************************************/ | ||
732 | |||
733 | /* (Driver->RIO,pre-emptive) | ||
734 | |||
735 | SUSPEND is sent pre-emptively from the driver to cause a port to suspend | ||
736 | transmission of data. (as if XOFF had been received) | ||
737 | */ | ||
738 | #if 0 | ||
739 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
740 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
741 | #endif | ||
742 | |||
743 | /***************************************************************************** | ||
744 | ********************************* ********************************* | ||
745 | ********************************* FCLOSE ********************************* | ||
746 | ********************************* ********************************* | ||
747 | *****************************************************************************/ | ||
748 | |||
749 | /* (Driver->RIO,pre-emptive) | ||
750 | |||
751 | FCLOSE is sent pre-emptively from the driver to force close a port. | ||
752 | A force close flushes receive and transmit queues, and also lowers all output | ||
753 | modem signals if the COR5_HUPCL (Hang Up On Close) flag is set. | ||
754 | */ | ||
755 | #if 0 | ||
756 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
757 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
758 | #endif | ||
759 | |||
760 | /***************************************************************************** | ||
761 | ********************************* ********************************* | ||
762 | ********************************* XPRINT ********************************* | ||
763 | ********************************* ********************************* | ||
764 | *****************************************************************************/ | ||
765 | |||
766 | /* (Driver->RIO,in-band) | ||
767 | |||
768 | XPRINT is sent as a normal I/O data packet except that the PKT_CMD_BIT of | ||
769 | the "len" field is set, and the first "data" byte is XPRINT. | ||
770 | |||
771 | The I/O data in the XPRINT packet will contain the following: | ||
772 | - Transparent Print Start Sequence | ||
773 | - Transparent Print Data | ||
774 | - Transparent Print Stop Sequence. | ||
775 | */ | ||
776 | #if 0 | ||
777 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
778 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
779 | #endif | ||
780 | |||
781 | /***************************************************************************** | ||
782 | ********************************** ********************************** | ||
783 | ********************************** MBIS ********************************** | ||
784 | ********************************** ********************************** | ||
785 | *****************************************************************************/ | ||
786 | |||
787 | /* (Driver->RIO,pre-emptive) | ||
788 | |||
789 | MBIS is sent pre-emptively from the driver to set a port's modem signals. | ||
790 | */ | ||
791 | #if 0 | ||
792 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
793 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
794 | #endif | ||
795 | #define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */ | ||
796 | |||
797 | /* ModemSet definitions... */ | ||
798 | #define MBIS_RTS 0x01 /* RTS modem signal */ | ||
799 | #define MBIS_DTR 0x02 /* DTR modem signal */ | ||
800 | |||
801 | /***************************************************************************** | ||
802 | ********************************** ********************************** | ||
803 | ********************************** MBIC ********************************** | ||
804 | ********************************** ********************************** | ||
805 | *****************************************************************************/ | ||
806 | |||
807 | /* (Driver->RIO,pre-emptive) | ||
808 | |||
809 | MBIC is sent pre-emptively from the driver to clear a port's modem signals. | ||
810 | */ | ||
811 | #if 0 | ||
812 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
813 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
814 | #endif | ||
815 | |||
816 | #define PKT_ModemClear (PKT_Data+4) /* Modem clear signals mask */ | ||
817 | |||
818 | /* ModemClear definitions... */ | ||
819 | #define MBIC_RTS 0x01 /* RTS modem signal */ | ||
820 | #define MBIC_DTR 0x02 /* DTR modem signal */ | ||
821 | |||
822 | /***************************************************************************** | ||
823 | ********************************** ********************************** | ||
824 | ********************************** MSET ********************************** | ||
825 | ********************************** ********************************** | ||
826 | *****************************************************************************/ | ||
827 | |||
828 | /* (Driver->RIO,pre-emptive) | ||
829 | |||
830 | MSET is sent pre-emptively from the driver to set/clear a port's modem signals. */ | ||
831 | #if 0 | ||
832 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
833 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
834 | #endif | ||
835 | |||
836 | #define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */ | ||
837 | |||
838 | /* ModemSet definitions... */ | ||
839 | #define MSET_RTS 0x01 /* RTS modem signal */ | ||
840 | #define MSET_DTR 0x02 /* DTR modem signal */ | ||
841 | |||
842 | /***************************************************************************** | ||
843 | ********************************* ********************************* | ||
844 | ********************************* PCLOSE ********************************* | ||
845 | ********************************* ********************************* | ||
846 | *****************************************************************************/ | ||
847 | |||
848 | /* (Driver->RIO,in-band) | ||
849 | |||
850 | PCLOSE is sent from the driver to pseudo close a previously opened port. | ||
851 | |||
852 | The port will close when all data has been sent/received, however, the | ||
853 | port's transmit / receive and modem signals will be left enabled and the | ||
854 | port marked internally as Pseudo Closed. */ | ||
855 | |||
856 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
857 | |||
858 | /***************************************************************************** | ||
859 | ********************************** ********************************** | ||
860 | ********************************** MGET ********************************** | ||
861 | ********************************** ********************************** | ||
862 | *****************************************************************************/ | ||
863 | |||
864 | /* (Driver->RIO,pre-emptive) | ||
865 | |||
866 | MGET is sent pre-emptively from the driver to request the port's current modem signals. */ | ||
867 | |||
868 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
869 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
870 | |||
871 | /***************************************************************************** | ||
872 | ********************************* ******************************** | ||
873 | ********************************* MEMDUMP ******************************** | ||
874 | ********************************* ******************************** | ||
875 | *****************************************************************************/ | ||
876 | |||
877 | /* (Driver->RIO,pre-emptive) | ||
878 | |||
879 | MEMDUMP is sent pre-emptively from the driver to request a dump of 32 bytes | ||
880 | of the specified port's RTA address space. | ||
881 | */ | ||
882 | #if 0 | ||
883 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
884 | #endif | ||
885 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
886 | #define PKT_SubCmd (PKT_Data+5) /* Sub Command */ | ||
887 | #define PKT_Address (PKT_Data+6) /* Requested address */ | ||
888 | |||
889 | /***************************************************************************** | ||
890 | ****************************** ***************************** | ||
891 | ****************************** READ_REGISTER ***************************** | ||
892 | ****************************** ***************************** | ||
893 | *****************************************************************************/ | ||
894 | |||
895 | /* (Driver->RIO,pre-emptive) | ||
896 | |||
897 | READ_REGISTER is sent pre-emptively from the driver to request the contents | ||
898 | of the CD1400 register specified in address. | ||
899 | */ | ||
900 | #if 0 | ||
901 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
902 | #endif | ||
903 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
904 | #define PKT_SubCmd (PKT_Data+5) /* Sub Command */ | ||
905 | #define PKT_Address (PKT_Data+6) /* Requested address */ | ||
906 | |||
907 | /***************************************************************************** | ||
908 | ************************ ************************** | ||
909 | ************************ COMMAND_RUP - COMPLETE ************************** | ||
910 | ************************ ************************** | ||
911 | *****************************************************************************/ | ||
912 | |||
913 | /* (RIO->Driver,pre-emptive) | ||
914 | |||
915 | COMMAND_RUP - COMPLETE is sent in response to all port I/O control command | ||
916 | packets, except MEMDUMP and READ_REGISTER. | ||
917 | */ | ||
918 | #if 0 | ||
919 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
920 | #endif | ||
921 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
922 | #define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ | ||
923 | #define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */ | ||
924 | #define PKT_PortStatus (PKT_Data+4) /* Port signal status */ | ||
925 | #define PKT_SubCmd (PKT_Data+5) /* Sub Command */ | ||
926 | |||
927 | /* ModemStatus definitions... */ | ||
928 | #define MODEM_DSR 0x80 /* Data Set Ready modem state */ | ||
929 | #define MODEM_CTS 0x40 /* Clear To Send modem state */ | ||
930 | #define MODEM_RI 0x20 /* Ring Indicate modem state */ | ||
931 | #define MODEM_CD 0x10 /* Carrier Detect modem state */ | ||
932 | #define MODEM_TSTOP 0x08 /* Transmit Stopped state */ | ||
933 | #define MODEM_TEMPTY 0x04 /* Transmit Empty state */ | ||
934 | #define MODEM_DTR 0x02 /* DTR modem output state */ | ||
935 | #define MODEM_RTS 0x01 /* RTS modem output state */ | ||
936 | |||
937 | /* PortStatus definitions... */ | ||
938 | #define PORT_ISOPEN 0x01 /* Port open ? */ | ||
939 | #define PORT_HUPCL 0x02 /* Hangup on close? */ | ||
940 | #define PORT_MOPENPEND 0x04 /* Modem open pending */ | ||
941 | #define PORT_ISPARALLEL 0x08 /* Parallel port */ | ||
942 | #define PORT_BREAK 0x10 /* Port on break */ | ||
943 | #define PORT_STATUSPEND 0020 /* Status packet pending */ | ||
944 | #define PORT_BREAKPEND 0x40 /* Break packet pending */ | ||
945 | #define PORT_MODEMPEND 0x80 /* Modem status packet pending */ | ||
946 | |||
947 | /***************************************************************************** | ||
948 | ************************ ************************** | ||
949 | ************************ COMMAND_RUP - COMPLETE ************************** | ||
950 | ************************ ************************** | ||
951 | *****************************************************************************/ | ||
952 | |||
953 | /* (RIO->Driver,pre-emptive) | ||
954 | |||
955 | COMMAND_RUP - COMPLETE is sent in response to all port I/O control command | ||
956 | packets, except MEMDUMP and READ_REGISTER. | ||
957 | */ | ||
958 | #if 0 | ||
959 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
960 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
961 | #define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ | ||
962 | #endif | ||
963 | #define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */ | ||
964 | #define PKT_PortStatus (PKT_Data+4) /* Port signal status */ | ||
965 | #if 0 | ||
966 | #define PKT_SubCmd (PKT_Data+5) /* Sub Command */ | ||
967 | #endif | ||
968 | |||
969 | /* ModemStatus definitions... */ | ||
970 | #define MODEM_DSR 0x80 /* Data Set Ready modem state */ | ||
971 | #define MODEM_CTS 0x40 /* Clear To Send modem state */ | ||
972 | #define MODEM_RI 0x20 /* Ring Indicate modem state */ | ||
973 | #define MODEM_CD 0x10 /* Carrier Detect modem state */ | ||
974 | #define MODEM_TSTOP 0x08 /* Transmit Stopped state */ | ||
975 | #define MODEM_TEMPTY 0x04 /* Transmit Empty state */ | ||
976 | #define MODEM_DTR 0x02 /* DTR modem output state */ | ||
977 | #define MODEM_RTS 0x01 /* RTS modem output state */ | ||
978 | |||
979 | /* PortStatus definitions... */ | ||
980 | #define PORT_ISOPEN 0x01 /* Port open ? */ | ||
981 | #define PORT_HUPCL 0x02 /* Hangup on close? */ | ||
982 | #define PORT_MOPENPEND 0x04 /* Modem open pending */ | ||
983 | #define PORT_ISPARALLEL 0x08 /* Parallel port */ | ||
984 | #define PORT_BREAK 0x10 /* Port on break */ | ||
985 | #define PORT_STATUSPEND 0020 /* Status packet pending */ | ||
986 | #define PORT_BREAKPEND 0x40 /* Break packet pending */ | ||
987 | #define PORT_MODEMPEND 0x80 /* Modem status packet pending */ | ||
988 | |||
989 | /***************************************************************************** | ||
990 | ******************** ******************** | ||
991 | ******************** COMMAND_RUP - COMPLETE - MEMDUMP ******************** | ||
992 | ******************** ******************** | ||
993 | *****************************************************************************/ | ||
994 | |||
995 | /* (RIO->Driver,pre-emptive) | ||
996 | |||
997 | COMMAND_RUP - COMPLETE - MEMDUMP is sent as an acknowledgement for a MEMDUMP | ||
998 | port I/O control command packet. | ||
999 | */ | ||
1000 | #if 0 | ||
1001 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1002 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
1003 | #define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ | ||
1004 | #define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */ | ||
1005 | #define PKT_PortStatus (PKT_Data+4) /* Port signal status */ | ||
1006 | #define PKT_SubCmd (PKT_Data+5) /* Sub Command */ | ||
1007 | #define PKT_Address (PKT_Data+6) /* Requested address */ | ||
1008 | #endif | ||
1009 | #define PKT_Dump (PKT_Data+8) /* 32bytes of requested dump data */ | ||
1010 | |||
1011 | /***************************************************************************** | ||
1012 | ***************** ***************** | ||
1013 | ***************** COMMAND_RUP - COMPLETE - READ_REGISTER ***************** | ||
1014 | ***************** ***************** | ||
1015 | *****************************************************************************/ | ||
1016 | |||
1017 | /* (RIO->Driver,pre-emptive) | ||
1018 | |||
1019 | COMMAND_RUP - COMPLETE - READ_REGISTER is sent as an acknowledgement for a | ||
1020 | READ_REGISTER port I/O control command packet. | ||
1021 | */ | ||
1022 | #if 0 | ||
1023 | #define PKT_Cmd (PKT_Data+0) /*Command code */ | ||
1024 | #define PKT_PhbNum (PKT_Data+1) /*Port number wrt RTA */ | ||
1025 | #define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ | ||
1026 | #endif | ||
1027 | #define PKT_RegisterValue (PKT_Data+3) /* Modem signal status */ | ||
1028 | #if 0 | ||
1029 | #define PKT_PortStatus (PKT_Data+4) /* Port signal status */ | ||
1030 | #define PKT_SubCmd (PKT_Data+5) /* Sub Command */ | ||
1031 | #endif | ||
1032 | |||
1033 | /***************************************************************************** | ||
1034 | ********************* *********************** | ||
1035 | ********************* COMMAND_RUP - BREAK_RECEIVED *********************** | ||
1036 | ********************* *********************** | ||
1037 | *****************************************************************************/ | ||
1038 | |||
1039 | /* (RIO->Driver,pre-emptive) | ||
1040 | |||
1041 | COMMAND_RUP - BREAK_RECEIVED packets are sent when the port detects a receive BREAK signal. | ||
1042 | */ | ||
1043 | #if 0 | ||
1044 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1045 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
1046 | #define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ | ||
1047 | #endif | ||
1048 | |||
1049 | /***************************************************************************** | ||
1050 | ********************* ************************* | ||
1051 | ********************* COMMAND_RUP - MODEM_STATUS ************************* | ||
1052 | ********************* ************************* | ||
1053 | *****************************************************************************/ | ||
1054 | |||
1055 | /* (RIO->Driver,pre-emptive) | ||
1056 | |||
1057 | COMMAND_RUP - MODEM_STATUS packets are sent whenever the port detects a | ||
1058 | change in the input modem signal states. | ||
1059 | |||
1060 | */ | ||
1061 | #if 0 | ||
1062 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1063 | #define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */ | ||
1064 | #define PKT_Cmd2 (PKT_Data+2) /* Command code copy */ | ||
1065 | #define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */ | ||
1066 | #endif | ||
1067 | |||
1068 | /***************************************************************************** | ||
1069 | ************************ ************************* | ||
1070 | ************************ BOOT_RUP - BOOT_REQUEST ************************* | ||
1071 | ************************ ************************* | ||
1072 | *****************************************************************************/ | ||
1073 | |||
1074 | /* (RIO->Driver,pre-emptive) | ||
1075 | |||
1076 | BOOT_RUP - BOOT_REQUEST packets are sent to the Driver from RIO to request | ||
1077 | firmware code to load onto attached RTAs. | ||
1078 | */ | ||
1079 | #if 0 | ||
1080 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1081 | #endif | ||
1082 | |||
1083 | /***************************************************************************** | ||
1084 | ************************ ************************ | ||
1085 | ************************ BOOT_RUP - BOOT_SEQUENCE ************************ | ||
1086 | ************************ ************************ | ||
1087 | *****************************************************************************/ | ||
1088 | |||
1089 | /* (Driver->RIO,pre-emptive) | ||
1090 | |||
1091 | BOOT_RUP - BOOT_SEQUENCE packets are sent from the Driver to RIO in response | ||
1092 | to a BOOT_RUP - BOOT_REQUEST packet. | ||
1093 | */ | ||
1094 | #if 0 | ||
1095 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1096 | #endif | ||
1097 | #define PKT_NumPackets (PKT_Data+2) /* Packets required to load firmware */ | ||
1098 | #define PKT_LoadBase (PKT_Data+4) /* RTA firmware load address */ | ||
1099 | #define PKT_CodeSize (PKT_Data+6) /* Size of firmware in bytes */ | ||
1100 | #define PKT_CmdString (PKT_Data+8) /* Command string */ | ||
1101 | |||
1102 | /***************************************************************************** | ||
1103 | ************************ *********************** | ||
1104 | ************************ BOOT_RUP - BOOT_COMPLETED *********************** | ||
1105 | ************************ *********************** | ||
1106 | *****************************************************************************/ | ||
1107 | |||
1108 | /* (RIO->Driver,pre-emptive) | ||
1109 | |||
1110 | BOOT_RUP - BOOT_COMPLETE is sent to the Driver from RIO when downloading of | ||
1111 | RTA firmware has completed. | ||
1112 | */ | ||
1113 | #if 0 | ||
1114 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1115 | #endif | ||
1116 | #define PKT_LinkNumber (PKT_Data+1) /* Link number RTA booted on */ | ||
1117 | #define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */ | ||
1118 | |||
1119 | /***************************************************************************** | ||
1120 | ************************ *********************** | ||
1121 | ************************ BOOT_RUP - Packet Request *********************** | ||
1122 | ************************ *********************** | ||
1123 | *****************************************************************************/ | ||
1124 | |||
1125 | /* (RIO->Driver,pre-emptive) | ||
1126 | |||
1127 | BOOT_RUP packet without the PKT_CMD_BIT set in the PKT->len field is sent | ||
1128 | from RIO to the Driver as a request for a firmware boot packet. */ | ||
1129 | |||
1130 | #define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */ | ||
1131 | |||
1132 | /***************************************************************************** | ||
1133 | *********************** *********************** | ||
1134 | *********************** BOOT_RUP - Packet Response *********************** | ||
1135 | *********************** *********************** | ||
1136 | *****************************************************************************/ | ||
1137 | |||
1138 | /* (Driver->RIO,pre-emptive) | ||
1139 | |||
1140 | In response to a BOOT_RUP boot packet request, the driver fills out the response | ||
1141 | packet with the 70 bytes of the requested sequence. | ||
1142 | */ | ||
1143 | #if 0 | ||
1144 | #define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */ | ||
1145 | #endif | ||
1146 | #define PKT_FirmwarePacket (PKT_Data+2) /* Firmware packet */ | ||
1147 | |||
1148 | /***************************************************************************** | ||
1149 | **************************** **************************** | ||
1150 | **************************** BOOT_RUP - IFOAD **************************** | ||
1151 | **************************** **************************** | ||
1152 | *****************************************************************************/ | ||
1153 | |||
1154 | /* (Driver->RIO,pre-emptive) | ||
1155 | |||
1156 | BOOT_RUP - IFOAD packets are sent from the Driver to an RTA to cause the | ||
1157 | RTA to shut down and reboot. | ||
1158 | */ | ||
1159 | #if 0 | ||
1160 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1161 | #endif | ||
1162 | #define PKT_IfoadId1 (PKT_Data+2) /* IFOAD Id 1 */ | ||
1163 | #define PKT_IfoadId2 (PKT_Data+3) /* IFOAD Id 2 */ | ||
1164 | |||
1165 | #define IFOADID1 0xAD | ||
1166 | #define IFOADID2 0xF0 | ||
1167 | |||
1168 | /***************************************************************************** | ||
1169 | ************************** *************************** | ||
1170 | ************************** BOOT_RUP - IDENTIFY *************************** | ||
1171 | ************************** *************************** | ||
1172 | *****************************************************************************/ | ||
1173 | |||
1174 | /* (Driver->RIO,pre-emptive) | ||
1175 | |||
1176 | BOOT_RUP - IDENTIFY packets are sent from the Driver to an RTA to cause the | ||
1177 | RTA to flash its LEDs for a period of time. | ||
1178 | */ | ||
1179 | #if 0 | ||
1180 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1181 | #endif | ||
1182 | #define PKT_IdentifyId (PKT_Data+2) /* defines pattern to flash */ | ||
1183 | |||
1184 | /***************************************************************************** | ||
1185 | **************************** *************************** | ||
1186 | **************************** BOOT_RUP - ZOMBIE *************************** | ||
1187 | **************************** *************************** | ||
1188 | *****************************************************************************/ | ||
1189 | |||
1190 | /* (Driver->RIO,pre-emptive) | ||
1191 | |||
1192 | BOOT_RUP - ZOMBIE packets are sent from the Driver to an RTA to cause the | ||
1193 | RTA to shut down and flash it's LEDs. | ||
1194 | */ | ||
1195 | #if 0 | ||
1196 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1197 | #endif | ||
1198 | #define PKT_ZombieId1 (PKT_Data+2) /* ZOMBIE Id 1 */ | ||
1199 | #define PKT_ZombieId2 (PKT_Data+3) /* ZOMBIE Id 2 */ | ||
1200 | |||
1201 | #define ZOMBIEID1 0x52 | ||
1202 | #define ZOMBIEID2 0x21 | ||
1203 | |||
1204 | /***************************************************************************** | ||
1205 | **************************** **************************** | ||
1206 | **************************** BOOT_RUP - UFOAD **************************** | ||
1207 | **************************** **************************** | ||
1208 | *****************************************************************************/ | ||
1209 | |||
1210 | /* (Driver->RIO,pre-emptive) | ||
1211 | |||
1212 | BOOT_RUP - UFOAD packets are sent from the Driver to an RTA to cause the RTA | ||
1213 | to ask it's neighbouring RTA to shut down and reboot. | ||
1214 | */ | ||
1215 | #if 0 | ||
1216 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1217 | #define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */ | ||
1218 | #endif | ||
1219 | #define PKT_UfoadId1 (PKT_Data+2) /* UFOAD Id 1 */ | ||
1220 | #define PKT_UfoadId2 (PKT_Data+3) /* UFOAD Id 2 */ | ||
1221 | |||
1222 | #define UFOADID1 0x1E | ||
1223 | #define UFOADID2 0x0D | ||
1224 | |||
1225 | /***************************************************************************** | ||
1226 | **************************** **************************** | ||
1227 | **************************** BOOT_RUP - IWAIT **************************** | ||
1228 | **************************** **************************** | ||
1229 | *****************************************************************************/ | ||
1230 | |||
1231 | /* (Driver->RIO,pre-emptive) | ||
1232 | |||
1233 | BOOT_RUP - IWAIT packets are sent from the Driver to an RTA to cause the RTA | ||
1234 | to pause booting on the specified link for 30 seconds. | ||
1235 | */ | ||
1236 | #if 0 | ||
1237 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1238 | #define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */ | ||
1239 | #endif | ||
1240 | #define PKT_IwaitId1 (PKT_Data+2) /* IWAIT Id 1 */ | ||
1241 | #define PKT_IwaitId2 (PKT_Data+3) /* IWAIT Id 2 */ | ||
1242 | |||
1243 | #define IWAITID1 0xDE | ||
1244 | #define IWAITID2 0xB1 | ||
1245 | |||
1246 | /***************************************************************************** | ||
1247 | ************************ *********************** | ||
1248 | ************************ ROUTE_RUP - ROUTE_REQUEST *********************** | ||
1249 | ************************ *********************** | ||
1250 | *****************************************************************************/ | ||
1251 | |||
1252 | /* (RIO->Driver,pre-emptive) | ||
1253 | |||
1254 | ROUTE_RUP - ROUTE_REQUEST packets are sent from a newly booted or connected | ||
1255 | RTA to a Driver to request an ID (RUP or unit number). | ||
1256 | */ | ||
1257 | #if 0 | ||
1258 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1259 | #endif | ||
1260 | #define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */ | ||
1261 | #define PKT_ModuleTypes (PKT_Data+6) /* RTA Module types */ | ||
1262 | |||
1263 | /* ModuleTypes definitions... */ | ||
1264 | #define MOD_BLANK 0x0F /* Blank plate attached */ | ||
1265 | #define MOD_RS232DB25 0x00 /* RS232 DB25 connector */ | ||
1266 | #define MOD_RS232RJ45 0x01 /* RS232 RJ45 connector */ | ||
1267 | #define MOD_RS422DB25 0x02 /* RS422 DB25 connector */ | ||
1268 | #define MOD_RS485DB25 0x03 /* RS485 DB25 connector */ | ||
1269 | #define MOD_PARALLEL 0x04 /* Centronics parallel */ | ||
1270 | |||
1271 | #define MOD2 0x08 /* Set to indicate Rev2 module */ | ||
1272 | |||
1273 | /***************************************************************************** | ||
1274 | ************************* ************************* | ||
1275 | ************************* ROUTE_RUP - ROUTE_FOAD ************************* | ||
1276 | ************************* ************************* | ||
1277 | *****************************************************************************/ | ||
1278 | |||
1279 | /* (Driver->RIO,pre-emptive) | ||
1280 | |||
1281 | ROUTE_RUP - ROUTE_FOAD packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST | ||
1282 | packet to cause the RTA to "Fall Over And Die"., i.e. shutdown and reboot. | ||
1283 | */ | ||
1284 | #if 0 | ||
1285 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1286 | #endif | ||
1287 | #define PKT_RouteCmdString (PKT_Data+2) /* Command string */ | ||
1288 | |||
1289 | /***************************************************************************** | ||
1290 | *********************** *********************** | ||
1291 | *********************** ROUTE_RUP - ROUTE_ALLOCATE *********************** | ||
1292 | *********************** *********************** | ||
1293 | *****************************************************************************/ | ||
1294 | |||
1295 | /* (Driver->RIO,pre-emptive) | ||
1296 | |||
1297 | ROUTE_RUP - ROUTE_ALLOCATE packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST | ||
1298 | packet to allocate the RTA's Id number (RUP number 1..16) | ||
1299 | */ | ||
1300 | #if 0 | ||
1301 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1302 | #endif | ||
1303 | #define PKT_IdNum (PKT_Data+1) /* RUP number for ports 1..8 */ | ||
1304 | #if 0 | ||
1305 | #define PKT_RouteCmdString (PKT_Data+2) /* Command string */ | ||
1306 | #endif | ||
1307 | #define PKT_IdNum2 (PKT_Data+0x17) /* RUP number for ports 9..16 */ | ||
1308 | |||
1309 | /***************************************************************************** | ||
1310 | *********************** *********************** | ||
1311 | *********************** ROUTE_RUP - ROUTE_TOPOLOGY *********************** | ||
1312 | *********************** *********************** | ||
1313 | *****************************************************************************/ | ||
1314 | |||
1315 | /* (RIO->Driver,pre-emptive) | ||
1316 | |||
1317 | ROUTE_RUP - ROUTE_TOPOLOGY packet is sent to inform the driver of an RTA's | ||
1318 | current link status. | ||
1319 | */ | ||
1320 | #if 0 | ||
1321 | #define PKT_Cmd (PKT_Data+0) /* Command code */ | ||
1322 | #endif | ||
1323 | #define PKT_Link1Rup (PKT_Data+2) /* Link 1 RUP number */ | ||
1324 | #define PKT_Link1Link (PKT_Data+3) /* Link 1 link number */ | ||
1325 | #define PKT_Link2Rup (PKT_Data+4) /* Link 2 RUP number */ | ||
1326 | #define PKT_Link2Link (PKT_Data+5) /* Link 2 link number */ | ||
1327 | #define PKT_Link3Rup (PKT_Data+6) /* Link 3 RUP number */ | ||
1328 | #define PKT_Link3Link (PKT_Data+7) /* Link 3 link number */ | ||
1329 | #define PKT_Link4Rup (PKT_Data+8) /* Link 4 RUP number */ | ||
1330 | #define PKT_Link4Link (PKT_Data+9) /* Link 4 link number */ | ||
1331 | #define PKT_RtaVpdProm (PKT_Data+10) /* 32 bytes of RTA VPD PROM Contents */ | ||
1332 | |||
1333 | #endif /* _sxwinif_h */ | ||
1334 | |||
1335 | /* End of RIOWINIF.H */ | ||
diff --git a/drivers/char/rio/riscos.h b/drivers/char/rio/riscos.h new file mode 100644 index 000000000000..7685cc1d9e7b --- /dev/null +++ b/drivers/char/rio/riscos.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : riscos.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:19 | ||
26 | ** Retrieved : 11/6/98 11:34:22 | ||
27 | ** | ||
28 | ** ident @(#)riscos.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_riscos_h__ | ||
34 | #define __rio_riscos_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_riscos_h_sccs_ = "@(#)riscos.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** This module used to define all those little itsy bits required for RISC/OS | ||
42 | ** now it's full of null macros. | ||
43 | */ | ||
44 | |||
45 | /* | ||
46 | ** RBYTE reads a byte from a location. | ||
47 | ** RWORD reads a word from a location. | ||
48 | ** WBYTE writes a byte to a location. | ||
49 | ** WWORD writes a word to a location. | ||
50 | ** RINDW reads a word through a pointer. | ||
51 | ** WINDW writes a word through a pointer. | ||
52 | ** RIOSWAB swaps the two bytes of a word, if needed. | ||
53 | */ | ||
54 | |||
55 | #define RIOSWAB(N) (N) | ||
56 | #define WBYTE(A,V) (A)=(uchar)(V) | ||
57 | #define WWORD(A,V) (A)=(ushort)(V) | ||
58 | #define RBYTE(A) (uchar)(A) | ||
59 | #define RWORD(A) (ushort)(A) | ||
60 | #define RINDW(A) (*(ushort *)(A)) | ||
61 | #define WINDW(A,V) (*(ushort *)(A)=(ushort)(V)) | ||
62 | |||
63 | #endif /* __rio_riscos_h__ */ | ||
diff --git a/drivers/char/rio/rom.h b/drivers/char/rio/rom.h new file mode 100644 index 000000000000..ee79b8e5b972 --- /dev/null +++ b/drivers/char/rio/rom.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* R O M | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _rom_h | ||
38 | #define _rom_h 1 | ||
39 | |||
40 | #ifndef lint | ||
41 | #ifdef SCCS | ||
42 | static char *_rio_rom_h_sccs = "@(#)rom.h 1.1" ; | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | typedef struct ROM ROM ; | ||
47 | struct ROM { | ||
48 | u_short slx ; | ||
49 | char pcb_letter_rev ; | ||
50 | char pcb_number_rev ; | ||
51 | char serial[4] ; | ||
52 | char year ; | ||
53 | char week ; | ||
54 | } ; | ||
55 | |||
56 | #endif | ||
57 | |||
58 | #define HOST_ROM (ROM *) 0x7c00 | ||
59 | #define RTA_ROM (ROM *) 0x7801 | ||
60 | #define ROM_LENGTH 0x20 | ||
61 | |||
62 | /*********** end of file ***********/ | ||
63 | |||
64 | |||
diff --git a/drivers/char/rio/route.h b/drivers/char/rio/route.h new file mode 100644 index 000000000000..c42dbb971718 --- /dev/null +++ b/drivers/char/rio/route.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* R O U T E H E A D E R | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra / Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _route_h | ||
38 | #define _route_h | ||
39 | |||
40 | #ifdef SCCS_LABELS | ||
41 | #ifndef lint | ||
42 | /* static char *_rio_route_h_sccs = "@(#)route.h 1.3"; */ | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | #define MAX_LINKS 4 | ||
47 | #define MAX_NODES 17 /* Maximum nodes in a subnet */ | ||
48 | #define NODE_BYTES ((MAX_NODES / 8) + 1) /* Number of bytes needed for | ||
49 | 1 bit per node */ | ||
50 | #define ROUTE_DATA_SIZE (NODE_BYTES + 2) /* Number of bytes for complete | ||
51 | info about cost etc. */ | ||
52 | #define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE) | ||
53 | /* Number of nodes we can squeeze | ||
54 | into one packet */ | ||
55 | #define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1) | ||
56 | /************************************************ | ||
57 | * Define the types of command for the ROUTE RUP. | ||
58 | ************************************************/ | ||
59 | #define ROUTE_REQUEST 0 /* Request an ID */ | ||
60 | #define ROUTE_FOAD 1 /* Kill the RTA */ | ||
61 | #define ROUTE_ALREADY 2 /* ID given already */ | ||
62 | #define ROUTE_USED 3 /* All ID's used */ | ||
63 | #define ROUTE_ALLOCATE 4 /* Here it is */ | ||
64 | #define ROUTE_REQ_TOP 5 /* I bet you didn't expect.... | ||
65 | the Topological Inquisition */ | ||
66 | #define ROUTE_TOPOLOGY 6 /* Topology request answered FD */ | ||
67 | /******************************************************************* | ||
68 | * Define the Route Map Structure | ||
69 | * | ||
70 | * The route map gives a pointer to a Link Structure to use. | ||
71 | * This allows Disconnected Links to be checked quickly | ||
72 | ******************************************************************/ | ||
73 | typedef struct COST_ROUTE COST_ROUTE; | ||
74 | struct COST_ROUTE { | ||
75 | unsigned char cost; /* Cost down this link */ | ||
76 | unsigned char route[NODE_BYTES]; /* Nodes thorough this route */ | ||
77 | } ; | ||
78 | |||
79 | typedef struct ROUTE_STR ROUTE_STR ; | ||
80 | struct ROUTE_STR { | ||
81 | COST_ROUTE cost_route[MAX_LINKS]; | ||
82 | /* cost / route for this link */ | ||
83 | ushort favoured; /* favoured link */ | ||
84 | } ; | ||
85 | |||
86 | |||
87 | #define NO_LINK (short) 5 /* Link unattached */ | ||
88 | #define ROUTE_NO_ID (short) 100 /* No Id */ | ||
89 | #define ROUTE_DISCONNECT (ushort) 0xff /* Not connected */ | ||
90 | #define ROUTE_INTERCONNECT (ushort) 0x40 /* Sub-net interconnect */ | ||
91 | |||
92 | |||
93 | #define SYNC_RUP (ushort) 255 | ||
94 | #define COMMAND_RUP (ushort) 254 | ||
95 | #define ERROR_RUP (ushort) 253 | ||
96 | #define POLL_RUP (ushort) 252 | ||
97 | #define BOOT_RUP (ushort) 251 | ||
98 | #define ROUTE_RUP (ushort) 250 | ||
99 | #define STATUS_RUP (ushort) 249 | ||
100 | #define POWER_RUP (ushort) 248 | ||
101 | |||
102 | #define HIGHEST_RUP (ushort) 255 /* Set to Top one */ | ||
103 | #define LOWEST_RUP (ushort) 248 /* Set to bottom one */ | ||
104 | |||
105 | #endif | ||
106 | |||
107 | /*********** end of file ***********/ | ||
108 | |||
diff --git a/drivers/char/rio/rtahw.h b/drivers/char/rio/rtahw.h new file mode 100644 index 000000000000..06860118cbc5 --- /dev/null +++ b/drivers/char/rio/rtahw.h | |||
@@ -0,0 +1,75 @@ | |||
1 | |||
2 | /**************************************************************************** | ||
3 | ******* ******* | ||
4 | ******* R T A H A R D W A R E | ||
5 | ******* ******* | ||
6 | **************************************************************************** | ||
7 | |||
8 | Author : Ian Nandhra | ||
9 | Date : | ||
10 | |||
11 | * | ||
12 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | |||
28 | Version : 0.01 | ||
29 | |||
30 | |||
31 | Mods | ||
32 | ---------------------------------------------------------------------------- | ||
33 | Date By Description | ||
34 | ---------------------------------------------------------------------------- | ||
35 | |||
36 | ***************************************************************************/ | ||
37 | |||
38 | #ifndef lint | ||
39 | #ifdef SCCS_LABELS | ||
40 | static char *_rio_rtahw_h_sccs = "@(#)rtahw.h 1.5" ; | ||
41 | #endif | ||
42 | #endif | ||
43 | |||
44 | #define WATCHDOG_ADDR ((unsigned short *)0x7a00) | ||
45 | #define RTA_LED_ADDR ((unsigned short *)0x7c00) | ||
46 | #define SERIALNUM_ADDR ((unsigned char *)0x7809) | ||
47 | #define LATCH_ADDR ((unsigned char *)0x7800) | ||
48 | |||
49 | /* | ||
50 | ** Here we define where the cd1400 chips are in memory. | ||
51 | */ | ||
52 | #define CD1400_ONE_ADDR (0x7300) | ||
53 | #define CD1400_TWO_ADDR (0x7200) | ||
54 | #define CD1400_THREE_ADDR (0x7100) | ||
55 | #define CD1400_FOUR_ADDR (0x7000) | ||
56 | |||
57 | /* | ||
58 | ** Define the different types of modules we can have | ||
59 | */ | ||
60 | enum module { | ||
61 | MOD_BLANK = 0x0f, /* Blank plate attached */ | ||
62 | MOD_RS232DB25 = 0x00, /* RS232 DB25 connector */ | ||
63 | MOD_RS232RJ45 = 0x01, /* RS232 RJ45 connector */ | ||
64 | MOD_RS422DB25 = 0x02, /* RS422 DB25 connector */ | ||
65 | MOD_RS485DB25 = 0x03, /* RS485 DB25 connector */ | ||
66 | MOD_PARALLEL = 0x04 /* Centronics parallel */ | ||
67 | }; | ||
68 | |||
69 | #define TYPE_HOST 0 | ||
70 | #define TYPE_RTA8 1 | ||
71 | #define TYPE_RTA16 2 | ||
72 | |||
73 | #define WATCH_DOG WATCHDOG_ADDR | ||
74 | |||
75 | /*********** end of file ***********/ | ||
diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h new file mode 100644 index 000000000000..b9d2bc03d14b --- /dev/null +++ b/drivers/char/rio/rup.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* R U P S T R U C T U R E | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _rup_h | ||
38 | #define _rup_h 1 | ||
39 | |||
40 | #ifdef SCCS_LABELS | ||
41 | #ifndef lint | ||
42 | /* static char *_rio_rup_h_sccs = "@(#)rup.h 1.5"; */ | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | #if defined( HOST ) || defined( INKERNEL ) | ||
47 | #define MAX_RUP ((short) 16) | ||
48 | #endif | ||
49 | #ifdef RTA | ||
50 | #define MAX_RUP ((short) 1) | ||
51 | #endif | ||
52 | |||
53 | #define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */ | ||
54 | |||
55 | /************************************************* | ||
56 | * Define all the packet request stuff | ||
57 | ************************************************/ | ||
58 | #define TX_RUP_INACTIVE 0 /* Nothing to transmit */ | ||
59 | #define TX_PACKET_READY 1 /* Transmit packet ready */ | ||
60 | #define TX_LOCK_RUP 2 /* Transmit side locked */ | ||
61 | |||
62 | #define RX_RUP_INACTIVE 0 /* Nothing received */ | ||
63 | #define RX_PACKET_READY 1 /* Packet received */ | ||
64 | |||
65 | #define RUP_NO_OWNER 0xff /* RUP not owned by any process */ | ||
66 | |||
67 | struct RUP { | ||
68 | PKT_ptr txpkt; /* Outgoing packet */ | ||
69 | PKT_ptr rxpkt; /* Incoming packet */ | ||
70 | WORD link; /* Which link to send down? */ | ||
71 | BYTE rup_dest_unit[2]; /* Destination unit */ | ||
72 | WORD handshake; /* For handshaking */ | ||
73 | WORD timeout; /* Timeout */ | ||
74 | WORD status; /* Status */ | ||
75 | WORD txcontrol; /* Transmit control */ | ||
76 | WORD rxcontrol; /* Receive control */ | ||
77 | }; | ||
78 | |||
79 | #endif | ||
80 | |||
81 | /*********** end of file ***********/ | ||
82 | |||
diff --git a/drivers/char/rio/rupstat.h b/drivers/char/rio/rupstat.h new file mode 100644 index 000000000000..b4aafaff0d78 --- /dev/null +++ b/drivers/char/rio/rupstat.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* RUPSTAT | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Jeremy Rolls | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | |||
37 | #ifndef _rupstat_h | ||
38 | #define _rupstat_h | ||
39 | |||
40 | #ifndef lint | ||
41 | #ifdef SCCS_LABELS | ||
42 | static char *_rio_rupstat_h_sccs = "@(#)rupstat.h 1.1" ; | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | #define STATUS_SYNC 0 | ||
47 | #define STATUS_REQ_TOP 1 | ||
48 | #define STATUS_TOPOLOGY 2 | ||
49 | |||
50 | #endif | ||
51 | |||
diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h new file mode 100644 index 000000000000..c1accb8cb624 --- /dev/null +++ b/drivers/char/rio/sam.h | |||
@@ -0,0 +1,74 @@ | |||
1 | /**************************************************************************** | ||
2 | ******* ******* | ||
3 | ******* S A M . H | ||
4 | ******* ******* | ||
5 | **************************************************************************** | ||
6 | |||
7 | Author : Ian Nandhra | ||
8 | Date : | ||
9 | |||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | |||
27 | Version : 0.01 | ||
28 | |||
29 | |||
30 | Mods | ||
31 | ---------------------------------------------------------------------------- | ||
32 | Date By Description | ||
33 | ---------------------------------------------------------------------------- | ||
34 | |||
35 | ***************************************************************************/ | ||
36 | #ifndef _sam_h | ||
37 | #define _sam_h 1 | ||
38 | |||
39 | #ifdef SCCS_LABELS | ||
40 | #ifndef lint | ||
41 | /* static char *_rio_sam_h_sccs = "@(#)sam.h 1.3"; */ | ||
42 | #endif | ||
43 | #endif | ||
44 | |||
45 | |||
46 | #if !defined( HOST ) && !defined( INKERNEL ) | ||
47 | #define RTA 1 | ||
48 | #endif | ||
49 | |||
50 | #define NUM_FREE_LIST_UNITS 500 | ||
51 | |||
52 | #ifndef FALSE | ||
53 | #define FALSE (short) 0x00 | ||
54 | #endif | ||
55 | #ifndef TRUE | ||
56 | #define TRUE (short) !FALSE | ||
57 | #endif | ||
58 | |||
59 | #define TX TRUE | ||
60 | #define RX FALSE | ||
61 | |||
62 | |||
63 | typedef struct FREE_LIST FREE_LIST ; | ||
64 | struct FREE_LIST { | ||
65 | FREE_LIST_ptr next ; | ||
66 | FREE_LIST_ptr prev ; | ||
67 | } ; | ||
68 | |||
69 | |||
70 | #endif | ||
71 | /*********** end of file ***********/ | ||
72 | |||
73 | |||
74 | |||
diff --git a/drivers/char/rio/selftest.h b/drivers/char/rio/selftest.h new file mode 100644 index 000000000000..deae48722a21 --- /dev/null +++ b/drivers/char/rio/selftest.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | ** File: selftest.h | ||
3 | ** | ||
4 | ** Author: David Dix | ||
5 | ** | ||
6 | ** Created: 15th March 1993 | ||
7 | ** | ||
8 | ** Last modified: 94/06/14 | ||
9 | ** | ||
10 | * | ||
11 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef _selftests_h_ | ||
29 | #define _selftests_h_ | ||
30 | |||
31 | /* | ||
32 | ** Selftest identifier... | ||
33 | */ | ||
34 | #define SELFTEST_MAGIC 0x5a5a | ||
35 | |||
36 | /* | ||
37 | ** This is the structure of the packet that is sent back after each | ||
38 | ** selftest on a booting RTA. | ||
39 | */ | ||
40 | typedef struct { | ||
41 | short magic; /* Identifies packet type */ | ||
42 | int test; /* Test number, see below */ | ||
43 | unsigned int result; /* Result value */ | ||
44 | unsigned int dataIn; | ||
45 | unsigned int dataOut; | ||
46 | }selftestStruct; | ||
47 | |||
48 | /* | ||
49 | ** The different tests are identified by the following data values. | ||
50 | */ | ||
51 | enum test { | ||
52 | TESTS_COMPLETE = 0x00, | ||
53 | MEMTEST_ADDR = 0x01, | ||
54 | MEMTEST_BIT = 0x02, | ||
55 | MEMTEST_FILL = 0x03, | ||
56 | MEMTEST_DATABUS = 0x04, | ||
57 | MEMTEST_ADDRBUS = 0x05, | ||
58 | CD1400_INIT = 0x10, | ||
59 | CD1400_LOOP = 0x11, | ||
60 | CD1400_INTERRUPT = 0x12 | ||
61 | }; | ||
62 | |||
63 | enum result { | ||
64 | E_PORT = 0x10, | ||
65 | E_TX = 0x11, | ||
66 | E_RX = 0x12, | ||
67 | E_EXCEPT = 0x13, | ||
68 | E_COMPARE = 0x14, | ||
69 | E_MODEM = 0x15, | ||
70 | E_TIMEOUT = 0x16, | ||
71 | E_INTERRUPT = 0x17 | ||
72 | }; | ||
73 | #endif /* _selftests_h_ */ | ||
diff --git a/drivers/char/rio/space.h b/drivers/char/rio/space.h new file mode 100644 index 000000000000..72398d342051 --- /dev/null +++ b/drivers/char/rio/space.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : space.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:19 | ||
26 | ** Retrieved : 11/6/98 11:34:22 | ||
27 | ** | ||
28 | ** ident @(#)space.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_space_h__ | ||
34 | #define __rio_space_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_space_h_sccs_ = "@(#)space.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | extern int rio_cntls; | ||
41 | extern int rio_bases[]; | ||
42 | extern int rio_limits[]; | ||
43 | extern int rio_vects[]; | ||
44 | |||
45 | #endif /* __rio_space_h__ */ | ||
diff --git a/drivers/char/rio/sysmap.h b/drivers/char/rio/sysmap.h new file mode 100644 index 000000000000..fdc731393576 --- /dev/null +++ b/drivers/char/rio/sysmap.h | |||
@@ -0,0 +1,63 @@ | |||
1 | |||
2 | /**************************************************************************** | ||
3 | ******* ******* | ||
4 | ******* S Y S T E M M A P H E A D E R | ||
5 | ******* ******* | ||
6 | **************************************************************************** | ||
7 | |||
8 | Author : Ian Nandhra | ||
9 | Date : | ||
10 | |||
11 | * | ||
12 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | |||
28 | Version : 0.01 | ||
29 | |||
30 | |||
31 | Mods | ||
32 | ---------------------------------------------------------------------------- | ||
33 | Date By Description | ||
34 | ---------------------------------------------------------------------------- | ||
35 | |||
36 | ***************************************************************************/ | ||
37 | |||
38 | #ifndef lint | ||
39 | #ifdef SCCS_LABELS | ||
40 | static char *_rio_sysmap_h_sccs = "@(#)sysmap.h 1.1" ; | ||
41 | #endif | ||
42 | #endif | ||
43 | |||
44 | #define SYSTEM_MAP_LEN 64 /* Len of System Map array */ | ||
45 | |||
46 | |||
47 | typedef struct SYS_MAP SYS_MAP ; | ||
48 | typedef struct SYS_MAP_LINK SYS_MAP_LINK ; | ||
49 | |||
50 | struct SYS_MAP_LINK { | ||
51 | short id ; /* Unit Id */ | ||
52 | short link ; /* Id's Link */ | ||
53 | short been_here ; /* Used by map_gen */ | ||
54 | } ; | ||
55 | |||
56 | struct SYS_MAP { | ||
57 | char serial_num[4] ; | ||
58 | SYS_MAP_LINK link[4] ; | ||
59 | } ; | ||
60 | |||
61 | |||
62 | /*********** end of file ***********/ | ||
63 | |||
diff --git a/drivers/char/rio/timeouts.h b/drivers/char/rio/timeouts.h new file mode 100644 index 000000000000..11b31330c901 --- /dev/null +++ b/drivers/char/rio/timeouts.h | |||
@@ -0,0 +1,51 @@ | |||
1 | |||
2 | /**************************************************************************** | ||
3 | ******* ******* | ||
4 | ******* T I M E O U T S | ||
5 | ******* ******* | ||
6 | **************************************************************************** | ||
7 | |||
8 | Author : Ian Nandhra | ||
9 | Date : | ||
10 | |||
11 | * | ||
12 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | |||
28 | Version : 0.01 | ||
29 | |||
30 | |||
31 | Mods | ||
32 | ---------------------------------------------------------------------------- | ||
33 | Date By Description | ||
34 | ---------------------------------------------------------------------------- | ||
35 | |||
36 | ***************************************************************************/ | ||
37 | |||
38 | #ifndef lint | ||
39 | #ifdef SCCS_LABELS | ||
40 | static char *_rio_defaults_h_sccs = "@(#)timeouts.h 1.3" ; | ||
41 | #endif | ||
42 | #endif | ||
43 | |||
44 | #define MILLISECOND (int) (1000/64) /* 15.625 low ticks */ | ||
45 | #define SECOND (int) 15625 /* Low priority ticks */ | ||
46 | |||
47 | #define TX_TIMEOUT (int) (200 * MILLISECOND) | ||
48 | |||
49 | |||
50 | /*********** end of file ***********/ | ||
51 | |||
diff --git a/drivers/char/rio/top.h b/drivers/char/rio/top.h new file mode 100644 index 000000000000..255c40d463a6 --- /dev/null +++ b/drivers/char/rio/top.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : top.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:19 | ||
26 | ** Retrieved : 11/6/98 11:34:22 | ||
27 | ** | ||
28 | ** ident @(#)top.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_top_h__ | ||
34 | #define __rio_top_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_top_h_sccs_ = "@(#)top.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** Topology information | ||
42 | */ | ||
43 | struct Top | ||
44 | { | ||
45 | uchar Unit; | ||
46 | uchar Link; | ||
47 | }; | ||
48 | |||
49 | #endif /* __rio_top_h__ */ | ||
diff --git a/drivers/char/rio/typdef.h b/drivers/char/rio/typdef.h new file mode 100644 index 000000000000..2cb9dd693fa1 --- /dev/null +++ b/drivers/char/rio/typdef.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : typdef.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:20 | ||
26 | ** Retrieved : 11/6/98 11:34:22 | ||
27 | ** | ||
28 | ** ident @(#)typdef.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_typdef_h__ | ||
34 | #define __rio_typdef_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_typdef_h_sccs_ = "@(#)typdef.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | #undef VPIX | ||
41 | |||
42 | /* | ||
43 | ** IT IS REALLY, REALLY, IMPORTANT THAT BYTES ARE UNSIGNED! | ||
44 | ** | ||
45 | ** These types are ONLY to be used for refering to data structures | ||
46 | ** on the RIO Host card! | ||
47 | */ | ||
48 | typedef volatile unsigned char BYTE; | ||
49 | typedef volatile unsigned short WORD; | ||
50 | typedef volatile unsigned int DWORD; | ||
51 | typedef volatile unsigned short RIOP; | ||
52 | typedef volatile short NUMBER; | ||
53 | |||
54 | |||
55 | /* | ||
56 | ** 27.01.199 ARG - mods to compile 'newutils' on LyxnOS - | ||
57 | ** These #defines are for the benefit of the 'libfuncs' library | ||
58 | ** only. They are not necessarily correct type mappings and | ||
59 | ** are here only to make the source compile. | ||
60 | */ | ||
61 | /* typedef unsigned int uint; */ | ||
62 | typedef unsigned long ulong_t; | ||
63 | typedef unsigned short ushort_t; | ||
64 | typedef unsigned char uchar_t; | ||
65 | typedef unsigned char queue_t; | ||
66 | typedef unsigned char mblk_t; | ||
67 | typedef unsigned int paddr_t; | ||
68 | typedef unsigned char uchar; | ||
69 | |||
70 | #define TPNULL ((ushort)(0x8000)) | ||
71 | |||
72 | |||
73 | /* | ||
74 | ** RIO structures defined in other include files. | ||
75 | */ | ||
76 | typedef struct PKT PKT; | ||
77 | typedef struct LPB LPB; | ||
78 | typedef struct RUP RUP; | ||
79 | typedef struct Port Port; | ||
80 | typedef struct DpRam DpRam; | ||
81 | |||
82 | #endif /* __rio_typdef_h__ */ | ||
diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h new file mode 100644 index 000000000000..eddf86278abc --- /dev/null +++ b/drivers/char/rio/unixrup.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | ** ----------------------------------------------------------------------------- | ||
3 | ** | ||
4 | ** Perle Specialix driver for Linux | ||
5 | ** Ported from existing RIO Driver for SCO sources. | ||
6 | * | ||
7 | * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | ** | ||
23 | ** Module : unixrup.h | ||
24 | ** SID : 1.2 | ||
25 | ** Last Modified : 11/6/98 11:34:20 | ||
26 | ** Retrieved : 11/6/98 11:34:22 | ||
27 | ** | ||
28 | ** ident @(#)unixrup.h 1.2 | ||
29 | ** | ||
30 | ** ----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #ifndef __rio_unixrup_h__ | ||
34 | #define __rio_unixrup_h__ | ||
35 | |||
36 | #ifdef SCCS_LABELS | ||
37 | static char *_unixrup_h_sccs_ = "@(#)unixrup.h 1.2"; | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | ** UnixRup data structure. This contains pointers to actual RUPs on the | ||
42 | ** host card, and all the command/boot control stuff. | ||
43 | */ | ||
44 | struct UnixRup | ||
45 | { | ||
46 | struct CmdBlk *CmdsWaitingP; /* Commands waiting to be done */ | ||
47 | struct CmdBlk *CmdPendingP; /* The command currently being sent */ | ||
48 | struct RUP *RupP; /* the Rup to send it to */ | ||
49 | uint Id; /* Id number */ | ||
50 | uint BaseSysPort; /* SysPort of first tty on this RTA */ | ||
51 | uint ModTypes; /* Modules on this RTA */ | ||
52 | spinlock_t RupLock; /* Lock structure for MPX */ | ||
53 | /* struct lockb RupLock; */ /* Lock structure for MPX */ | ||
54 | }; | ||
55 | |||
56 | #endif /* __rio_unixrup_h__ */ | ||