📄 i82365.c
字号:
/* * i82365.c * Support for i82365 and similar ISA-to-PCMCIA bridges * * Taken from Linux kernel sources, distributed under GPL2 * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The initial developer of the original code is David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Ported by: Anselm Martin Hoffmeister, Stockholm Projekt Computer-Service, Sankt Augustin/Bonn, GERMANY *//* * * * ****************************** * PLEASE DO NOT YET WORK ON THIS * ****************************** * * I'm still fixing it up on every end, so we most probably would interfere * at some point. If there's anything obvious or better, not-so-obvious, * please contact me by e-mail: anselm (AT) hoffmeister (DOT) be *THANKS* */#include "../include/pcmcia.h"#include "../include/pcmcia-opts.h"#include "../include/i82365.h"#ifndef CONFIG_ISA#error PCMCIA_I82365 only works with ISA defined - set CONFIG_ISA#endiftypedef enum pcic_id { IS_I82365A, IS_I82365B, IS_I82365DF, IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469, IS_PD6710, IS_PD672X, IS_VT83C469,} pcic_id;/* Flags for classifying groups of controllers */#define IS_VADEM 0x0001#define IS_CIRRUS 0x0002#define IS_TI 0x0004#define IS_O2MICRO 0x0008#define IS_VIA 0x0010#define IS_TOPIC 0x0020#define IS_RICOH 0x0040#define IS_UNKNOWN 0x0400#define IS_VG_PWR 0x0800#define IS_DF_PWR 0x1000#define IS_PCI 0x2000#define IS_ALIVE 0x8000typedef struct pcic_t { char *name; u_short flags;} pcic_t;static pcic_t pcic[] = { { "Intel i82365sl A step", 0 }, { "Intel i82365sl B step", 0 }, { "Intel i82365sl DF", IS_DF_PWR }, { "IBM Clone", 0 }, { "Ricoh RF5C296/396", 0 }, { "VLSI 82C146", 0 }, { "Vadem VG-468", IS_VADEM }, { "Vadem VG-469", IS_VADEM|IS_VG_PWR }, { "Cirrus PD6710", IS_CIRRUS }, { "Cirrus PD672x", IS_CIRRUS }, { "VIA VT83C469", IS_CIRRUS|IS_VIA },};typedef struct cirrus_state_t { u_char misc1, misc2; u_char timer[6];} cirrus_state_t;typedef struct vg46x_state_t { u_char ctl, ema;} vg46x_state_t;typedef struct socket_info_t { u_short type, flags; socket_cap_t cap; ioaddr_t ioaddr; u_short psock; u_char cs_irq, intr; void (*handler)(void *info, u_int events); void *info; union { cirrus_state_t cirrus; vg46x_state_t vg46x; } state;} socket_info_t;//static socket_info_t socket[8];int i365_base = 0x3e0; // Default in Linux kernelint cycle_time = 120; // External clock time in ns, 120ns =~ 8.33 MHzint mydriverid = 0;void phex ( unsigned char c );/*static int to_cycles(int ns){ return ns/cycle_time;}*//*static int to_ns(int cycles){ return cycle_time*cycles;}*/static u_char i365_get(u_short sock, u_short reg){ //unsigned long flags; //spin_lock_irqsave(&bus_lock,flags); { ioaddr_t port = pccsock[sock].ioaddr; u_char val; reg = I365_REG(pccsock[sock].internalid, reg); outb(reg, port); val = inb(port+1); //spin_unlock_irqrestore(&bus_lock,flags); return val; }}static void i365_set(u_short sock, u_short reg, u_char data){ //unsigned long flags; //spin_lock_irqsave(&bus_lock,flags); { ioaddr_t port = pccsock[sock].ioaddr; u_char val = I365_REG(pccsock[sock].internalid, reg); outb(val, port); outb(data, port+1); //spin_unlock_irqrestore(&bus_lock,flags); }}void add_socket_i365(u_short port, int psock, int type) { pccsock[pccsocks].ioaddr = port; pccsock[pccsocks].internalid = psock; pccsock[pccsocks].type = type; pccsock[pccsocks].flags = pcic[type].flags; pccsock[pccsocks].drivernum = mydriverid; pccsock[pccsocks].configoffset = -1; // Find out if a card in inside that socket pccsock[pccsocks].status = (( 12 == (i365_get(pccsocks,I365_STATUS)&12) ) ? HASCARD : EMPTY ); // *TODO* check if that's all if ( 0 == (psock & 1) ) { printf ( "Found a PCMCIA controller (i82365) at io %x, type '%s'\n", port, pcic[type].name ); // pccsock[pccsocks].status == HASCARD? "holds card":"empty" ); } pccsocks++; return;}void i365_bset(u_short sock, u_short reg, u_char mask) { u_char d = i365_get(sock, reg); d |= mask; i365_set(sock, reg, d);}void i365_bclr(u_short sock, u_short reg, u_char mask) { u_char d = i365_get(sock, reg); d &= ~mask; i365_set(sock, reg, d);}/*static void i365_bflip(u_short sock, u_short reg, u_char mask, int b){ u_char d = i365_get(sock, reg); if (b) d |= mask; else d &= ~mask; i365_set(sock, reg, d);}*//*static u_short i365_get_pair(u_short sock, u_short reg){ u_short a, b; a = i365_get(sock, reg); b = i365_get(sock, reg+1); return (a + (b<<8));}*//*static void i365_set_pair(u_short sock, u_short reg, u_short data){ i365_set(sock, reg, data & 0xff); i365_set(sock, reg+1, data >> 8);}*/int identify_i365 ( u_short port, u_short sock ) { u_char val; int type = -1; /* Use the next free entry in the socket table */ pccsock[pccsocks].ioaddr = port; pccsock[pccsocks].internalid = sock; // *TODO* wakeup a sleepy cirrus controller? if ((val = i365_get(pccsocks, I365_IDENT)) & 0x70) return -1; switch (val) { case 0x82: type = IS_I82365A; break; case 0x83: type = IS_I82365B; break; case 0x84: type = IS_I82365DF; break; case 0x88: case 0x89: case 0x8a: type = IS_IBM; break; } /* Check for Vadem VG-468 chips */ outb(0x0e, port); outb(0x37, port); i365_bset(pccsocks, VG468_MISC, VG468_MISC_VADEMREV); val = i365_get(pccsocks, I365_IDENT); if (val & I365_IDENT_VADEM) { i365_bclr(pccsocks, VG468_MISC, VG468_MISC_VADEMREV); type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468; } /* Check for Ricoh chips */ val = i365_get(pccsocks, RF5C_CHIP_ID); if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396)) type = IS_RF5Cx96; /* Check for Cirrus CL-PD67xx chips */ i365_set(pccsocks, PD67_CHIP_INFO, 0); val = i365_get(pccsocks, PD67_CHIP_INFO); if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) { val = i365_get(pccsocks, PD67_CHIP_INFO); if ((val & PD67_INFO_CHIP_ID) == 0) { type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710; i365_set(pccsocks, PD67_EXT_INDEX, 0xe5); if (i365_get(pccsocks, PD67_EXT_INDEX) != 0xe5) type = IS_VT83C469; } } return type;}int init_i82365(void) { int i, j, sock, k, ns, id; //unsigned int ui,uj; //unsigned char * upc; ioaddr_t port; int i82365s = 0; // Change from kernel: No irq init, no check_region, no isapnp support // No ignore socket, no extra sockets to check (so it's easier here :-/) // Probably we don't need any of them; in case YOU do, SHOUT AT ME! id = identify_i365(i365_base, 0); if ((id == IS_I82365DF) && (identify_i365(i365_base, 1) != id)) { for (i = 0; i < 4; i++) { port = i365_base + ((i & 1) << 2) + ((i & 2) << 1); sock = (i & 1) << 1; if (identify_i365(port, sock) == IS_I82365DF) { add_socket_i365(port, sock, IS_VLSI); } } } else { for (i = 0; i < 4; i += 2) { port = i365_base + 2*(i>>2); sock = (i & 3); id = identify_i365(port, sock); if (id < 0) continue; for (j = ns = 0; j < 2; j++) { /* Does the socket exist? */ if (identify_i365(port, sock+j) < 0) continue; /* Check for bad socket decode */ for (k = 0; k <= i82365s; k++) i365_set(k, I365_MEM(0)+I365_W_OFF, k); for (k = 0; k <= i82365s; k++) if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k) break; if (k <= i82365s) break; add_socket_i365(port, sock+j, id); ns++; } } } return 0;/* printf ( "Selecting config 1: io 0x300 @byte 87*2.." ); upc[(2*87)] = 2; i365_bclr(1, I365_ADDRWIN, 1 ); i365_set(1,I365_INTCTL, 0x65 ); //no-reset, memory-card i365_set(1, I365_IO(0)+0, 0x20 ); i365_set(1, I365_IO(0)+1, 0x03 ); i365_set(1, I365_IO(0)+2, 0x3f ); i365_set(1, I365_IO(0)+3, 0x03 ); i365_set(1, 0x3a, 0x05 ); i365_set(1, 0x3b, 0x05 ); i365_set(1, 0x3c, 0x05 ); i365_set(1, 0x3d, 0x05 ); i365_set(1, 0x3e, 0x05 ); i365_set(1, 0x3f, 0x05 ); i365_set(1, 0x07, 0x0a ); i365_set(1, I365_ADDRWIN, 0x40 ); // 0x40 printf ( "!\n" ); getchar(); printf ( "\n" ); return 0; */}void phex ( unsigned char c ) { unsigned char a = 0, b = 0; b = ( c & 0xf ); if ( b > 9 ) b += ('a'-'9'-1); b += '0'; a = ( c & 0xf0 ) >> 4; if ( a > 9 ) a += ('a'-'9'-1); a += '0'; printf ( "%c%c ", a, b );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -