i82092.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:23k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.  * Driver for Intel I82092AA PCI-PCMCIA bridge.
  3.  *
  4.  * (C) 2001 Red Hat, Inc.
  5.  *
  6.  * Author: Arjan Van De Ven <arjanv@redhat.com>
  7.  * Loosly based on i82365.c from the pcmcia-cs package
  8.  *
  9.  * $Id: i82092aa.c,v 1.2 2001/10/23 14:43:34 arjanv Exp $
  10.  */
  11. #include <linux/kernel.h>
  12. #include <linux/config.h>
  13. #include <linux/module.h>
  14. #include <linux/pci.h>
  15. #include <linux/init.h>
  16. #include <pcmcia/cs_types.h>
  17. #include <pcmcia/ss.h>
  18. #include <pcmcia/cs.h>
  19. #include <asm/system.h>
  20. #include <asm/io.h>
  21. #include "i82092aa.h"
  22. #include "i82365.h"
  23. MODULE_LICENSE("GPL");
  24. /* PCI core routines */
  25. static struct pci_device_id i82092aa_pci_ids[] = {
  26. {
  27.       vendor:PCI_VENDOR_ID_INTEL,
  28.       device:PCI_DEVICE_ID_INTEL_82092AA_0,
  29.       subvendor:PCI_ANY_ID,
  30.       subdevice:PCI_ANY_ID,
  31.       class: 0, class_mask:0,
  32.  },
  33.  {} 
  34. };
  35. static struct pci_driver i82092aa_pci_drv = {
  36. name:           "i82092aa",
  37. id_table:       i82092aa_pci_ids,
  38. probe:          i82092aa_pci_probe,
  39. remove:         __devexit_p(i82092aa_pci_remove),
  40. suspend:        NULL,
  41. resume:         NULL 
  42. };
  43. /* the pccard structure and its functions */
  44. static struct pccard_operations i82092aa_operations = {
  45. init:    i82092aa_init,
  46. suspend:     i82092aa_suspend,
  47. register_callback:  i82092aa_register_callback,
  48. inquire_socket: i82092aa_inquire_socket,   
  49. get_status: i82092aa_get_status,
  50. get_socket: i82092aa_get_socket,
  51. set_socket: i82092aa_set_socket,
  52. get_io_map: i82092aa_get_io_map,
  53. set_io_map: i82092aa_set_io_map,
  54. get_mem_map: i82092aa_get_mem_map,
  55. set_mem_map: i82092aa_set_mem_map,
  56. proc_setup: i82092aa_proc_setup,
  57. };
  58. /* The card can do upto 4 sockets, allocate a structure for each of them */
  59. struct socket_info {
  60. int card_state;  /*  0 = no socket,
  61.     1 = empty socket, 
  62.     2 = card but not initialized,
  63.     3 = operational card */
  64. int  io_base;  /* base io address of the socket */
  65. socket_cap_t cap;
  66. unsigned int pending_events; /* Pending events on this interface */
  67. void (*handler)(void *info, u_int events); 
  68. /* callback to the driver of the card */
  69. void *info; /* to be passed to the handler */
  70. struct pci_dev *dev; /* The PCI device for the socket */
  71. };
  72. #define MAX_SOCKETS 4
  73. static struct socket_info sockets[MAX_SOCKETS];
  74. static int socket_count;  /* shortcut */                                                                   
  75. static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
  76. {
  77. unsigned char configbyte;
  78. int i;
  79. enter("i82092aa_pci_probe");
  80. if (pci_enable_device(dev))
  81. return -EIO;
  82. pci_read_config_byte(dev, 0x40, &configbyte);  /* PCI Configuration Control */
  83. switch(configbyte&6) {
  84. case 0:
  85. printk(KERN_INFO "i82092aa: configured as a 2 socket device.n");
  86. socket_count = 2;
  87. break;
  88. case 2:
  89. printk(KERN_INFO "i82092aa: configured as a 1 socket device.n");
  90. socket_count = 1;
  91. break;
  92. case 4:
  93. case 6:
  94. printk(KERN_INFO "i82092aa: configured as a 4 socket device.n");
  95. socket_count = 4;
  96. break;
  97. default:
  98. printk(KERN_ERR "i82092aa: Oops, you did something we didn't think of.n");
  99. return -EIO;
  100. break;
  101. }
  102. for (i = 0;i<socket_count;i++) {
  103. sockets[i].card_state = 1; /* 1 = present but empty */
  104. sockets[i].io_base = (dev->resource[0].start & ~1);
  105.  if (sockets[i].io_base > 0) 
  106.   request_region(sockets[i].io_base, 2, "i82092aa");
  107.  
  108. sockets[i].cap.features |= SS_CAP_PCCARD;
  109. sockets[i].cap.map_size = 0x1000;
  110. sockets[i].cap.irq_mask = 0;
  111. sockets[i].cap.pci_irq  = dev->irq;
  112. if (card_present(i)) {
  113. sockets[i].card_state = 3;
  114. dprintk(KERN_DEBUG "i82092aa: slot %i is occupiedn",i);
  115. } else {
  116. dprintk(KERN_DEBUG "i82092aa: slot %i is vacantn",i);
  117. }
  118. }
  119. /* Now, specifiy that all interrupts are to be done as PCI interrupts */
  120. configbyte = 0xFF; /* bitmask, one bit per event, 1 = PCI interrupt, 0 = ISA interrupt */
  121. pci_write_config_byte(dev, 0x50, configbyte); /* PCI Interrupt Routing Register */
  122. /* Register the interrupt handler */
  123. dprintk(KERN_DEBUG "Requesting interrupt %i n",dev->irq);
  124. if (request_irq(dev->irq, i82092aa_interrupt, SA_SHIRQ, "i82092aa", i82092aa_interrupt)) {
  125. printk(KERN_ERR "i82092aa: Failed to register IRQ %d, abortingn", dev->irq);
  126. return -EIO;
  127. }
  128.  
  129. if (register_ss_entry(socket_count, &i82092aa_operations) != 0)
  130. printk(KERN_NOTICE "i82092aa: register_ss_entry() failedn");
  131. leave("i82092aa_pci_probe");
  132. return 0;
  133. }
  134. static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
  135. {
  136. enter("i82092aa_pci_remove");
  137. free_irq(dev->irq, i82092aa_interrupt);
  138. leave("i82092aa_pci_remove");
  139. }
  140. static spinlock_t port_lock = SPIN_LOCK_UNLOCKED;
  141. /* basic value read/write functions */
  142. static unsigned char indirect_read(int socket, unsigned short reg)
  143. {
  144. unsigned short int port;
  145. unsigned char val;
  146. unsigned long flags;
  147. spin_lock_irqsave(&port_lock,flags);
  148. reg += socket * 0x40;
  149. port = sockets[socket].io_base;
  150. outb(reg,port);
  151. val = inb(port+1);
  152. spin_unlock_irqrestore(&port_lock,flags);
  153. return val;
  154. }
  155. static unsigned short indirect_read16(int socket, unsigned short reg)
  156. {
  157. unsigned short int port;
  158. unsigned short tmp;
  159. unsigned long flags;
  160. spin_lock_irqsave(&port_lock,flags);
  161. reg  = reg + socket * 0x40;
  162. port = sockets[socket].io_base;
  163. outb(reg,port);
  164. tmp = inb(port+1);
  165. reg++;
  166. outb(reg,port);
  167. tmp = tmp | (inb(port+1)<<8);
  168. spin_unlock_irqrestore(&port_lock,flags);
  169. return tmp;
  170. }
  171. static void indirect_write(int socket, unsigned short reg, unsigned char value)
  172. {
  173. unsigned short int port;
  174. unsigned long flags;
  175. spin_lock_irqsave(&port_lock,flags);
  176. reg = reg + socket * 0x40;
  177. port = sockets[socket].io_base; 
  178. outb(reg,port);
  179. outb(value,port+1);
  180. spin_unlock_irqrestore(&port_lock,flags);
  181. }
  182. static void indirect_setbit(int socket, unsigned short reg, unsigned char mask)
  183. {
  184. unsigned short int port;
  185. unsigned char val;
  186. unsigned long flags;
  187. spin_lock_irqsave(&port_lock,flags);
  188. reg = reg + socket * 0x40;
  189. port = sockets[socket].io_base; 
  190. outb(reg,port);
  191. val = inb(port+1);
  192. val |= mask;
  193. outb(reg,port);
  194. outb(val,port+1);
  195. spin_unlock_irqrestore(&port_lock,flags);
  196. }
  197. static void indirect_resetbit(int socket, unsigned short reg, unsigned char mask)
  198. {
  199. unsigned short int port;
  200. unsigned char val;
  201. unsigned long flags;
  202. spin_lock_irqsave(&port_lock,flags);
  203. reg = reg + socket * 0x40;
  204. port = sockets[socket].io_base; 
  205. outb(reg,port);
  206. val = inb(port+1);
  207. val &= ~mask;
  208. outb(reg,port);
  209. outb(val,port+1);
  210. spin_unlock_irqrestore(&port_lock,flags);
  211. }
  212. static void indirect_write16(int socket, unsigned short reg, unsigned short value)
  213. {
  214. unsigned short int port;
  215. unsigned char val;
  216. unsigned long flags;
  217. spin_lock_irqsave(&port_lock,flags);
  218. reg = reg + socket * 0x40;
  219. port = sockets[socket].io_base; 
  220. outb(reg,port);
  221. val = value & 255;
  222. outb(val,port+1);
  223. reg++;
  224. outb(reg,port);
  225. val = value>>8;
  226. outb(val,port+1);
  227. spin_unlock_irqrestore(&port_lock,flags);
  228. }
  229. /* simple helper functions */
  230. /* External clock time, in nanoseconds.  120 ns = 8.33 MHz */
  231. static int cycle_time = 120;
  232. static int to_cycles(int ns)
  233. {
  234. if (cycle_time!=0)
  235. return ns/cycle_time;
  236. else
  237. return 0;
  238. }
  239.     
  240. static int to_ns(int cycles)
  241. {
  242. return cycle_time*cycles;
  243. }
  244. /* Interrupt handler functionality */
  245. static void i82092aa_bh(void *dummy)
  246. {
  247.         unsigned int events;
  248. int i;
  249.                 
  250.         for (i=0; i < socket_count; i++) {
  251.          events = xchg(&(sockets[i].pending_events),0);
  252.          printk("events = %x n",events);
  253.                 if (sockets[i].handler)
  254.                  sockets[i].handler(sockets[i].info, events);
  255. }
  256. }
  257.                                                                                                                                         
  258. static struct tq_struct i82092aa_task = {
  259.         routine:        i82092aa_bh
  260. };
  261.         
  262. static void i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
  263. {
  264. int i;
  265. int loopcount = 0;
  266. unsigned int events, active=0;
  267. /* enter("i82092aa_interrupt");*/
  268. while (1) {
  269. loopcount++;
  270. if (loopcount>20) {
  271. printk(KERN_ERR "i82092aa: infinite eventloop in interrupt n");
  272. break;
  273. }
  274. active = 0;
  275. for (i=0;i<socket_count;i++) {
  276. int csc;
  277. if (sockets[i].card_state==0) /* Inactive socket, should not happen */
  278. continue;
  279. csc = indirect_read(i,I365_CSC); /* card status change register */
  280. if ((csc==0) ||  /* no events on this socket */
  281.    (sockets[i].handler==NULL)) /* no way to handle events */
  282.     continue;
  283. events = 0;
  284.  
  285. if (csc & I365_CSC_DETECT) {
  286. events |= SS_DETECT;
  287. printk("Card detected in socket %i!n",i);
  288.  }
  289. if (indirect_read(i,I365_INTCTL) & I365_PC_IOCARD) { 
  290. /* For IO/CARDS, bit 0 means "read the card" */
  291. events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; 
  292. } else {
  293. /* Check for battery/ready events */
  294. events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
  295. events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
  296. events |= (csc & I365_CSC_READY) ? SS_READY : 0;
  297. }
  298. if (events) {
  299. sockets[i].pending_events |= events;
  300. schedule_task(&i82092aa_task);
  301. }
  302. active |= events;
  303. }
  304. if (active==0) /* no more events to handle */
  305. break;
  306. }
  307. /* leave("i82092aa_interrupt");*/
  308. }
  309. /* socket functions */
  310. static int card_present(int socketno)
  311. {
  312. unsigned int val;
  313. enter("card_present");
  314. if ((socketno<0) || (socketno > MAX_SOCKETS))
  315. return 0;
  316. if (sockets[socketno].io_base == 0)
  317. return 0;
  318. val = indirect_read(socketno, 1); /* Interface status register */
  319. if ((val&12)==12) {
  320. leave("card_present 1");
  321. return 1;
  322. }
  323. leave("card_present 0");
  324. return 0;
  325. }
  326. static void set_bridge_state(int sock)
  327. {
  328. enter("set_bridge_state");
  329. indirect_write(sock, I365_GBLCTL,0x00);
  330. indirect_write(sock, I365_GENCTL,0x00);
  331. indirect_setbit(sock, I365_INTCTL,0x08);
  332. leave("set_bridge_state");
  333. }
  334.       
  335. static int i82092aa_init(unsigned int s)
  336. {
  337. int i;
  338.         pccard_io_map io = { 0, 0, 0, 0, 1 };
  339.         pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
  340.         
  341.         enter("i82092aa_init");
  342.                         
  343.         mem.sys_stop = 0x0fff;
  344.         i82092aa_set_socket(s, &dead_socket);
  345.         for (i = 0; i < 2; i++) {
  346.          io.map = i;
  347.                 i82092aa_set_io_map(s, &io);
  348. }
  349.         for (i = 0; i < 5; i++) {
  350.          mem.map = i;
  351.                 i82092aa_set_mem_map(s, &mem);
  352. }
  353. leave("i82092aa_init");
  354. return 0;
  355. }
  356.                                                                                                                                                                                                                                               
  357. static int i82092aa_suspend(unsigned int sock)
  358. {
  359. int retval;
  360. enter("i82092aa_suspend");
  361.         retval =  i82092aa_set_socket(sock, &dead_socket);
  362.         leave("i82092aa_suspend");
  363.         return retval;
  364. }
  365.        
  366. static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
  367. {
  368. enter("i82092aa_register_callback");
  369. sockets[sock].handler = handler;
  370.         sockets[sock].info = info;
  371.         if (handler == NULL) {   
  372.          MOD_DEC_USE_COUNT;   
  373.   } else {
  374. MOD_INC_USE_COUNT;
  375. }
  376. leave("i82092aa_register_callback");
  377. return 0;
  378. } /* i82092aa_register_callback */
  379.                                         
  380. static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap)
  381. {
  382. enter("i82092aa_inquire_socket");
  383. *cap = sockets[sock].cap;
  384. leave("i82092aa_inquire_socket");
  385. return 0;
  386. } /* i82092aa_inquire_socket */
  387. static int i82092aa_get_status(unsigned int sock, u_int *value)
  388. {
  389. unsigned int status;
  390. enter("i82092aa_get_status");
  391. status = indirect_read(sock,I365_STATUS); /* Interface Status Register */
  392. *value = 0;
  393. if ((status & I365_CS_DETECT) == I365_CS_DETECT) {
  394. *value |= SS_DETECT;
  395. }
  396. /* IO cards have a different meaning of bits 0,1 */
  397. /* Also notice the inverse-logic on the bits */
  398.  if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) {
  399.   /* IO card */
  400.   if (!(status & I365_CS_STSCHG))
  401.   *value |= SS_STSCHG;
  402.  } else { /* non I/O card */
  403.   if (!(status & I365_CS_BVD1))
  404.   *value |= SS_BATDEAD;
  405.   if (!(status & I365_CS_BVD2))
  406.   *value |= SS_BATWARN;
  407.  
  408.  }
  409.  
  410.  if (status & I365_CS_WRPROT)
  411.   (*value) |= SS_WRPROT; /* card is write protected */
  412.  
  413.  if (status & I365_CS_READY)
  414.   (*value) |= SS_READY;    /* card is not busy */
  415.  
  416.  if (status & I365_CS_POWERON)
  417.   (*value) |= SS_POWERON;  /* power is applied to the card */
  418. leave("i82092aa_get_status");
  419. return 0;
  420. }
  421. static int i82092aa_get_socket(unsigned int sock, socket_state_t *state) 
  422. {
  423. unsigned char reg,vcc,vpp;
  424. enter("i82092aa_get_socket");
  425. state->flags    = 0;
  426. state->Vcc      = 0;
  427. state->Vpp      = 0;
  428. state->io_irq   = 0;
  429. state->csc_mask = 0;
  430. /* First the power status of the socket */
  431. reg = indirect_read(sock,I365_POWER); /* PCTRL - Power Control Register */
  432. if (reg & I365_PWR_AUTO)
  433. state->flags |= SS_PWR_AUTO;  /* Automatic Power Switch */
  434. if (reg & I365_PWR_OUT)
  435. state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
  436. vcc = reg & I365_VCC_MASK;    vpp = reg & I365_VPP1_MASK;
  437. if (reg & I365_VCC_5V) { /* Can still be 3.3V, in this case the Vcc value will be overwritten later */
  438. state->Vcc = 50;
  439. if (vpp == I365_VPP1_5V)
  440. state->Vpp = 50;
  441. if (vpp == I365_VPP1_12V)
  442. state->Vpp = 120;
  443. }
  444. if ((reg & I365_VCC_3V)==I365_VCC_3V)
  445. state->Vcc = 33;
  446. /* Now the IO card, RESET flags and IO interrupt */
  447. reg = indirect_read(sock, I365_INTCTL); /* IGENC, Interrupt and General Control */
  448. if ((reg & I365_PC_RESET)==0)
  449. state->flags |= SS_RESET;
  450. if (reg & I365_PC_IOCARD) 
  451. state->flags |= SS_IOCARD; /* This is an IO card */
  452. /* Set the IRQ number */
  453. if (sockets[sock].dev!=NULL)
  454. state->io_irq = sockets[sock].dev->irq;
  455. /* Card status change */
  456. reg = indirect_read(sock, I365_CSCINT); /* CSCICR, Card Status Change Interrupt Configuration */
  457. if (reg & I365_CSC_DETECT) 
  458. state->csc_mask |= SS_DETECT; /* Card detect is enabled */
  459. if (state->flags & SS_IOCARD) {/* IO Cards behave different */
  460. if (reg & I365_CSC_STSCHG)
  461. state->csc_mask |= SS_STSCHG;
  462. } else {
  463. if (reg & I365_CSC_BVD1) 
  464. state->csc_mask |= SS_BATDEAD;
  465. if (reg & I365_CSC_BVD2) 
  466. state->csc_mask |= SS_BATWARN;
  467. if (reg & I365_CSC_READY) 
  468. state->csc_mask |= SS_READY;
  469. }
  470. leave("i82092aa_get_socket");
  471. return 0;
  472. }
  473. static int i82092aa_set_socket(unsigned int sock, socket_state_t *state) 
  474. {
  475. unsigned char reg;
  476. enter("i82092aa_set_socket");
  477. /* First, set the global controller options */
  478. set_bridge_state(sock);
  479. /* Values for the IGENC register */
  480. reg = 0;
  481. if (!(state->flags & SS_RESET))  /* The reset bit has "inverse" logic */
  482. reg = reg | I365_PC_RESET;  
  483. if (state->flags & SS_IOCARD) 
  484. reg = reg | I365_PC_IOCARD;
  485. indirect_write(sock,I365_INTCTL,reg); /* IGENC, Interrupt and General Control Register */
  486. /* Power registers */
  487. reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */
  488. if (state->flags & SS_PWR_AUTO) {
  489. printk("Auto powern");
  490. reg |= I365_PWR_AUTO; /* automatic power mngmnt */
  491. }
  492. if (state->flags & SS_OUTPUT_ENA) {
  493. printk("Power Enabled n");
  494. reg |= I365_PWR_OUT; /* enable power */
  495. }
  496. switch (state->Vcc) {
  497. case 0:
  498. break;
  499. case 50: 
  500. printk("setting voltage to Vcc to 5V on socket %in",sock);
  501. reg |= I365_VCC_5V;
  502. break;
  503. default:
  504. printk("i82092aa: i82092aa_set_socket called with invalid VCC power value: %i ", state->Vcc);
  505. leave("i82092aa_set_socket");
  506. return -EINVAL;
  507. }
  508. switch (state->Vpp) {
  509. case 0:
  510. printk("not setting Vpp on socket %in",sock);
  511. break;
  512. case 50: 
  513. printk("setting Vpp to 5.0 for socket %in",sock);
  514. reg |= I365_VPP1_5V | I365_VPP2_5V;
  515. break;
  516. case 120: 
  517. printk("setting Vpp to 12.0n");
  518. reg |= I365_VPP1_12V | I365_VPP2_12V;
  519. break;
  520. default:
  521. printk("i82092aa: i82092aa_set_socket called with invalid VPP power value: %i ", state->Vcc);
  522. leave("i82092aa_set_socket");
  523. return -EINVAL;
  524. }
  525. if (reg != indirect_read(sock,I365_POWER)) /* only write if changed */
  526. indirect_write(sock,I365_POWER,reg);
  527. /* Enable specific interrupt events */
  528. reg = 0x00;
  529. if (state->csc_mask & SS_DETECT) {
  530. reg |= I365_CSC_DETECT;
  531. }
  532. if (state->flags & SS_IOCARD) {
  533. if (state->csc_mask & SS_STSCHG)
  534. reg |= I365_CSC_STSCHG;
  535. } else {
  536. if (state->csc_mask & SS_BATDEAD) 
  537. reg |= I365_CSC_BVD1;
  538. if (state->csc_mask & SS_BATWARN) 
  539. reg |= I365_CSC_BVD2;
  540. if (state->csc_mask & SS_READY) 
  541. reg |= I365_CSC_READY; 
  542.                         
  543. }
  544. /* now write the value and clear the (probably bogus) pending stuff by doing a dummy read*/
  545. indirect_write(sock,I365_CSCINT,reg);
  546. (void)indirect_read(sock,I365_CSC);
  547. leave("i82092aa_set_socket");
  548. return 0;
  549. }
  550. static int i82092aa_get_io_map(unsigned int sock, struct pccard_io_map *io)
  551. {
  552. unsigned char map, ioctl, addr;
  553. enter("i82092aa_get_io_map");
  554. map = io->map;
  555. if (map > 1) {
  556. leave("i82092aa_get_io_map with -EINVAL");
  557. return -EINVAL;
  558. }
  559. /* FIXME: How does this fit in with the PCI resource (re)allocation */
  560. io->start = indirect_read16(sock, I365_IO(map)+I365_W_START);
  561. io->stop  = indirect_read16(sock, I365_IO(map)+I365_W_START);
  562. ioctl = indirect_read(sock,I365_IOCTL); /* IOCREG: I/O Control Register */
  563. addr  = indirect_read(sock,I365_ADDRWIN); /* */
  564. io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; /* check this out later */
  565. io->flags = 0;
  566. if (addr & I365_IOCTL_16BIT(map))
  567. io->flags |= MAP_AUTOSZ;
  568. leave("i82092aa_get_io_map");
  569. return 0;
  570. }
  571. static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io)
  572. {
  573. unsigned char map, ioctl;
  574. enter("i82092aa_set_io_map");
  575. map = io->map;
  576. /* Check error conditions */
  577. if (map > 1) {
  578. leave("i82092aa_set_io_map with invalid map");
  579. return -EINVAL;
  580. }
  581. if ((io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)){
  582. leave("i82092aa_set_io_map with invalid io");
  583. return -EINVAL;
  584. }
  585. /* Turn off the window before changing anything */ 
  586. if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map))
  587. indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map));
  588. /* printk("set_io_map: Setting range to %x - %x n",io->start,io->stop);  */
  589. /* write the new values */
  590. indirect_write16(sock,I365_IO(map)+I365_W_START,io->start);            
  591. indirect_write16(sock,I365_IO(map)+I365_W_STOP,io->stop);            
  592.             
  593. ioctl = indirect_read(sock,I365_IOCTL) & ~I365_IOCTL_MASK(map);
  594. if (io->flags & (MAP_16BIT|MAP_AUTOSZ))
  595. ioctl |= I365_IOCTL_16BIT(map);
  596. indirect_write(sock,I365_IOCTL,ioctl);
  597. /* Turn the window back on if needed */
  598. if (io->flags & MAP_ACTIVE)
  599. indirect_setbit(sock,I365_ADDRWIN,I365_ENA_IO(map));
  600. leave("i82092aa_set_io_map");
  601. return 0;
  602. }
  603. static int i82092aa_get_mem_map(unsigned sock, struct pccard_mem_map *mem)
  604. {
  605. unsigned short base, i;
  606. unsigned char map, addr;
  607. enter("i82092aa_get_mem_map");
  608. mem->flags = 0;
  609. mem->speed = 0;
  610. map = mem->map;
  611. if (map > 4) {
  612. leave("i82092aa_get_mem_map: -EINVAL");
  613. return -EINVAL;
  614. }
  615. addr = indirect_read(sock, I365_ADDRWIN);
  616. if (addr & I365_ENA_MEM(map))
  617. mem->flags |= MAP_ACTIVE; /* yes this mapping is active */
  618. base = I365_MEM(map); 
  619. /* Find the start address - this register also has mapping info */
  620. i = indirect_read16(sock,base+I365_W_START);
  621. if (i & I365_MEM_16BIT)
  622. mem->flags |= MAP_16BIT;
  623. if (i & I365_MEM_0WS)
  624. mem->flags |= MAP_0WS;
  625. mem->sys_start = ((unsigned long)(i & 0x0fff) << 12);
  626. /* Find the end address - this register also has speed info */
  627. i = indirect_read16(sock,base+I365_W_STOP);
  628. if (i & I365_MEM_WS0)
  629. mem->speed = 1;
  630. if (i & I365_MEM_WS1)
  631. mem->speed += 2;
  632. mem->speed = to_ns(mem->speed);
  633. mem->sys_stop = ( (unsigned long)(i & 0x0fff) << 12) + 0x0fff;
  634. /* Find the card start address, also some more MAP attributes */
  635. i = indirect_read16(sock, base+I365_W_OFF);
  636. if (i & I365_MEM_WRPROT)
  637. mem->flags |= MAP_WRPROT;
  638. if (i & I365_MEM_REG)
  639. mem->flags |= MAP_ATTRIB;
  640. mem->card_start = ( (unsigned long)(i & 0x3fff)<12) + mem->sys_start;
  641. mem->card_start &=  0x3ffffff;
  642. printk("Card %i is from %lx to %lx n",sock,mem->sys_start,mem->sys_stop);
  643. leave("i82092aa_get_mem_map");
  644. return 0;
  645. }
  646. static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem)
  647. {
  648. unsigned short base, i;
  649. unsigned char map;
  650. enter("i82092aa_set_mem_map");
  651. map = mem->map;
  652. if (map > 4) {
  653. leave("i82092aa_set_mem_map: invalid map");
  654. return -EINVAL;
  655. }
  656. if ( (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) ||
  657.      (mem->speed > 1000) ) {
  658. leave("i82092aa_set_mem_map: invalid address / speed");
  659. printk("invalid mem map for socket %i : %lx to %lx with a start of %x n",sock,mem->sys_start, mem->sys_stop, mem->card_start);
  660. return -EINVAL;
  661. }
  662. /* Turn off the window before changing anything */
  663. if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
  664.               indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
  665.                  
  666.                  
  667. /*  printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i n",map, mem->sys_start,mem->sys_stop,sock,mem->speed,mem->flags & MAP_ACTIVE);  */
  668. /* write the start address */
  669. base = I365_MEM(map);
  670. i = (mem->sys_start >> 12) & 0x0fff;
  671. if (mem->flags & MAP_16BIT) 
  672. i |= I365_MEM_16BIT;
  673. if (mem->flags & MAP_0WS)
  674. i |= I365_MEM_0WS;
  675. indirect_write16(sock,base+I365_W_START,i);
  676.                
  677. /* write the stop address */
  678. i= (mem->sys_stop >> 12) & 0x0fff;
  679. switch (to_cycles(mem->speed)) {
  680. case 0:
  681. break;
  682. case 1:
  683. i |= I365_MEM_WS0;
  684. break;
  685. case 2:
  686. i |= I365_MEM_WS1;
  687. break;
  688. default:
  689. i |= I365_MEM_WS1 | I365_MEM_WS0;
  690. break;
  691. }
  692. indirect_write16(sock,base+I365_W_STOP,i);
  693. /* card start */
  694. i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
  695. if (mem->flags & MAP_WRPROT)
  696. i |= I365_MEM_WRPROT;
  697. if (mem->flags & MAP_ATTRIB) {
  698. /* printk("requesting attribute memory for socket %in",sock);*/
  699. i |= I365_MEM_REG;
  700. } else {
  701. /* printk("requesting normal memory for socket %in",sock);*/
  702. }
  703. indirect_write16(sock,base+I365_W_OFF,i);
  704. /* Enable the window if necessary */
  705. if (mem->flags & MAP_ACTIVE)
  706. indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
  707.             
  708. leave("i82092aa_set_mem_map");
  709. return 0;
  710. }
  711. static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base)
  712. {
  713. }
  714. /* Module stuff */
  715. static int i82092aa_module_init(void)
  716. {
  717. enter("i82092aa_module_init");
  718. pci_register_driver(&i82092aa_pci_drv);
  719. leave("i82092aa_module_init");
  720. return 0;
  721. }
  722. static void i82092aa_module_exit(void)
  723. {
  724. enter("i82092aa_module_exit");
  725. pci_unregister_driver(&i82092aa_pci_drv);
  726. unregister_ss_entry(&i82092aa_operations);
  727. if (sockets[0].io_base>0)
  728.  release_region(sockets[0].io_base, 2);
  729. leave("i82092aa_module_exit");
  730. }
  731. module_init(i82092aa_module_init);
  732. module_exit(i82092aa_module_exit);