1 | #ifdef CONFIG_PCMCIA |
---|
2 | |
---|
3 | /* |
---|
4 | * i82365.c |
---|
5 | * Support for i82365 and similar ISA-to-PCMCIA bridges |
---|
6 | * |
---|
7 | * Taken from Linux kernel sources, distributed under GPL2 |
---|
8 | * |
---|
9 | * Software distributed under the License is distributed on an "AS |
---|
10 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
---|
11 | * implied. See the License for the specific language governing |
---|
12 | * rights and limitations under the License. |
---|
13 | * |
---|
14 | * The initial developer of the original code is David A. Hinds |
---|
15 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds |
---|
16 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
---|
17 | * |
---|
18 | * Ported by: Anselm Martin Hoffmeister, Stockholm Projekt Computer-Service, Sankt Augustin/Bonn, GERMANY |
---|
19 | */ |
---|
20 | |
---|
21 | /* |
---|
22 | * |
---|
23 | * |
---|
24 | * ****************************** |
---|
25 | * PLEASE DO NOT YET WORK ON THIS |
---|
26 | * ****************************** |
---|
27 | * |
---|
28 | * I'm still fixing it up on every end, so we most probably would interfere |
---|
29 | * at some point. If there's anything obvious or better, not-so-obvious, |
---|
30 | * please contact me by e-mail: anselm (AT) hoffmeister (DOT) be *THANKS* |
---|
31 | */ |
---|
32 | #include "../include/pcmcia.h" |
---|
33 | #include "../include/pcmcia-opts.h" |
---|
34 | #include "../include/i82365.h" |
---|
35 | |
---|
36 | #ifndef CONFIG_ISA |
---|
37 | #error PCMCIA_I82365 only works with ISA defined - set CONFIG_ISA |
---|
38 | #endif |
---|
39 | |
---|
40 | typedef enum pcic_id { |
---|
41 | IS_I82365A, IS_I82365B, IS_I82365DF, |
---|
42 | IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469, |
---|
43 | IS_PD6710, IS_PD672X, IS_VT83C469, |
---|
44 | } pcic_id; |
---|
45 | |
---|
46 | /* Flags for classifying groups of controllers */ |
---|
47 | #define IS_VADEM 0x0001 |
---|
48 | #define IS_CIRRUS 0x0002 |
---|
49 | #define IS_TI 0x0004 |
---|
50 | #define IS_O2MICRO 0x0008 |
---|
51 | #define IS_VIA 0x0010 |
---|
52 | #define IS_TOPIC 0x0020 |
---|
53 | #define IS_RICOH 0x0040 |
---|
54 | #define IS_UNKNOWN 0x0400 |
---|
55 | #define IS_VG_PWR 0x0800 |
---|
56 | #define IS_DF_PWR 0x1000 |
---|
57 | #define IS_PCI 0x2000 |
---|
58 | #define IS_ALIVE 0x8000 |
---|
59 | |
---|
60 | typedef struct pcic_t { |
---|
61 | char *name; |
---|
62 | u_short flags; |
---|
63 | } pcic_t; |
---|
64 | |
---|
65 | static pcic_t pcic[] = { |
---|
66 | { "Intel i82365sl A step", 0 }, |
---|
67 | { "Intel i82365sl B step", 0 }, |
---|
68 | { "Intel i82365sl DF", IS_DF_PWR }, |
---|
69 | { "IBM Clone", 0 }, |
---|
70 | { "Ricoh RF5C296/396", 0 }, |
---|
71 | { "VLSI 82C146", 0 }, |
---|
72 | { "Vadem VG-468", IS_VADEM }, |
---|
73 | { "Vadem VG-469", IS_VADEM|IS_VG_PWR }, |
---|
74 | { "Cirrus PD6710", IS_CIRRUS }, |
---|
75 | { "Cirrus PD672x", IS_CIRRUS }, |
---|
76 | { "VIA VT83C469", IS_CIRRUS|IS_VIA }, |
---|
77 | }; |
---|
78 | |
---|
79 | typedef struct cirrus_state_t { |
---|
80 | u_char misc1, misc2; |
---|
81 | u_char timer[6]; |
---|
82 | } cirrus_state_t; |
---|
83 | |
---|
84 | typedef struct vg46x_state_t { |
---|
85 | u_char ctl, ema; |
---|
86 | } vg46x_state_t; |
---|
87 | |
---|
88 | typedef struct socket_info_t { |
---|
89 | u_short type, flags; |
---|
90 | socket_cap_t cap; |
---|
91 | ioaddr_t ioaddr; |
---|
92 | u_short psock; |
---|
93 | u_char cs_irq, intr; |
---|
94 | void (*handler)(void *info, u_int events); |
---|
95 | void *info; |
---|
96 | union { |
---|
97 | cirrus_state_t cirrus; |
---|
98 | vg46x_state_t vg46x; |
---|
99 | } state; |
---|
100 | } socket_info_t; |
---|
101 | |
---|
102 | //static socket_info_t socket[8]; |
---|
103 | |
---|
104 | int i365_base = 0x3e0; // Default in Linux kernel |
---|
105 | int cycle_time = 120; // External clock time in ns, 120ns =~ 8.33 MHz |
---|
106 | int mydriverid = 0; |
---|
107 | |
---|
108 | void phex ( unsigned char c ); |
---|
109 | /*static int to_cycles(int ns) |
---|
110 | { |
---|
111 | return ns/cycle_time; |
---|
112 | } |
---|
113 | */ |
---|
114 | /*static int to_ns(int cycles) |
---|
115 | { |
---|
116 | return cycle_time*cycles; |
---|
117 | } |
---|
118 | */ |
---|
119 | |
---|
120 | static u_char i365_get(u_short sock, u_short reg) |
---|
121 | { |
---|
122 | //unsigned long flags; |
---|
123 | //spin_lock_irqsave(&bus_lock,flags); |
---|
124 | { |
---|
125 | ioaddr_t port = pccsock[sock].ioaddr; |
---|
126 | u_char val; |
---|
127 | reg = I365_REG(pccsock[sock].internalid, reg); |
---|
128 | outb(reg, port); val = inb(port+1); |
---|
129 | //spin_unlock_irqrestore(&bus_lock,flags); |
---|
130 | return val; |
---|
131 | } |
---|
132 | } |
---|
133 | |
---|
134 | static void i365_set(u_short sock, u_short reg, u_char data) |
---|
135 | { |
---|
136 | //unsigned long flags; |
---|
137 | //spin_lock_irqsave(&bus_lock,flags); |
---|
138 | { |
---|
139 | ioaddr_t port = pccsock[sock].ioaddr; |
---|
140 | u_char val = I365_REG(pccsock[sock].internalid, reg); |
---|
141 | outb(val, port); outb(data, port+1); |
---|
142 | //spin_unlock_irqrestore(&bus_lock,flags); |
---|
143 | } |
---|
144 | } |
---|
145 | |
---|
146 | void add_socket_i365(u_short port, int psock, int type) { |
---|
147 | pccsock[pccsocks].ioaddr = port; |
---|
148 | pccsock[pccsocks].internalid = psock; |
---|
149 | pccsock[pccsocks].type = type; |
---|
150 | pccsock[pccsocks].flags = pcic[type].flags; |
---|
151 | pccsock[pccsocks].drivernum = mydriverid; |
---|
152 | pccsock[pccsocks].configoffset = -1; |
---|
153 | // Find out if a card in inside that socket |
---|
154 | pccsock[pccsocks].status = (( 12 == (i365_get(pccsocks,I365_STATUS)&12) ) ? HASCARD : EMPTY ); |
---|
155 | // *TODO* check if that's all |
---|
156 | if ( 0 == (psock & 1) ) { |
---|
157 | printf ( "Found a PCMCIA controller (i82365) at io %x, type '%s'\n", port, pcic[type].name ); |
---|
158 | // pccsock[pccsocks].status == HASCARD? "holds card":"empty" ); |
---|
159 | } |
---|
160 | pccsocks++; |
---|
161 | return; |
---|
162 | } |
---|
163 | |
---|
164 | void i365_bset(u_short sock, u_short reg, u_char mask) { |
---|
165 | u_char d = i365_get(sock, reg); |
---|
166 | d |= mask; |
---|
167 | i365_set(sock, reg, d); |
---|
168 | } |
---|
169 | |
---|
170 | void i365_bclr(u_short sock, u_short reg, u_char mask) { |
---|
171 | u_char d = i365_get(sock, reg); |
---|
172 | d &= ~mask; |
---|
173 | i365_set(sock, reg, d); |
---|
174 | } |
---|
175 | |
---|
176 | |
---|
177 | /*static void i365_bflip(u_short sock, u_short reg, u_char mask, int b) |
---|
178 | { |
---|
179 | u_char d = i365_get(sock, reg); |
---|
180 | if (b) |
---|
181 | d |= mask; |
---|
182 | else |
---|
183 | d &= ~mask; |
---|
184 | i365_set(sock, reg, d); |
---|
185 | } |
---|
186 | */ |
---|
187 | |
---|
188 | /* |
---|
189 | static u_short i365_get_pair(u_short sock, u_short reg) |
---|
190 | { |
---|
191 | u_short a, b; |
---|
192 | a = i365_get(sock, reg); |
---|
193 | b = i365_get(sock, reg+1); |
---|
194 | return (a + (b<<8)); |
---|
195 | } |
---|
196 | */ |
---|
197 | |
---|
198 | /* |
---|
199 | static void i365_set_pair(u_short sock, u_short reg, u_short data) |
---|
200 | { |
---|
201 | i365_set(sock, reg, data & 0xff); |
---|
202 | i365_set(sock, reg+1, data >> 8); |
---|
203 | } |
---|
204 | */ |
---|
205 | int identify_i365 ( u_short port, u_short sock ) { |
---|
206 | u_char val; |
---|
207 | int type = -1; |
---|
208 | /* Use the next free entry in the socket table */ |
---|
209 | pccsock[pccsocks].ioaddr = port; |
---|
210 | pccsock[pccsocks].internalid = sock; |
---|
211 | // *TODO* wakeup a sleepy cirrus controller? |
---|
212 | |
---|
213 | if ((val = i365_get(pccsocks, I365_IDENT)) & 0x70) |
---|
214 | return -1; |
---|
215 | switch (val) { |
---|
216 | case 0x82: |
---|
217 | type = IS_I82365A; break; |
---|
218 | case 0x83: |
---|
219 | type = IS_I82365B; break; |
---|
220 | case 0x84: |
---|
221 | type = IS_I82365DF; break; |
---|
222 | case 0x88: case 0x89: case 0x8a: |
---|
223 | type = IS_IBM; break; |
---|
224 | } |
---|
225 | /* Check for Vadem VG-468 chips */ |
---|
226 | outb(0x0e, port); |
---|
227 | outb(0x37, port); |
---|
228 | i365_bset(pccsocks, VG468_MISC, VG468_MISC_VADEMREV); |
---|
229 | val = i365_get(pccsocks, I365_IDENT); |
---|
230 | if (val & I365_IDENT_VADEM) { |
---|
231 | i365_bclr(pccsocks, VG468_MISC, VG468_MISC_VADEMREV); |
---|
232 | type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468; |
---|
233 | } |
---|
234 | |
---|
235 | /* Check for Ricoh chips */ |
---|
236 | val = i365_get(pccsocks, RF5C_CHIP_ID); |
---|
237 | if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396)) type = IS_RF5Cx96; |
---|
238 | |
---|
239 | /* Check for Cirrus CL-PD67xx chips */ |
---|
240 | i365_set(pccsocks, PD67_CHIP_INFO, 0); |
---|
241 | val = i365_get(pccsocks, PD67_CHIP_INFO); |
---|
242 | if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) { |
---|
243 | val = i365_get(pccsocks, PD67_CHIP_INFO); |
---|
244 | if ((val & PD67_INFO_CHIP_ID) == 0) { |
---|
245 | type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710; |
---|
246 | i365_set(pccsocks, PD67_EXT_INDEX, 0xe5); |
---|
247 | if (i365_get(pccsocks, PD67_EXT_INDEX) != 0xe5) type = IS_VT83C469; |
---|
248 | } |
---|
249 | } |
---|
250 | return type; |
---|
251 | } |
---|
252 | |
---|
253 | int init_i82365(void) { |
---|
254 | int i, j, sock, k, ns, id; |
---|
255 | //unsigned int ui,uj; |
---|
256 | //unsigned char * upc; |
---|
257 | ioaddr_t port; |
---|
258 | int i82365s = 0; |
---|
259 | // Change from kernel: No irq init, no check_region, no isapnp support |
---|
260 | // No ignore socket, no extra sockets to check (so it's easier here :-/) |
---|
261 | // Probably we don't need any of them; in case YOU do, SHOUT AT ME! |
---|
262 | id = identify_i365(i365_base, 0); |
---|
263 | if ((id == IS_I82365DF) && (identify_i365(i365_base, 1) != id)) { |
---|
264 | for (i = 0; i < 4; i++) { |
---|
265 | port = i365_base + ((i & 1) << 2) + ((i & 2) << 1); |
---|
266 | sock = (i & 1) << 1; |
---|
267 | if (identify_i365(port, sock) == IS_I82365DF) { |
---|
268 | add_socket_i365(port, sock, IS_VLSI); |
---|
269 | } |
---|
270 | } |
---|
271 | } else { |
---|
272 | for (i = 0; i < 4; i += 2) { |
---|
273 | port = i365_base + 2*(i>>2); |
---|
274 | sock = (i & 3); |
---|
275 | id = identify_i365(port, sock); |
---|
276 | if (id < 0) continue; |
---|
277 | |
---|
278 | for (j = ns = 0; j < 2; j++) { |
---|
279 | /* Does the socket exist? */ |
---|
280 | if (identify_i365(port, sock+j) < 0) continue; |
---|
281 | /* Check for bad socket decode */ |
---|
282 | for (k = 0; k <= i82365s; k++) |
---|
283 | i365_set(k, I365_MEM(0)+I365_W_OFF, k); |
---|
284 | for (k = 0; k <= i82365s; k++) |
---|
285 | if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k) |
---|
286 | break; |
---|
287 | if (k <= i82365s) break; |
---|
288 | add_socket_i365(port, sock+j, id); ns++; |
---|
289 | } |
---|
290 | } |
---|
291 | } |
---|
292 | return 0; |
---|
293 | |
---|
294 | |
---|
295 | |
---|
296 | |
---|
297 | |
---|
298 | |
---|
299 | |
---|
300 | /* printf ( "Selecting config 1: io 0x300 @byte 87*2.." ); |
---|
301 | upc[(2*87)] = 2; |
---|
302 | i365_bclr(1, I365_ADDRWIN, 1 ); |
---|
303 | i365_set(1,I365_INTCTL, 0x65 ); //no-reset, memory-card |
---|
304 | i365_set(1, I365_IO(0)+0, 0x20 ); |
---|
305 | i365_set(1, I365_IO(0)+1, 0x03 ); |
---|
306 | i365_set(1, I365_IO(0)+2, 0x3f ); |
---|
307 | i365_set(1, I365_IO(0)+3, 0x03 ); |
---|
308 | i365_set(1, 0x3a, 0x05 ); |
---|
309 | i365_set(1, 0x3b, 0x05 ); |
---|
310 | i365_set(1, 0x3c, 0x05 ); |
---|
311 | i365_set(1, 0x3d, 0x05 ); |
---|
312 | i365_set(1, 0x3e, 0x05 ); |
---|
313 | i365_set(1, 0x3f, 0x05 ); |
---|
314 | i365_set(1, 0x07, 0x0a ); |
---|
315 | i365_set(1, I365_ADDRWIN, 0x40 ); // 0x40 |
---|
316 | printf ( "!\n" ); getchar(); |
---|
317 | printf ( "\n" ); |
---|
318 | return 0; */ |
---|
319 | } |
---|
320 | |
---|
321 | void phex ( unsigned char c ) { |
---|
322 | unsigned char a = 0, b = 0; |
---|
323 | b = ( c & 0xf ); |
---|
324 | if ( b > 9 ) b += ('a'-'9'-1); |
---|
325 | b += '0'; |
---|
326 | a = ( c & 0xf0 ) >> 4; |
---|
327 | if ( a > 9 ) a += ('a'-'9'-1); |
---|
328 | a += '0'; |
---|
329 | printf ( "%c%c ", a, b ); |
---|
330 | return; |
---|
331 | } |
---|
332 | |
---|
333 | int deinit_i82365(void) { |
---|
334 | printf("Deinitializing i82365\n" ); |
---|
335 | return 0; |
---|
336 | } |
---|
337 | |
---|
338 | /*static int i365_get_status(u_short sock, u_int *value) |
---|
339 | { |
---|
340 | u_int status; |
---|
341 | |
---|
342 | status = i365_get(sock, I365_STATUS); |
---|
343 | *value = ((status & I365_CS_DETECT) == I365_CS_DETECT) |
---|
344 | ? SS_DETECT : 0; |
---|
345 | |
---|
346 | if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) |
---|
347 | *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG; |
---|
348 | else { |
---|
349 | *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD; |
---|
350 | *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN; |
---|
351 | } |
---|
352 | *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0; |
---|
353 | *value |= (status & I365_CS_READY) ? SS_READY : 0; |
---|
354 | *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0; |
---|
355 | |
---|
356 | #ifdef CONFIG_ISA |
---|
357 | if (pccsock[sock].type == IS_VG469) { |
---|
358 | status = i365_get(sock, VG469_VSENSE); |
---|
359 | if (pccsock[sock].internalid & 1) { |
---|
360 | *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD; |
---|
361 | *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD; |
---|
362 | } else { |
---|
363 | *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD; |
---|
364 | *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD; |
---|
365 | } |
---|
366 | } |
---|
367 | #endif |
---|
368 | |
---|
369 | printf("i82365: GetStatus(%d) = %#4.4x\n", sock, *value); |
---|
370 | return 0; |
---|
371 | } //i365_get_status |
---|
372 | */ |
---|
373 | |
---|
374 | /*static int i365_set_socket(u_short sock, socket_state_t *state) |
---|
375 | { |
---|
376 | socket_info_t *t = &socket[sock]; |
---|
377 | u_char reg; |
---|
378 | |
---|
379 | printf("i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " |
---|
380 | "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags, |
---|
381 | state->Vcc, state->Vpp, state->io_irq, state->csc_mask); |
---|
382 | printf ("\nERROR:UNIMPLEMENTED\n" ); |
---|
383 | return 0; |
---|
384 | // First set global controller options |
---|
385 | // set_bridge_state(sock); *TODO* check: need this here? |
---|
386 | |
---|
387 | // IO card, RESET flag, IO interrupt |
---|
388 | reg = t->intr; |
---|
389 | if (state->io_irq != t->cap.pci_irq) reg |= state->io_irq; |
---|
390 | reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET; |
---|
391 | reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0; |
---|
392 | i365_set(sock, I365_INTCTL, reg); |
---|
393 | |
---|
394 | reg = I365_PWR_NORESET; |
---|
395 | if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO; |
---|
396 | if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT; |
---|
397 | |
---|
398 | if (t->flags & IS_CIRRUS) { |
---|
399 | if (state->Vpp != 0) { |
---|
400 | if (state->Vpp == 120) |
---|
401 | reg |= I365_VPP1_12V; |
---|
402 | else if (state->Vpp == state->Vcc) |
---|
403 | reg |= I365_VPP1_5V; |
---|
404 | else return -EINVAL; |
---|
405 | } |
---|
406 | if (state->Vcc != 0) { |
---|
407 | reg |= I365_VCC_5V; |
---|
408 | if (state->Vcc == 33) |
---|
409 | i365_bset(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); |
---|
410 | else if (state->Vcc == 50) |
---|
411 | i365_bclr(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V); |
---|
412 | else return -EINVAL; |
---|
413 | } |
---|
414 | } else if (t->flags & IS_VG_PWR) { |
---|
415 | if (state->Vpp != 0) { |
---|
416 | if (state->Vpp == 120) |
---|
417 | reg |= I365_VPP1_12V; |
---|
418 | else if (state->Vpp == state->Vcc) |
---|
419 | reg |= I365_VPP1_5V; |
---|
420 | else return -EINVAL; |
---|
421 | } |
---|
422 | if (state->Vcc != 0) { |
---|
423 | reg |= I365_VCC_5V; |
---|
424 | if (state->Vcc == 33) |
---|
425 | i365_bset(sock, VG469_VSELECT, VG469_VSEL_VCC); |
---|
426 | else if (state->Vcc == 50) |
---|
427 | i365_bclr(sock, VG469_VSELECT, VG469_VSEL_VCC); |
---|
428 | else return -EINVAL; |
---|
429 | } |
---|
430 | } else if (t->flags & IS_DF_PWR) { |
---|
431 | switch (state->Vcc) { |
---|
432 | case 0: break; |
---|
433 | case 33: reg |= I365_VCC_3V; break; |
---|
434 | case 50: reg |= I365_VCC_5V; break; |
---|
435 | default: return -EINVAL; |
---|
436 | } |
---|
437 | switch (state->Vpp) { |
---|
438 | case 0: break; |
---|
439 | case 50: reg |= I365_VPP1_5V; break; |
---|
440 | case 120: reg |= I365_VPP1_12V; break; |
---|
441 | default: return -EINVAL; |
---|
442 | } |
---|
443 | } else { |
---|
444 | switch (state->Vcc) { |
---|
445 | case 0: break; |
---|
446 | case 50: reg |= I365_VCC_5V; break; |
---|
447 | default: return -EINVAL; |
---|
448 | } |
---|
449 | switch (state->Vpp) { |
---|
450 | case 0: break; |
---|
451 | case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break; |
---|
452 | case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break; |
---|
453 | default: return -EINVAL; |
---|
454 | } |
---|
455 | } |
---|
456 | |
---|
457 | if (reg != i365_get(sock, I365_POWER)) |
---|
458 | i365_set(sock, I365_POWER, reg); |
---|
459 | |
---|
460 | // Chipset-specific functions |
---|
461 | if (t->flags & IS_CIRRUS) { |
---|
462 | // Speaker control |
---|
463 | i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA, |
---|
464 | state->flags & SS_SPKR_ENA); |
---|
465 | } |
---|
466 | |
---|
467 | // Card status change interrupt mask |
---|
468 | reg = t->cs_irq << 4; |
---|
469 | if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT; |
---|
470 | if (state->flags & SS_IOCARD) { |
---|
471 | if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG; |
---|
472 | } else { |
---|
473 | if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1; |
---|
474 | if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2; |
---|
475 | if (state->csc_mask & SS_READY) reg |= I365_CSC_READY; |
---|
476 | } |
---|
477 | i365_set(sock, I365_CSCINT, reg); |
---|
478 | i365_get(sock, I365_CSC); |
---|
479 | |
---|
480 | return 0; |
---|
481 | } // i365_set_socket |
---|
482 | */ |
---|
483 | |
---|
484 | /*static int i365_get_io_map(u_short sock, struct pccard_io_map *io) |
---|
485 | { |
---|
486 | u_char map, ioctl, addr; |
---|
487 | printf ( "GETIOMAP unimplemented\n" ); return 0; |
---|
488 | map = io->map; |
---|
489 | if (map > 1) return -EINVAL; |
---|
490 | io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START); |
---|
491 | io->stop = i365_get_pair(sock, I365_IO(map)+I365_W_STOP); |
---|
492 | ioctl = i365_get(sock, I365_IOCTL); |
---|
493 | addr = i365_get(sock, I365_ADDRWIN); |
---|
494 | io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; |
---|
495 | io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0; |
---|
496 | io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0; |
---|
497 | io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0; |
---|
498 | io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0; |
---|
499 | printf("i82365: GetIOMap(%d, %d) = %#2.2x, %d ns, " |
---|
500 | "%#4.4x-%#4.4x\n", sock, map, io->flags, io->speed, |
---|
501 | io->start, io->stop); |
---|
502 | return 0; |
---|
503 | } // i365_get_io_map |
---|
504 | */ |
---|
505 | |
---|
506 | /*====================================================================*/ |
---|
507 | |
---|
508 | /*static int i365_set_io_map(u_short sock, struct pccard_io_map *io) |
---|
509 | { |
---|
510 | u_char map, ioctl; |
---|
511 | |
---|
512 | printf("i82365: SetIOMap(%d, %d, %#2.2x, %d ns, " |
---|
513 | "%#4.4x-%#4.4x)\n", sock, io->map, io->flags, |
---|
514 | io->speed, io->start, io->stop); |
---|
515 | printf ( "UNIMPLEMENTED\n" ); |
---|
516 | return 0; |
---|
517 | map = io->map; |
---|
518 | //if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) || |
---|
519 | if ((map > 1) || |
---|
520 | (io->stop < io->start)) return -EINVAL; |
---|
521 | // Turn off the window before changing anything |
---|
522 | if (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(map)) |
---|
523 | i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map)); |
---|
524 | i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start); |
---|
525 | i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop); |
---|
526 | ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map); |
---|
527 | if (io->speed) ioctl |= I365_IOCTL_WAIT(map); |
---|
528 | if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); |
---|
529 | if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); |
---|
530 | if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); |
---|
531 | i365_set(sock, I365_IOCTL, ioctl); |
---|
532 | // Turn on the window if necessary |
---|
533 | if (io->flags & MAP_ACTIVE) |
---|
534 | i365_bset(sock, I365_ADDRWIN, I365_ENA_IO(map)); |
---|
535 | return 0; |
---|
536 | } // i365_set_io_map |
---|
537 | */ |
---|
538 | |
---|
539 | /* |
---|
540 | static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem) |
---|
541 | { |
---|
542 | u_short base, i; |
---|
543 | u_char map; |
---|
544 | |
---|
545 | printf("i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5" |
---|
546 | "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed, |
---|
547 | mem->sys_start, mem->sys_stop, mem->card_start); |
---|
548 | |
---|
549 | printf ( "UNIMPLEMENTED\n" ); |
---|
550 | return 0; |
---|
551 | map = mem->map; |
---|
552 | if ((map > 4) || (mem->card_start > 0x3ffffff) || |
---|
553 | (mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) |
---|
554 | return -EINVAL; |
---|
555 | if (!(socket[sock].flags & IS_PCI) && |
---|
556 | ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))) |
---|
557 | return -EINVAL; |
---|
558 | |
---|
559 | // Turn off the window before changing anything |
---|
560 | if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map)) |
---|
561 | i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map)); |
---|
562 | |
---|
563 | base = I365_MEM(map); |
---|
564 | i = (mem->sys_start >> 12) & 0x0fff; |
---|
565 | if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT; |
---|
566 | if (mem->flags & MAP_0WS) i |= I365_MEM_0WS; |
---|
567 | i365_set_pair(sock, base+I365_W_START, i); |
---|
568 | |
---|
569 | i = (mem->sys_stop >> 12) & 0x0fff; |
---|
570 | switch (to_cycles(mem->speed)) { |
---|
571 | case 0: break; |
---|
572 | case 1: i |= I365_MEM_WS0; break; |
---|
573 | case 2: i |= I365_MEM_WS1; break; |
---|
574 | default: i |= I365_MEM_WS1 | I365_MEM_WS0; break; |
---|
575 | } |
---|
576 | i365_set_pair(sock, base+I365_W_STOP, i); |
---|
577 | |
---|
578 | i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; |
---|
579 | if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT; |
---|
580 | if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG; |
---|
581 | i365_set_pair(sock, base+I365_W_OFF, i); |
---|
582 | |
---|
583 | // Turn on the window if necessary |
---|
584 | if (mem->flags & MAP_ACTIVE) |
---|
585 | i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map)); |
---|
586 | return 0; |
---|
587 | } // i365_set_mem_map |
---|
588 | */ |
---|
589 | |
---|
590 | |
---|
591 | int i82365_interfacer ( interface_func_t func, int sockno, int par1, int par2, void* par3 ) { |
---|
592 | //int i, j, k; |
---|
593 | //u_int ui; |
---|
594 | u_char *upc; |
---|
595 | struct pcc_config_t * pccc; |
---|
596 | switch ( func ) { |
---|
597 | case INIT: |
---|
598 | mydriverid = par1; |
---|
599 | return init_i82365(); |
---|
600 | case SHUTDOWN: |
---|
601 | i365_set(sockno, I365_ADDRWIN, i365_get(sockno, I365_ADDRWIN) & 0x20 ); |
---|
602 | i365_set(sockno, I365_INTCTL, 0x05 ); |
---|
603 | sleepticks(2); |
---|
604 | i365_set(sockno,I365_INTCTL, 0x45 ); //no-reset, memory-card |
---|
605 | break; |
---|
606 | case MAPATTRMEM: |
---|
607 | i365_set(sockno,I365_POWER, 0xb1 ); |
---|
608 | i365_set(sockno, I365_INTCTL, 0x05 ); |
---|
609 | sleepticks(2); |
---|
610 | i365_set(sockno,I365_INTCTL, 0x45 ); //no-reset, memory-card |
---|
611 | i365_set(sockno, I365_ADDRWIN, i365_get(sockno, I365_ADDRWIN) & 0x20 ); |
---|
612 | //i365_bclr(sockno, I365_ADDRWIN, 1 ); |
---|
613 | i365_set(sockno, I365_MEM(0)+0, ( par1 >> 12 )& 0xff ); //start |
---|
614 | i365_set(sockno, I365_MEM(0)+1, ( par1 >> 20 ) & 0x0f ); |
---|
615 | i365_set(sockno, I365_MEM(0)+2, ((par1 + par2 - 1 ) >> 12 ) & 0xff ); //end |
---|
616 | i365_set(sockno, I365_MEM(0)+3, (( par1 + par2 - 1 ) >> 20 ) & 0x0f ); |
---|
617 | i365_set(sockno, I365_MEM(0)+4, ((0x4000000 - par1) >> 12) & 0xff ); //offset low |
---|
618 | i365_set(sockno, I365_MEM(0)+5, 0x40 | (((0x40000000 - par1) >> 12) & 0x3f)); |
---|
619 | i365_bset(sockno, I365_ADDRWIN, 1 ); |
---|
620 | if ( ! ( 1 & i365_get ( sockno, I365_ADDRWIN ) ) ) return 1; |
---|
621 | break; |
---|
622 | case UNMAPATTRMEM: |
---|
623 | i365_set(sockno, I365_ADDRWIN, i365_get(sockno, I365_ADDRWIN) & 0x20 ); |
---|
624 | i365_set(sockno,I365_INTCTL, 0x45 ); //no-reset, memory-card |
---|
625 | break; |
---|
626 | case SELECTCONFIG: // Params: par1: config number; par3 config pointer pointer |
---|
627 | if ( 0 > pccsock[sockno].configoffset ) return 1; |
---|
628 | if ( NULL == (pccc = par3 ) ) return 2; |
---|
629 | // write config number to |
---|
630 | upc = ioremap ( MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN ); |
---|
631 | if ( pccsock[sockno].configoffset > MAP_ATTRMEM_LEN ) return 3; |
---|
632 | if ( ( par1 & 0x7fffffc0 ) ) return 4; |
---|
633 | if ( pccc->index != par1 ) return 5; |
---|
634 | upc[pccsock[sockno].configoffset] = ( upc[pccsock[sockno].configoffset] & 0xc0 ) | ( par1 & 0x3f ); |
---|
635 | i365_set(sockno, I365_IOCTL, (i365_get(sockno, I365_IOCTL) & 0xfe) | 0x20 ); // 16bit autosize |
---|
636 | i365_set(sockno, I365_IO(0)+0, pccc->iowin & 0xff); |
---|
637 | i365_set(sockno, I365_IO(0)+1, (pccc->iowin >> 8) & 0xff); |
---|
638 | i365_set(sockno, I365_IO(0)+2, (pccc->iowin+pccc->iolen - 1) & 0xff); |
---|
639 | i365_set(sockno, I365_IO(0)+3, ((pccc->iowin+pccc->iolen- 1) >> 8) & 0xff); |
---|
640 | // Disable mem mapping |
---|
641 | i365_bclr(sockno, I365_ADDRWIN, 1); |
---|
642 | i365_set(sockno, I365_INTCTL, 0x65); |
---|
643 | i365_bset(sockno, I365_ADDRWIN,0x40); |
---|
644 | break; |
---|
645 | default: |
---|
646 | return -1; // ERROR: Unknown function called |
---|
647 | } |
---|
648 | return 0; |
---|
649 | } |
---|
650 | |
---|
651 | // get_mem_map[1320] |
---|
652 | // cirrus_get_state/set/opts... |
---|
653 | // vg46x_get_state/... |
---|
654 | // get_bridge_state/... |
---|
655 | |
---|
656 | #endif /* CONFIG_PCMCIA */ |
---|