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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: isurf.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
  2.  *
  3.  * low level stuff for Siemens I-Surf/I-Talk cards
  4.  *
  5.  * Author       Karsten Keil
  6.  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
  7.  * 
  8.  * This software may be used and distributed according to the terms
  9.  * of the GNU General Public License, incorporated herein by reference.
  10.  *
  11.  */
  12. #define __NO_VERSION__
  13. #include <linux/init.h>
  14. #include "hisax.h"
  15. #include "isac.h"
  16. #include "isar.h"
  17. #include "isdnl1.h"
  18. #include <linux/isapnp.h>
  19. extern const char *CardType[];
  20. static const char *ISurf_revision = "$Revision: 1.1.4.1 $";
  21. #define byteout(addr,val) outb(val,addr)
  22. #define bytein(addr) inb(addr)
  23. #define ISURF_ISAR_RESET 1
  24. #define ISURF_ISAC_RESET 2
  25. #define ISURF_ISAR_EA 4
  26. #define ISURF_ARCOFI_RESET 8
  27. #define ISURF_RESET (ISURF_ISAR_RESET | ISURF_ISAC_RESET | ISURF_ARCOFI_RESET)
  28. #define ISURF_ISAR_OFFSET 0
  29. #define ISURF_ISAC_OFFSET 0x100
  30. #define ISURF_IOMEM_SIZE 0x400
  31. /* Interface functions */
  32. static u_char
  33. ReadISAC(struct IsdnCardState *cs, u_char offset)
  34. {
  35. return (readb(cs->hw.isurf.isac + offset));
  36. }
  37. static void
  38. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  39. {
  40. writeb(value, cs->hw.isurf.isac + offset); mb();
  41. }
  42. static void
  43. ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  44. {
  45. register int i;
  46. for (i = 0; i < size; i++)
  47. data[i] = readb(cs->hw.isurf.isac);
  48. }
  49. static void
  50. WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  51. {
  52. register int i;
  53. for (i = 0; i < size; i++){
  54. writeb(data[i], cs->hw.isurf.isac);mb();
  55. }
  56. }
  57. /* ISAR access routines
  58.  * mode = 0 access with IRQ on
  59.  * mode = 1 access with IRQ off
  60.  * mode = 2 access with IRQ off and using last offset
  61.  */
  62.   
  63. static u_char
  64. ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
  65. {
  66. return(readb(cs->hw.isurf.isar + offset));
  67. }
  68. static void
  69. WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
  70. {
  71. writeb(value, cs->hw.isurf.isar + offset);mb();
  72. }
  73. static void
  74. isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs)
  75. {
  76. struct IsdnCardState *cs = dev_id;
  77. u_char val;
  78. int cnt = 5;
  79. if (!cs) {
  80. printk(KERN_WARNING "ISurf: Spurious interrupt!n");
  81. return;
  82. }
  83. val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
  84.       Start_ISAR:
  85. if (val & ISAR_IRQSTA)
  86. isar_int_main(cs);
  87. val = readb(cs->hw.isurf.isac + ISAC_ISTA);
  88.       Start_ISAC:
  89. if (val)
  90. isac_interrupt(cs, val);
  91. val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
  92. if ((val & ISAR_IRQSTA) && --cnt) {
  93. if (cs->debug & L1_DEB_HSCX)
  94. debugl1(cs, "ISAR IntStat after IntRoutine");
  95. goto Start_ISAR;
  96. }
  97. val = readb(cs->hw.isurf.isac + ISAC_ISTA);
  98. if (val && --cnt) {
  99. if (cs->debug & L1_DEB_ISAC)
  100. debugl1(cs, "ISAC IntStat after IntRoutine");
  101. goto Start_ISAC;
  102. }
  103. if (!cnt)
  104. printk(KERN_WARNING "ISurf IRQ LOOPn");
  105. writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
  106. writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb();
  107. writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb();
  108. writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
  109. }
  110. void
  111. release_io_isurf(struct IsdnCardState *cs)
  112. {
  113. release_region(cs->hw.isurf.reset, 1);
  114. iounmap((unsigned char *)cs->hw.isurf.isar);
  115. release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
  116. }
  117. static void
  118. reset_isurf(struct IsdnCardState *cs, u_char chips)
  119. {
  120. long flags;
  121. printk(KERN_INFO "ISurf: resetting cardn");
  122. byteout(cs->hw.isurf.reset, chips); /* Reset On */
  123. save_flags(flags);
  124. sti();
  125. set_current_state(TASK_UNINTERRUPTIBLE);
  126. schedule_timeout((10*HZ)/1000);
  127. byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */
  128. set_current_state(TASK_UNINTERRUPTIBLE);
  129. schedule_timeout((10*HZ)/1000);
  130. restore_flags(flags);
  131. }
  132. static int
  133. ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  134. {
  135. switch (mt) {
  136. case CARD_RESET:
  137. reset_isurf(cs, ISURF_RESET);
  138. return(0);
  139. case CARD_RELEASE:
  140. release_io_isurf(cs);
  141. return(0);
  142. case CARD_INIT:
  143. clear_pending_isac_ints(cs);
  144. writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb();
  145. initisac(cs);
  146. initisar(cs);
  147. /* Reenable ISAC IRQ */
  148. cs->writeisac(cs, ISAC_MASK, 0);
  149. /* RESET Receiver and Transmitter */
  150. cs->writeisac(cs, ISAC_CMDR, 0x41);
  151. return(0);
  152. case CARD_TEST:
  153. return(0);
  154. }
  155. return(0);
  156. }
  157. static int
  158. isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
  159. int ret;
  160. if ((ic->command == ISDN_CMD_IOCTL) && (ic->arg == 9)) {
  161. ret = isar_auxcmd(cs, ic);
  162. if (!ret) {
  163. reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET |
  164. ISURF_ARCOFI_RESET);
  165. initisac(cs);
  166. cs->writeisac(cs, ISAC_MASK, 0);
  167. cs->writeisac(cs, ISAC_CMDR, 0x41);
  168. }
  169. return(ret);
  170. }
  171. return(isar_auxcmd(cs, ic));
  172. }
  173. #ifdef __ISAPNP__
  174. static struct pci_bus *pnp_surf __devinitdata = NULL;
  175. #endif
  176. int __init
  177. setup_isurf(struct IsdnCard *card)
  178. {
  179. int ver;
  180. struct IsdnCardState *cs = card->cs;
  181. char tmp[64];
  182. strcpy(tmp, ISurf_revision);
  183. printk(KERN_INFO "HiSax: ISurf driver Rev. %sn", HiSax_getrev(tmp));
  184.   if (cs->typ != ISDN_CTYPE_ISURF)
  185.   return(0);
  186. if (card->para[1] && card->para[2]) {
  187. cs->hw.isurf.reset = card->para[1];
  188. cs->hw.isurf.phymem = card->para[2];
  189. cs->irq = card->para[0];
  190. } else {
  191. #ifdef __ISAPNP__
  192. struct pci_bus *pb;
  193. struct pci_dev *pd;
  194. if (isapnp_present()) {
  195. cs->subtyp = 0;
  196. if ((pb = isapnp_find_card(
  197. ISAPNP_VENDOR('S', 'I', 'E'),
  198. ISAPNP_FUNCTION(0x0010), pnp_surf))) {
  199. pnp_surf = pb;
  200. pd = NULL;
  201. if (!(pd = isapnp_find_dev(pnp_surf,
  202. ISAPNP_VENDOR('S', 'I', 'E'),
  203. ISAPNP_FUNCTION(0x0010), pd))) {
  204. printk(KERN_ERR "ISurfPnP: PnP error card found, no devicen");
  205. return (0);
  206. }
  207. pd->prepare(pd);
  208. pd->deactivate(pd);
  209. pd->activate(pd);
  210. cs->hw.isurf.reset = pd->resource[0].start;
  211. cs->hw.isurf.phymem = pd->resource[1].start;
  212. cs->irq = pd->irq_resource[0].start;
  213. if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
  214. printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lxn",
  215. cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem);
  216. pd->deactivate(pd);
  217. return(0);
  218. }
  219. } else {
  220. printk(KERN_INFO "ISurfPnP: no ISAPnP card foundn");
  221. return(0);
  222. }
  223. } else {
  224. printk(KERN_INFO "ISurfPnP: no ISAPnP bus foundn");
  225. return(0);
  226. }
  227. #else
  228. printk(KERN_WARNING "HiSax: %s port/mem not setn",
  229. CardType[card->typ]);
  230. return (0);
  231. #endif
  232. }
  233. if (check_region(cs->hw.isurf.reset, 1)) {
  234. printk(KERN_WARNING
  235. "HiSax: %s config port %x already in usen",
  236. CardType[card->typ],
  237. cs->hw.isurf.reset);
  238. return (0);
  239. } else {
  240. request_region(cs->hw.isurf.reset, 1, "isurf isdn");
  241. }
  242. if (check_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE)) {
  243. printk(KERN_WARNING
  244. "HiSax: %s memory region %lx-%lx already in usen",
  245. CardType[card->typ],
  246. cs->hw.isurf.phymem,
  247. cs->hw.isurf.phymem + ISURF_IOMEM_SIZE);
  248. release_region(cs->hw.isurf.reset, 1);
  249. return (0);
  250. } else {
  251. request_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE,
  252. "isurf iomem");
  253. }
  254. cs->hw.isurf.isar =
  255. (unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
  256. cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
  257. printk(KERN_INFO
  258.        "ISurf: defined at 0x%x 0x%lx IRQ %dn",
  259.        cs->hw.isurf.reset,
  260.        cs->hw.isurf.phymem,
  261.        cs->irq);
  262. cs->cardmsg = &ISurf_card_msg;
  263. cs->irq_func = &isurf_interrupt;
  264. cs->auxcmd = &isurf_auxcmd;
  265. cs->readisac = &ReadISAC;
  266. cs->writeisac = &WriteISAC;
  267. cs->readisacfifo = &ReadISACfifo;
  268. cs->writeisacfifo = &WriteISACfifo;
  269. cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
  270. cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
  271. reset_isurf(cs, ISURF_RESET);
  272. test_and_set_bit(HW_ISAR, &cs->HW_Flags);
  273. ISACVersion(cs, "ISurf:");
  274. cs->BC_Read_Reg = &ReadISAR;
  275. cs->BC_Write_Reg = &WriteISAR;
  276. cs->BC_Send_Data = &isar_fill_fifo;
  277. ver = ISARVersion(cs, "ISurf:");
  278. if (ver < 0) {
  279. printk(KERN_WARNING
  280. "ISurf: wrong ISAR version (ret = %d)n", ver);
  281. release_io_isurf(cs);
  282. return (0);
  283. }
  284. return (1);
  285. }