You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

i82365.c 20KB

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