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 (at) 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 */ 657