]>
Commit | Line | Data |
---|---|---|
cd1a2927 MT |
1 | /*\r |
2 | * PCMCIA bridge device probe\r | |
3 | *\r | |
4 | * This file is part of the IPCop Firewall.\r | |
5 | *\r | |
6 | * IPCop is free software; you can redistribute it and/or modify\r | |
7 | * it under the terms of the GNU General Public License as published by\r | |
8 | * the Free Software Foundation; either version 2 of the License, or\r | |
9 | * (at your option) any later version.\r | |
10 | *\r | |
11 | * IPCop is distributed in the hope that it will be useful,\r | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of\r | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r | |
14 | * GNU General Public License for more details.\r | |
15 | *\r | |
16 | * You should have received a copy of the GNU General Public License\r | |
17 | * along with IPCop; if not, write to the Free Software\r | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r | |
19 | *\r | |
20 | * The initial developer of the original code is David A. Hinds\r | |
21 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds\r | |
22 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.\r | |
23 | *\r | |
24 | * $Id: pcmcia.c,v 1.6.2.4 2005/12/08 02:12:28 franck78 Exp $\r | |
25 | *\r | |
26 | */\r | |
27 | \r | |
28 | #include "install.h"\r | |
29 | #include "pcmcia.h"\r | |
30 | \r | |
31 | #ifdef __GLIBC__\r | |
32 | #include <sys/io.h>\r | |
33 | #else\r | |
34 | #include <asm/io.h>\r | |
35 | #endif\r | |
36 | \r | |
37 | extern FILE *flog;\r | |
38 | extern int modprobe(char *);\r | |
39 | \r | |
40 | /*====================================================================*/\r | |
41 | \r | |
42 | typedef struct {\r | |
43 | u_short vendor, device;\r | |
44 | char *modname;\r | |
45 | char *name;\r | |
46 | } pci_id_t;\r | |
47 | \r | |
48 | pci_id_t pci_id[] = {\r | |
49 | { 0x1013, 0x1100, "i82365", "Cirrus Logic CL 6729" },\r | |
50 | { 0x1013, 0x1110, "yenta_socket", "Cirrus Logic PD 6832" },\r | |
51 | { 0x10b3, 0xb106, "yenta_socket", "SMC 34C90" },\r | |
52 | { 0x1180, 0x0465, "yenta_socket", "Ricoh RL5C465" },\r | |
53 | { 0x1180, 0x0466, "yenta_socket", "Ricoh RL5C466" },\r | |
54 | { 0x1180, 0x0475, "yenta_socket", "Ricoh RL5C475" },\r | |
55 | { 0x1180, 0x0476, "yenta_socket", "Ricoh RL5C476" },\r | |
56 | { 0x1180, 0x0477, "yenta_socket", "Ricoh RL5C477" },\r | |
57 | { 0x1180, 0x0478, "yenta_socket", "Ricoh RL5C478" },\r | |
58 | { 0x104c, 0xac12, "yenta_socket", "Texas Instruments PCI1130" }, \r | |
59 | { 0x104c, 0xac13, "yenta_socket", "Texas Instruments PCI1031" }, \r | |
60 | { 0x104c, 0xac15, "yenta_socket", "Texas Instruments PCI1131" }, \r | |
61 | { 0x104c, 0xac1a, "yenta_socket", "Texas Instruments PCI1210" }, \r | |
62 | { 0x104c, 0xac1e, "yenta_socket", "Texas Instruments PCI1211" }, \r | |
63 | { 0x104c, 0xac17, "yenta_socket", "Texas Instruments PCI1220" }, \r | |
64 | { 0x104c, 0xac19, "yenta_socket", "Texas Instruments PCI1221" }, \r | |
65 | { 0x104c, 0xac1c, "yenta_socket", "Texas Instruments PCI1225" }, \r | |
66 | { 0x104c, 0xac16, "yenta_socket", "Texas Instruments PCI1250" }, \r | |
67 | { 0x104c, 0xac1d, "yenta_socket", "Texas Instruments PCI1251A" }, \r | |
68 | { 0x104c, 0xac1f, "yenta_socket", "Texas Instruments PCI1251B" }, \r | |
69 | { 0x104c, 0xac50, "yenta_socket", "Texas Instruments PCI1410" }, \r | |
70 | { 0x104c, 0xac51, "yenta_socket", "Texas Instruments PCI1420" }, \r | |
71 | { 0x104c, 0xac1b, "yenta_socket", "Texas Instruments PCI1450" }, \r | |
72 | { 0x104c, 0xac52, "yenta_socket", "Texas Instruments PCI1451" }, \r | |
73 | { 0x104c, 0xac56, "yenta_socket", "Texas Instruments PCI1510" }, \r | |
74 | { 0x104c, 0xac55, "yenta_socket", "Texas Instruments PCI1520" }, \r | |
75 | { 0x104c, 0xac54, "yenta_socket", "Texas Instruments PCI1620" }, \r | |
76 | { 0x104c, 0xac41, "yenta_socket", "Texas Instruments PCI4410" }, \r | |
77 | { 0x104c, 0xac40, "yenta_socket", "Texas Instruments PCI4450" }, \r | |
78 | { 0x104c, 0xac42, "yenta_socket", "Texas Instruments PCI4451" }, \r | |
79 | { 0x104c, 0xac44, "yenta_socket", "Texas Instruments PCI4510" }, \r | |
80 | { 0x104c, 0xac46, "yenta_socket", "Texas Instruments PCI4520" }, \r | |
81 | { 0x104c, 0xac49, "yenta_socket", "Texas Instruments PCI7410" }, \r | |
82 | { 0x104c, 0xac47, "yenta_socket", "Texas Instruments PCI7510" }, \r | |
83 | { 0x104c, 0xac48, "yenta_socket", "Texas Instruments PCI7610" }, \r | |
84 | { 0x1217, 0x6729, "i82365", "O2 Micro 6729" }, \r | |
85 | { 0x1217, 0x673a, "i82365", "O2 Micro 6730" }, \r | |
86 | { 0x1217, 0x6832, "yenta_socket", "O2 Micro 6832/6833" }, \r | |
87 | { 0x1217, 0x6836, "yenta_socket", "O2 Micro 6836/6860" }, \r | |
88 | { 0x1217, 0x6872, "yenta_socket", "O2 Micro 6812" }, \r | |
89 | { 0x1217, 0x6925, "yenta_socket", "O2 Micro 6922" }, \r | |
90 | { 0x1217, 0x6933, "yenta_socket", "O2 Micro 6933" }, \r | |
91 | { 0x1217, 0x6972, "yenta_socket", "O2 Micro 6912" }, \r | |
92 | { 0x1179, 0x0603, "i82365", "Toshiba ToPIC95-A" }, \r | |
93 | { 0x1179, 0x060a, "yenta_socket", "Toshiba ToPIC95-B" }, \r | |
94 | { 0x1179, 0x060f, "yenta_socket", "Toshiba ToPIC97" }, \r | |
95 | { 0x1179, 0x0617, "yenta_socket", "Toshiba ToPIC100" }, \r | |
96 | { 0x119b, 0x1221, "i82365", "Omega Micro 82C092G" }, \r | |
97 | { 0x8086, 0x1221, "i82092", "Intel 82092AA_0" }, \r | |
98 | { 0x8086, 0x1222, "i82092", "Intel 82092AA_1" }, \r | |
99 | { 0x1524, 0x1211, "yenta_socket", "ENE 1211" },\r | |
100 | { 0x1524, 0x1225, "yenta_socket", "ENE 1225" },\r | |
101 | { 0x1524, 0x1410, "yenta_socket", "ENE 1410" },\r | |
102 | { 0x1524, 0x1420, "yenta_socket", "ENE 1420" },\r | |
103 | };\r | |
104 | #define PCI_COUNT (sizeof(pci_id)/sizeof(pci_id_t))\r | |
105 | \r | |
106 | static char * pci_probe()\r | |
107 | {\r | |
108 | char s[256], *modname = NULL;\r | |
109 | u_int device, vendor, i;\r | |
110 | FILE *f;\r | |
111 | \r | |
112 | if ((f = fopen("/proc/bus/pci/devices", "r")) != NULL) {\r | |
113 | while (fgets(s, 256, f) != NULL) {\r | |
114 | u_int n = strtoul(s+5, NULL, 16);\r | |
115 | vendor = (n >> 16); device = (n & 0xffff);\r | |
116 | for (i = 0; i < PCI_COUNT; i++)\r | |
117 | if ((vendor == pci_id[i].vendor) &&\r | |
118 | (device == pci_id[i].device)) break;\r | |
119 | \r | |
120 | if (i < PCI_COUNT) {\r | |
121 | modname = pci_id[i].modname;\r | |
122 | break;\r | |
123 | }\r | |
124 | }\r | |
125 | }\r | |
126 | \r | |
127 | return modname;\r | |
128 | }\r | |
129 | \r | |
130 | /*====================================================================*/\r | |
131 | \r | |
132 | #ifndef __alpha__\r | |
133 | typedef u_short ioaddr_t;\r | |
134 | \r | |
135 | static ioaddr_t i365_base = 0x03e0;\r | |
136 | \r | |
137 | static u_char i365_get(u_short sock, u_short reg)\r | |
138 | {\r | |
139 | u_char val = I365_REG(sock, reg);\r | |
140 | outb(val, i365_base); val = inb(i365_base+1);\r | |
141 | return val;\r | |
142 | }\r | |
143 | \r | |
144 | #if 0 // the following code do nothing usefull, it ends with return 0 anyway\r | |
145 | \r | |
146 | static void i365_set(u_short sock, u_short reg, u_char data)\r | |
147 | {\r | |
148 | u_char val = I365_REG(sock, reg);\r | |
149 | outb(val, i365_base); outb(data, i365_base+1);\r | |
150 | }\r | |
151 | \r | |
152 | static void i365_bset(u_short sock, u_short reg, u_char mask)\r | |
153 | {\r | |
154 | u_char d = i365_get(sock, reg);\r | |
155 | d |= mask;\r | |
156 | i365_set(sock, reg, d);\r | |
157 | }\r | |
158 | \r | |
159 | static void i365_bclr(u_short sock, u_short reg, u_char mask)\r | |
160 | {\r | |
161 | u_char d = i365_get(sock, reg);\r | |
162 | d &= ~mask;\r | |
163 | i365_set(sock, reg, d);\r | |
164 | }\r | |
165 | #endif\r | |
166 | \r | |
167 | int i365_probe()\r | |
168 | {\r | |
169 | int val, slot, sock, done;\r | |
170 | // char *name = "i82365sl";\r | |
171 | \r | |
172 | ioperm(i365_base, 4, 1);\r | |
173 | ioperm(0x80, 1, 1);\r | |
174 | for (slot = 0; slot < 2; slot++) {\r | |
175 | for (sock = done = 0; sock < 2; sock++) {\r | |
176 | val = i365_get(sock, I365_IDENT);\r | |
177 | switch (val) {\r | |
178 | case 0x82:\r | |
179 | // name = "i82365sl A step";\r | |
180 | // break;\r | |
181 | case 0x83:\r | |
182 | // name = "i82365sl B step";\r | |
183 | // break;\r | |
184 | case 0x84:\r | |
185 | // name = "VLSI 82C146";\r | |
186 | // break;\r | |
187 | case 0x88: case 0x89: case 0x8a:\r | |
188 | // name = "IBM Clone";\r | |
189 | // break;\r | |
190 | case 0x8b: case 0x8c:\r | |
191 | break;\r | |
192 | default:\r | |
193 | done = 1;\r | |
194 | }\r | |
195 | if (done) break;\r | |
196 | }\r | |
197 | if (done && sock) break;\r | |
198 | i365_base += 2;\r | |
199 | }\r | |
200 | \r | |
201 | if (sock == 0) {\r | |
202 | return -1;\r | |
203 | }\r | |
204 | \r | |
205 | #if 0 // the following code do nothing usefull, it ends with return 0 anyway\r | |
206 | if ((sock == 2) && (strcmp(name, "VLSI 82C146") == 0))\r | |
207 | name = "i82365sl DF";\r | |
208 | \r | |
209 | /* Check for Vadem chips */\r | |
210 | outb(0x0e, i365_base);\r | |
211 | outb(0x37, i365_base);\r | |
212 | i365_bset(0, VG468_MISC, VG468_MISC_VADEMREV);\r | |
213 | val = i365_get(0, I365_IDENT);\r | |
214 | if (val & I365_IDENT_VADEM) {\r | |
215 | if ((val & 7) < 4)\r | |
216 | name = "Vadem VG-468";\r | |
217 | else\r | |
218 | name = "Vadem VG-469";\r | |
219 | i365_bclr(0, VG468_MISC, VG468_MISC_VADEMREV);\r | |
220 | }\r | |
221 | \r | |
222 | /* Check for Cirrus CL-PD67xx chips */\r | |
223 | i365_set(0, PD67_CHIP_INFO, 0);\r | |
224 | val = i365_get(0, PD67_CHIP_INFO);\r | |
225 | if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {\r | |
226 | val = i365_get(0, PD67_CHIP_INFO);\r | |
227 | if ((val & PD67_INFO_CHIP_ID) == 0) {\r | |
228 | if (val & PD67_INFO_SLOTS)\r | |
229 | name = "Cirrus CL-PD672x";\r | |
230 | else {\r | |
231 | name = "Cirrus CL-PD6710";\r | |
232 | sock = 1;\r | |
233 | }\r | |
234 | i365_set(0, PD67_EXT_INDEX, 0xe5);\r | |
235 | if (i365_get(0, PD67_EXT_INDEX) != 0xe5)\r | |
236 | name = "VIA VT83C469";\r | |
237 | }\r | |
238 | }\r | |
239 | #endif\r | |
240 | return 0;\r | |
241 | \r | |
242 | } /* i365_probe */\r | |
243 | #endif\r | |
244 | \r | |
245 | /*====================================================================*/\r | |
246 | \r | |
247 | #ifndef __alpha__\r | |
248 | static u_short tcic_getw(ioaddr_t base, u_char reg)\r | |
249 | {\r | |
250 | u_short val = inw(base+reg);\r | |
251 | return val;\r | |
252 | }\r | |
253 | \r | |
254 | static void tcic_setw(ioaddr_t base, u_char reg, u_short data)\r | |
255 | {\r | |
256 | outw(data, base+reg);\r | |
257 | }\r | |
258 | \r | |
259 | int tcic_probe_at(ioaddr_t base)\r | |
260 | {\r | |
261 | int i;\r | |
262 | u_short old;\r | |
263 | \r | |
264 | /* Anything there?? */\r | |
265 | for (i = 0; i < 0x10; i += 2)\r | |
266 | if (tcic_getw(base, i) == 0xffff)\r | |
267 | return -1;\r | |
268 | \r | |
269 | /* Try to reset the chip */\r | |
270 | tcic_setw(base, TCIC_SCTRL, TCIC_SCTRL_RESET);\r | |
271 | tcic_setw(base, TCIC_SCTRL, 0);\r | |
272 | \r | |
273 | /* Can we set the addr register? */\r | |
274 | old = tcic_getw(base, TCIC_ADDR);\r | |
275 | tcic_setw(base, TCIC_ADDR, 0);\r | |
276 | if (tcic_getw(base, TCIC_ADDR) != 0) {\r | |
277 | tcic_setw(base, TCIC_ADDR, old);\r | |
278 | return -2;\r | |
279 | }\r | |
280 | \r | |
281 | tcic_setw(base, TCIC_ADDR, 0xc3a5);\r | |
282 | if (tcic_getw(base, TCIC_ADDR) != 0xc3a5)\r | |
283 | return -3;\r | |
284 | \r | |
285 | return 2;\r | |
286 | }\r | |
287 | \r | |
288 | int tcic_probe(ioaddr_t base)\r | |
289 | {\r | |
290 | int sock;\r | |
291 | \r | |
292 | ioperm(base, 16, 1);\r | |
293 | ioperm(0x80, 1, 1);\r | |
294 | sock = tcic_probe_at(base);\r | |
295 | \r | |
296 | if (sock <= 0) {\r | |
297 | return -1;\r | |
298 | }\r | |
299 | \r | |
300 | return 0;\r | |
301 | \r | |
302 | } /* tcic_probe */\r | |
303 | #endif\r | |
304 | \r | |
305 | /*====================================================================*/\r | |
306 | char * initialize_pcmcia (void)\r | |
307 | {\r | |
308 | #ifndef __alpha__\r | |
309 | ioaddr_t tcic_base = TCIC_BASE;\r | |
310 | #endif\r | |
311 | char* pcmcia;\r | |
312 | \r | |
313 | if ((pcmcia = pci_probe()))\r | |
314 | return pcmcia; /* we're all done */\r | |
315 | #ifndef __alpha__\r | |
316 | else if (i365_probe() == 0)\r | |
317 | return "i82365";\r | |
318 | else if (tcic_probe(tcic_base) == 0)\r | |
319 | return "tcic";\r | |
320 | #endif\r | |
321 | else {\r | |
322 | /* Detect ISAPNP based i82365 controllers */\r | |
323 | FILE *f;\r | |
324 | modprobe("i82365");\r | |
325 | if ((f = fopen("/proc/bus/pccard/00/info", "r"))) {\r | |
326 | fclose(f);\r | |
327 | return "i82365";\r | |
328 | }\r | |
329 | }\r | |
330 | \r | |
331 | return NULL;\r | |
332 | }\r |