iPXE
i82365.c
Go to the documentation of this file.
00001 #ifdef CONFIG_PCMCIA
00002 
00003 /*
00004  *      i82365.c
00005  *      Support for i82365 and similar ISA-to-PCMCIA bridges
00006  *
00007  *      Taken from Linux kernel sources, distributed under GPL2
00008  *
00009  *   Software distributed under the License is distributed on an "AS
00010  *   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
00011  *   implied. See the License for the specific language governing
00012  *   rights and limitations under the License.
00013  *
00014  *   The initial developer of the original code is David A. Hinds
00015  *   <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
00016  *   are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
00017  *
00018  *      Ported by: Anselm Martin Hoffmeister, Stockholm Projekt Computer-Service, Sankt Augustin/Bonn, GERMANY
00019  */
00020 
00021 /*
00022  *
00023  *
00024  *                      ******************************
00025  *                      PLEASE DO NOT YET WORK ON THIS
00026  *                      ******************************
00027  *
00028  *      I'm still fixing it up on every end, so we most probably would interfere
00029  *      at some point. If there's anything obvious or better, not-so-obvious,
00030  *      please contact me by e-mail: anselm (AT) hoffmeister (DOT) be   *THANKS*
00031  */
00032 #include "../include/pcmcia.h"
00033 #include "../include/pcmcia-opts.h"
00034 #include "../include/i82365.h"
00035 
00036 #ifndef CONFIG_ISA
00037 #error  PCMCIA_I82365 only works with ISA defined - set CONFIG_ISA
00038 #endif
00039 
00040 typedef enum pcic_id {
00041     IS_I82365A, IS_I82365B, IS_I82365DF,
00042     IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
00043     IS_PD6710, IS_PD672X, IS_VT83C469,
00044 } pcic_id;
00045 
00046 /* Flags for classifying groups of controllers */
00047 #define IS_VADEM        0x0001
00048 #define IS_CIRRUS       0x0002
00049 #define IS_TI           0x0004
00050 #define IS_O2MICRO      0x0008
00051 #define IS_VIA          0x0010
00052 #define IS_TOPIC        0x0020
00053 #define IS_RICOH        0x0040
00054 #define IS_UNKNOWN      0x0400
00055 #define IS_VG_PWR       0x0800
00056 #define IS_DF_PWR       0x1000
00057 #define IS_PCI          0x2000
00058 #define IS_ALIVE        0x8000
00059 
00060 typedef struct pcic_t {
00061     char                *name;
00062     u_short             flags;
00063 } pcic_t;
00064 
00065 static pcic_t pcic[] = {
00066     { "Intel i82365sl A step", 0 },
00067     { "Intel i82365sl B step", 0 },
00068     { "Intel i82365sl DF", IS_DF_PWR },
00069     { "IBM Clone", 0 },
00070     { "Ricoh RF5C296/396", 0 },
00071     { "VLSI 82C146", 0 },
00072     { "Vadem VG-468", IS_VADEM },
00073     { "Vadem VG-469", IS_VADEM|IS_VG_PWR },
00074     { "Cirrus PD6710", IS_CIRRUS },
00075     { "Cirrus PD672x", IS_CIRRUS },
00076     { "VIA VT83C469", IS_CIRRUS|IS_VIA },
00077 };
00078 
00079 typedef struct cirrus_state_t {
00080     u_char              misc1, misc2;
00081     u_char              timer[6];
00082 } cirrus_state_t;
00083 
00084 typedef struct vg46x_state_t {
00085     u_char              ctl, ema;
00086 } vg46x_state_t;
00087 
00088 typedef struct socket_info_t {
00089     u_short             type, flags;
00090     socket_cap_t        cap;
00091     ioaddr_t            ioaddr;
00092     u_short             psock;
00093     u_char              cs_irq, intr;
00094     void                (*handler)(void *info, u_int events);
00095     void                *info;
00096     union {
00097         cirrus_state_t          cirrus;
00098         vg46x_state_t           vg46x;
00099     } state;
00100 } socket_info_t;
00101 
00102 //static socket_info_t socket[8];
00103 
00104 int     i365_base = 0x3e0; // Default in Linux kernel
00105 int     cycle_time = 120; // External clock time in ns, 120ns =~ 8.33 MHz
00106 int     mydriverid = 0;
00107 
00108 void    phex ( unsigned char c );
00109 /*static int to_cycles(int ns)
00110 {
00111     return ns/cycle_time;
00112 }
00113 */
00114 /*static int to_ns(int cycles)
00115 {
00116     return cycle_time*cycles;
00117 }
00118 */
00119 
00120 static u_char i365_get(u_short sock, u_short reg)
00121 {
00122     //unsigned long flags;
00123     //spin_lock_irqsave(&bus_lock,flags);
00124     {
00125         ioaddr_t port = pccsock[sock].ioaddr;
00126         u_char val;
00127         reg = I365_REG(pccsock[sock].internalid, reg);
00128         outb(reg, port); val = inb(port+1);
00129         //spin_unlock_irqrestore(&bus_lock,flags);
00130         return val;
00131     }
00132 }
00133 
00134 static void i365_set(u_short sock, u_short reg, u_char data)
00135 {
00136     //unsigned long flags;
00137     //spin_lock_irqsave(&bus_lock,flags);
00138     {
00139         ioaddr_t port = pccsock[sock].ioaddr;
00140         u_char val = I365_REG(pccsock[sock].internalid, reg);
00141         outb(val, port); outb(data, port+1);
00142         //spin_unlock_irqrestore(&bus_lock,flags);
00143     }
00144 }
00145 
00146 void    add_socket_i365(u_short port, int psock, int type) {
00147         pccsock[pccsocks].ioaddr = port;
00148         pccsock[pccsocks].internalid = psock;
00149         pccsock[pccsocks].type = type;
00150         pccsock[pccsocks].flags = pcic[type].flags;
00151         pccsock[pccsocks].drivernum = mydriverid;
00152         pccsock[pccsocks].configoffset = -1;
00153         // Find out if a card in inside that socket
00154         pccsock[pccsocks].status = (( 12 == (i365_get(pccsocks,I365_STATUS)&12) )  ?  HASCARD : EMPTY );
00155         // *TODO* check if that's all
00156         if ( 0 == (psock & 1) ) {
00157                 printf ( "Found a PCMCIA controller (i82365) at io %x, type '%s'\n", port, pcic[type].name );
00158                 //      pccsock[pccsocks].status == HASCARD? "holds card":"empty" );
00159         }
00160         pccsocks++;
00161         return;
00162 }
00163 
00164 void    i365_bset(u_short sock, u_short reg, u_char mask) {
00165         u_char d = i365_get(sock, reg);
00166         d |= mask;
00167         i365_set(sock, reg, d);
00168 }
00169 
00170 void    i365_bclr(u_short sock, u_short reg, u_char mask) {
00171         u_char d = i365_get(sock, reg);
00172         d &= ~mask;
00173         i365_set(sock, reg, d);
00174 }
00175 
00176 
00177 /*static void i365_bflip(u_short sock, u_short reg, u_char mask, int b)
00178 {
00179     u_char d = i365_get(sock, reg);
00180     if (b)
00181         d |= mask;
00182     else
00183         d &= ~mask;
00184     i365_set(sock, reg, d);
00185 }
00186 */
00187 
00188 /*
00189 static u_short i365_get_pair(u_short sock, u_short reg)
00190 {
00191     u_short a, b;
00192     a = i365_get(sock, reg);
00193     b = i365_get(sock, reg+1);
00194     return (a + (b<<8));
00195 }
00196 */
00197 
00198 /*
00199 static void i365_set_pair(u_short sock, u_short reg, u_short data)
00200 {
00201     i365_set(sock, reg, data & 0xff);
00202     i365_set(sock, reg+1, data >> 8);
00203 }
00204 */
00205 int     identify_i365 ( u_short port, u_short sock ) {
00206         u_char val;
00207         int type = -1;
00208         /* Use the next free entry in the socket table */
00209         pccsock[pccsocks].ioaddr = port;
00210         pccsock[pccsocks].internalid = sock;
00211         // *TODO* wakeup a sleepy cirrus controller?
00212 
00213         if ((val = i365_get(pccsocks, I365_IDENT)) & 0x70)
00214             return -1;
00215         switch (val) {
00216         case 0x82:
00217             type = IS_I82365A; break;
00218         case 0x83:
00219             type = IS_I82365B; break;
00220         case 0x84:
00221             type = IS_I82365DF; break;
00222         case 0x88: case 0x89: case 0x8a:
00223             type = IS_IBM; break;
00224         }
00225         /* Check for Vadem VG-468 chips */
00226         outb(0x0e, port);
00227         outb(0x37, port);
00228         i365_bset(pccsocks, VG468_MISC, VG468_MISC_VADEMREV);
00229         val = i365_get(pccsocks, I365_IDENT);
00230         if (val & I365_IDENT_VADEM) {
00231             i365_bclr(pccsocks, VG468_MISC, VG468_MISC_VADEMREV);
00232             type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468;
00233         }
00234 
00235         /* Check for Ricoh chips */
00236         val = i365_get(pccsocks, RF5C_CHIP_ID);
00237         if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396)) type = IS_RF5Cx96;
00238 
00239         /* Check for Cirrus CL-PD67xx chips */
00240         i365_set(pccsocks, PD67_CHIP_INFO, 0);
00241         val = i365_get(pccsocks, PD67_CHIP_INFO);
00242         if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
00243             val = i365_get(pccsocks, PD67_CHIP_INFO);
00244             if ((val & PD67_INFO_CHIP_ID) == 0) {
00245                 type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
00246                 i365_set(pccsocks, PD67_EXT_INDEX, 0xe5);
00247                 if (i365_get(pccsocks, PD67_EXT_INDEX) != 0xe5) type = IS_VT83C469;
00248             }
00249         }
00250     return type;
00251 }
00252 
00253 int     init_i82365(void) {
00254         int     i, j, sock, k, ns, id;
00255         //unsigned int ui,uj;
00256         //unsigned char * upc;
00257         ioaddr_t port;
00258         int     i82365s = 0;
00259         // Change from kernel: No irq init, no check_region, no isapnp support
00260         // No ignore socket, no extra sockets to check (so it's easier here :-/)
00261         // Probably we don't need any of them; in case YOU do, SHOUT AT ME!
00262         id = identify_i365(i365_base, 0);
00263         if ((id == IS_I82365DF) && (identify_i365(i365_base, 1) != id)) {
00264                 for (i = 0; i < 4; i++) {
00265                     port = i365_base + ((i & 1) << 2) + ((i & 2) << 1);
00266                     sock = (i & 1) << 1;
00267                     if (identify_i365(port, sock) == IS_I82365DF) {
00268                         add_socket_i365(port, sock, IS_VLSI);
00269                     }
00270                 }
00271         } else {
00272           for (i = 0; i < 4; i += 2) {
00273             port = i365_base + 2*(i>>2);
00274             sock = (i & 3);
00275             id = identify_i365(port, sock);
00276             if (id < 0) continue;
00277 
00278             for (j = ns = 0; j < 2; j++) {
00279                 /* Does the socket exist? */
00280                 if (identify_i365(port, sock+j) < 0)    continue;
00281                 /* Check for bad socket decode */
00282                 for (k = 0; k <= i82365s; k++)
00283                     i365_set(k, I365_MEM(0)+I365_W_OFF, k);
00284                 for (k = 0; k <= i82365s; k++)
00285                     if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k)
00286                         break;
00287                 if (k <= i82365s) break;
00288                 add_socket_i365(port, sock+j, id); ns++;
00289             }
00290           }
00291         }
00292         return  0;
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 /*      printf ( "Selecting config 1: io 0x300 @byte 87*2.." );
00301         upc[(2*87)] = 2;
00302         i365_bclr(1, I365_ADDRWIN, 1 );
00303         i365_set(1,I365_INTCTL, 0x65 ); //no-reset, memory-card
00304         i365_set(1, I365_IO(0)+0, 0x20 );
00305         i365_set(1, I365_IO(0)+1, 0x03 );
00306         i365_set(1, I365_IO(0)+2, 0x3f );
00307         i365_set(1, I365_IO(0)+3, 0x03 );
00308         i365_set(1, 0x3a, 0x05 );
00309         i365_set(1, 0x3b, 0x05 );
00310         i365_set(1, 0x3c, 0x05 );
00311         i365_set(1, 0x3d, 0x05 );
00312         i365_set(1, 0x3e, 0x05 );
00313         i365_set(1, 0x3f, 0x05 );
00314         i365_set(1, 0x07, 0x0a );
00315         i365_set(1, I365_ADDRWIN, 0x40 ); // 0x40
00316         printf ( "!\n" ); getchar();
00317         printf ( "\n" );
00318         return 0; */
00319 }
00320 
00321 void    phex ( unsigned char c ) {
00322         unsigned char a = 0, b = 0;
00323         b = ( c & 0xf );
00324         if ( b > 9 ) b += ('a'-'9'-1);
00325         b += '0';
00326         a = ( c & 0xf0 ) >> 4;
00327         if ( a > 9 ) a += ('a'-'9'-1);
00328         a += '0';
00329         printf ( "%c%c ", a, b );
00330         return;
00331 }
00332 
00333 int     deinit_i82365(void) {
00334         printf("Deinitializing i82365\n" );
00335         return 0;
00336 }
00337 
00338 /*static int i365_get_status(u_short sock, u_int *value)
00339 {
00340     u_int status;
00341 
00342     status = i365_get(sock, I365_STATUS);
00343     *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
00344         ? SS_DETECT : 0;
00345 
00346     if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
00347         *value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
00348     else {
00349         *value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
00350         *value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
00351     }
00352     *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
00353     *value |= (status & I365_CS_READY) ? SS_READY : 0;
00354     *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
00355 
00356 #ifdef CONFIG_ISA
00357     if (pccsock[sock].type == IS_VG469) {
00358         status = i365_get(sock, VG469_VSENSE);
00359         if (pccsock[sock].internalid & 1) {
00360             *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD;
00361             *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD;
00362         } else {
00363             *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD;
00364             *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
00365         }
00366     }
00367 #endif
00368 
00369     printf("i82365: GetStatus(%d) = %#4.4x\n", sock, *value);
00370     return 0;
00371 } //i365_get_status
00372 */
00373 
00374 /*static int i365_set_socket(u_short sock, socket_state_t *state)
00375 {
00376     socket_info_t *t = &socket[sock];
00377     u_char reg;
00378 
00379     printf("i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
00380           "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
00381           state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
00382 printf ("\nERROR:UNIMPLEMENTED\n" );
00383 return 0;
00384     // First set global controller options 
00385     // set_bridge_state(sock); *TODO* check: need this here?
00386 
00387     // IO card, RESET flag, IO interrupt 
00388     reg = t->intr;
00389     if (state->io_irq != t->cap.pci_irq) reg |= state->io_irq;
00390     reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
00391     reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
00392     i365_set(sock, I365_INTCTL, reg);
00393 
00394     reg = I365_PWR_NORESET;
00395     if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
00396     if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
00397 
00398     if (t->flags & IS_CIRRUS) {
00399         if (state->Vpp != 0) {
00400             if (state->Vpp == 120)
00401                 reg |= I365_VPP1_12V;
00402             else if (state->Vpp == state->Vcc)
00403                 reg |= I365_VPP1_5V;
00404             else return -EINVAL;
00405         }
00406         if (state->Vcc != 0) {
00407             reg |= I365_VCC_5V;
00408             if (state->Vcc == 33)
00409                 i365_bset(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
00410             else if (state->Vcc == 50)
00411                 i365_bclr(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
00412             else return -EINVAL;
00413         }
00414     } else if (t->flags & IS_VG_PWR) {
00415         if (state->Vpp != 0) {
00416             if (state->Vpp == 120)
00417                 reg |= I365_VPP1_12V;
00418             else if (state->Vpp == state->Vcc)
00419                 reg |= I365_VPP1_5V;
00420             else return -EINVAL;
00421         }
00422        if (state->Vcc != 0) {
00423             reg |= I365_VCC_5V;
00424             if (state->Vcc == 33)
00425                 i365_bset(sock, VG469_VSELECT, VG469_VSEL_VCC);
00426             else if (state->Vcc == 50)
00427                 i365_bclr(sock, VG469_VSELECT, VG469_VSEL_VCC);
00428             else return -EINVAL;
00429         }
00430     } else if (t->flags & IS_DF_PWR) {
00431         switch (state->Vcc) {
00432         case 0:         break;
00433         case 33:        reg |= I365_VCC_3V; break;
00434         case 50:        reg |= I365_VCC_5V; break;
00435         default:        return -EINVAL;
00436         }
00437         switch (state->Vpp) {
00438         case 0:         break;
00439         case 50:        reg |= I365_VPP1_5V; break;
00440         case 120:       reg |= I365_VPP1_12V; break;
00441         default:        return -EINVAL;
00442         }
00443     } else {
00444         switch (state->Vcc) {
00445         case 0:         break;
00446         case 50:        reg |= I365_VCC_5V; break;
00447         default:        return -EINVAL;
00448         }
00449         switch (state->Vpp) {
00450         case 0:         break;
00451         case 50:        reg |= I365_VPP1_5V | I365_VPP2_5V; break;
00452         case 120:       reg |= I365_VPP1_12V | I365_VPP2_12V; break;
00453         default:        return -EINVAL;
00454         }
00455     }
00456 
00457     if (reg != i365_get(sock, I365_POWER))
00458         i365_set(sock, I365_POWER, reg);
00459 
00460     // Chipset-specific functions 
00461     if (t->flags & IS_CIRRUS) {
00462         // Speaker control 
00463         i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
00464                    state->flags & SS_SPKR_ENA);
00465     }
00466 
00467     // Card status change interrupt mask 
00468     reg = t->cs_irq << 4;
00469     if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
00470     if (state->flags & SS_IOCARD) {
00471         if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
00472     } else {
00473         if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1;
00474         if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
00475         if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
00476     }
00477     i365_set(sock, I365_CSCINT, reg);
00478     i365_get(sock, I365_CSC);
00479 
00480     return 0;
00481 } // i365_set_socket 
00482 */
00483 
00484 /*static int i365_get_io_map(u_short sock, struct pccard_io_map *io)
00485 {
00486     u_char map, ioctl, addr;
00487         printf ( "GETIOMAP unimplemented\n" ); return 0;
00488     map = io->map;
00489     if (map > 1) return -EINVAL;
00490     io->start = i365_get_pair(sock, I365_IO(map)+I365_W_START);
00491     io->stop = i365_get_pair(sock, I365_IO(map)+I365_W_STOP);
00492     ioctl = i365_get(sock, I365_IOCTL);
00493     addr = i365_get(sock, I365_ADDRWIN);
00494     io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0;
00495     io->flags  = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0;
00496     io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0;
00497     io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0;
00498     io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0;
00499     printf("i82365: GetIOMap(%d, %d) = %#2.2x, %d ns, "
00500           "%#4.4x-%#4.4x\n", sock, map, io->flags, io->speed,
00501           io->start, io->stop);
00502     return 0;
00503 } // i365_get_io_map 
00504 */
00505 
00506 /*====================================================================*/
00507 
00508 /*static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
00509 {
00510     u_char map, ioctl;
00511 
00512     printf("i82365: SetIOMap(%d, %d, %#2.2x, %d ns, "
00513           "%#4.4x-%#4.4x)\n", sock, io->map, io->flags,
00514           io->speed, io->start, io->stop);
00515 printf ( "UNIMPLEMENTED\n" );
00516         return 0;
00517     map = io->map;
00518     //if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
00519     if ((map > 1) ||
00520         (io->stop < io->start)) return -EINVAL;
00521     // Turn off the window before changing anything 
00522     if (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(map))
00523         i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map));
00524     i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start);
00525     i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop);
00526     ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map);
00527     if (io->speed) ioctl |= I365_IOCTL_WAIT(map);
00528     if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
00529     if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
00530     if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
00531     i365_set(sock, I365_IOCTL, ioctl);
00532     // Turn on the window if necessary 
00533     if (io->flags & MAP_ACTIVE)
00534         i365_bset(sock, I365_ADDRWIN, I365_ENA_IO(map));
00535     return 0;
00536 } // i365_set_io_map 
00537 */
00538 
00539 /*
00540 static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
00541 {
00542     u_short base, i;
00543     u_char map;
00544 
00545     printf("i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
00546           "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
00547           mem->sys_start, mem->sys_stop, mem->card_start);
00548 
00549 printf ( "UNIMPLEMENTED\n" );
00550         return 0;
00551     map = mem->map;
00552     if ((map > 4) || (mem->card_start > 0x3ffffff) ||
00553         (mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
00554         return -EINVAL;
00555     if (!(socket[sock].flags & IS_PCI) &&
00556         ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff)))
00557         return -EINVAL;
00558 
00559     // Turn off the window before changing anything 
00560     if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
00561         i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
00562 
00563     base = I365_MEM(map);
00564     i = (mem->sys_start >> 12) & 0x0fff;
00565     if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
00566     if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
00567     i365_set_pair(sock, base+I365_W_START, i);
00568 
00569     i = (mem->sys_stop >> 12) & 0x0fff;
00570     switch (to_cycles(mem->speed)) {
00571     case 0:     break;
00572     case 1:     i |= I365_MEM_WS0; break;
00573     case 2:     i |= I365_MEM_WS1; break;
00574     default:    i |= I365_MEM_WS1 | I365_MEM_WS0; break;
00575     }
00576     i365_set_pair(sock, base+I365_W_STOP, i);
00577 
00578     i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
00579     if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
00580     if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
00581     i365_set_pair(sock, base+I365_W_OFF, i);
00582 
00583     // Turn on the window if necessary 
00584     if (mem->flags & MAP_ACTIVE)
00585         i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
00586     return 0;
00587 } // i365_set_mem_map 
00588 */
00589 
00590 
00591 int     i82365_interfacer ( interface_func_t func, int sockno, int par1, int par2, void* par3 ) {
00592         //int   i, j, k;
00593         //u_int ui;
00594         u_char *upc;
00595         struct pcc_config_t * pccc;
00596         switch ( func ) {
00597           case  INIT:
00598                 mydriverid = par1;
00599                 return  init_i82365();
00600           case  SHUTDOWN:
00601                 i365_set(sockno, I365_ADDRWIN, i365_get(sockno, I365_ADDRWIN) & 0x20 );
00602                 i365_set(sockno, I365_INTCTL, 0x05 );
00603                 sleepticks(2);
00604                 i365_set(sockno,I365_INTCTL, 0x45 ); //no-reset, memory-card
00605                 break;
00606           case  MAPATTRMEM:
00607                 i365_set(sockno,I365_POWER, 0xb1 );
00608                 i365_set(sockno, I365_INTCTL, 0x05 );
00609                 sleepticks(2);
00610                 i365_set(sockno,I365_INTCTL, 0x45 ); //no-reset, memory-card
00611                 i365_set(sockno, I365_ADDRWIN, i365_get(sockno, I365_ADDRWIN) & 0x20 );
00612                 //i365_bclr(sockno, I365_ADDRWIN, 1 );
00613                 i365_set(sockno, I365_MEM(0)+0, ( par1 >> 12 )& 0xff ); //start
00614                 i365_set(sockno, I365_MEM(0)+1, ( par1 >> 20 ) & 0x0f );
00615                 i365_set(sockno, I365_MEM(0)+2, ((par1 + par2 - 1 ) >> 12 ) & 0xff ); //end
00616                 i365_set(sockno, I365_MEM(0)+3, (( par1 + par2 - 1 ) >> 20 ) & 0x0f  );
00617                 i365_set(sockno, I365_MEM(0)+4, ((0x4000000 - par1) >> 12) & 0xff ); //offset low
00618                 i365_set(sockno, I365_MEM(0)+5, 0x40 | (((0x40000000 - par1) >> 12) & 0x3f));
00619                 i365_bset(sockno, I365_ADDRWIN, 1 );
00620                 if ( ! ( 1 & i365_get ( sockno, I365_ADDRWIN ) ) ) return 1;
00621                 break;
00622           case  UNMAPATTRMEM:
00623                 i365_set(sockno, I365_ADDRWIN, i365_get(sockno, I365_ADDRWIN) & 0x20 );
00624                 i365_set(sockno,I365_INTCTL, 0x45 ); //no-reset, memory-card
00625                 break;
00626           case  SELECTCONFIG:   // Params: par1: config number; par3 config pointer pointer
00627                 if ( 0 > pccsock[sockno].configoffset ) return 1;
00628                 if ( NULL == (pccc = par3 ) ) return 2;
00629                 // write config number to 
00630                 upc = ioremap ( MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN );
00631                 if ( pccsock[sockno].configoffset > MAP_ATTRMEM_LEN ) return 3;
00632                 if ( ( par1 & 0x7fffffc0 ) ) return 4;
00633                 if ( pccc->index != par1 ) return 5;
00634                 upc[pccsock[sockno].configoffset] = ( upc[pccsock[sockno].configoffset] & 0xc0 ) | ( par1 & 0x3f );
00635                 i365_set(sockno, I365_IOCTL, (i365_get(sockno, I365_IOCTL) & 0xfe) | 0x20 );    // 16bit autosize
00636                 i365_set(sockno, I365_IO(0)+0, pccc->iowin & 0xff);
00637                 i365_set(sockno, I365_IO(0)+1, (pccc->iowin >> 8) & 0xff);
00638                 i365_set(sockno, I365_IO(0)+2, (pccc->iowin+pccc->iolen - 1) & 0xff);
00639                 i365_set(sockno, I365_IO(0)+3, ((pccc->iowin+pccc->iolen- 1) >> 8) & 0xff);
00640                 // Disable mem mapping
00641                 i365_bclr(sockno, I365_ADDRWIN, 1);
00642                 i365_set(sockno, I365_INTCTL, 0x65);
00643                 i365_bset(sockno, I365_ADDRWIN,0x40);
00644                 break;
00645           default:
00646                 return  -1; // ERROR: Unknown function called
00647         }
00648         return  0;
00649 }
00650 
00651 // get_mem_map[1320]
00652 // cirrus_get_state/set/opts...
00653 // vg46x_get_state/...
00654 // get_bridge_state/...
00655 
00656 #endif /* CONFIG_PCMCIA */