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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: niccy.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
  2.  *
  3.  * low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
  4.  * compatible (SAGEM cybermodem)
  5.  *
  6.  * Author       Karsten Keil
  7.  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
  8.  * 
  9.  * This software may be used and distributed according to the terms
  10.  * of the GNU General Public License, incorporated herein by reference.
  11.  * 
  12.  * Thanks to Dr. Neuhaus and SAGEM for information
  13.  *
  14.  */
  15. #define __NO_VERSION__
  16. #include <linux/config.h>
  17. #include <linux/init.h>
  18. #include "hisax.h"
  19. #include "isac.h"
  20. #include "hscx.h"
  21. #include "isdnl1.h"
  22. #include <linux/pci.h>
  23. #include <linux/isapnp.h>
  24. extern const char *CardType[];
  25. const char *niccy_revision = "$Revision: 1.1.4.1 $";
  26. #define byteout(addr,val) outb(val,addr)
  27. #define bytein(addr) inb(addr)
  28. #define ISAC_PCI_DATA 0
  29. #define HSCX_PCI_DATA 1
  30. #define ISAC_PCI_ADDR 2
  31. #define HSCX_PCI_ADDR 3
  32. #define ISAC_PNP 0
  33. #define HSCX_PNP 1
  34. /* SUB Types */
  35. #define NICCY_PNP 1
  36. #define NICCY_PCI 2
  37. /* PCI stuff */
  38. #define PCI_IRQ_CTRL_REG 0x38
  39. #define PCI_IRQ_ENABLE 0x1f00
  40. #define PCI_IRQ_DISABLE 0xff0000
  41. #define PCI_IRQ_ASSERT 0x800000
  42. static inline u_char
  43. readreg(unsigned int ale, unsigned int adr, u_char off)
  44. {
  45. register u_char ret;
  46. long flags;
  47. save_flags(flags);
  48. cli();
  49. byteout(ale, off);
  50. ret = bytein(adr);
  51. restore_flags(flags);
  52. return (ret);
  53. }
  54. static inline void
  55. readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
  56. {
  57. /* fifo read without cli because it's allready done  */
  58. byteout(ale, off);
  59. insb(adr, data, size);
  60. }
  61. static inline void
  62. writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
  63. {
  64. long flags;
  65. save_flags(flags);
  66. cli();
  67. byteout(ale, off);
  68. byteout(adr, data);
  69. restore_flags(flags);
  70. }
  71. static inline void
  72. writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
  73. {
  74. /* fifo write without cli because it's allready done  */
  75. byteout(ale, off);
  76. outsb(adr, data, size);
  77. }
  78. /* Interface functions */
  79. static u_char
  80. ReadISAC(struct IsdnCardState *cs, u_char offset)
  81. {
  82. return (readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset));
  83. }
  84. static void
  85. WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
  86. {
  87. writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset, value);
  88. }
  89. static void
  90. ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  91. {
  92. readfifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size);
  93. }
  94. static void
  95. WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
  96. {
  97. writefifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size);
  98. }
  99. static u_char
  100. ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
  101. {
  102. return (readreg(cs->hw.niccy.hscx_ale,
  103. cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0)));
  104. }
  105. static void
  106. WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
  107. {
  108. writereg(cs->hw.niccy.hscx_ale,
  109.  cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0), value);
  110. }
  111. #define READHSCX(cs, nr, reg) readreg(cs->hw.niccy.hscx_ale, 
  112. cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0))
  113. #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.niccy.hscx_ale, 
  114. cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0), data)
  115. #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.niccy.hscx_ale, 
  116. cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt)
  117. #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.niccy.hscx_ale, 
  118. cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt)
  119. #include "hscx_irq.c"
  120. static void
  121. niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs)
  122. {
  123. struct IsdnCardState *cs = dev_id;
  124. u_char val;
  125. if (!cs) {
  126. printk(KERN_WARNING "Niccy: Spurious interrupt!n");
  127. return;
  128. }
  129. if (cs->subtyp == NICCY_PCI) {
  130. int ival;
  131. ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
  132. if (!(ival & PCI_IRQ_ASSERT)) /* IRQ not for us (shared) */
  133. return;
  134. outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
  135. }
  136. val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
  137.       Start_HSCX:
  138. if (val)
  139. hscx_int_main(cs, val);
  140. val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA);
  141.       Start_ISAC:
  142. if (val)
  143. isac_interrupt(cs, val);
  144. val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
  145. if (val) {
  146. if (cs->debug & L1_DEB_HSCX)
  147. debugl1(cs, "HSCX IntStat after IntRoutine");
  148. goto Start_HSCX;
  149. }
  150. val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA);
  151. if (val) {
  152. if (cs->debug & L1_DEB_ISAC)
  153. debugl1(cs, "ISAC IntStat after IntRoutine");
  154. goto Start_ISAC;
  155. }
  156. writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF);
  157. writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF);
  158. writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF);
  159. writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0);
  160. writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0);
  161. writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0);
  162. }
  163. void
  164. release_io_niccy(struct IsdnCardState *cs)
  165. {
  166. if (cs->subtyp == NICCY_PCI) {
  167. int val;
  168. val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
  169. val &= PCI_IRQ_DISABLE;
  170. outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
  171. release_region(cs->hw.niccy.cfg_reg, 0x40);
  172. release_region(cs->hw.niccy.isac, 4);
  173. } else {
  174. release_region(cs->hw.niccy.isac, 2);
  175. release_region(cs->hw.niccy.isac_ale, 2);
  176. }
  177. }
  178. static void
  179. niccy_reset(struct IsdnCardState *cs)
  180. {
  181. if (cs->subtyp == NICCY_PCI) {
  182. int val;
  183. val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
  184. val |= PCI_IRQ_ENABLE;
  185. outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
  186. }
  187. inithscxisac(cs, 3);
  188. }
  189. static int
  190. niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
  191. {
  192. switch (mt) {
  193. case CARD_RESET:
  194. niccy_reset(cs);
  195. return(0);
  196. case CARD_RELEASE:
  197. release_io_niccy(cs);
  198. return(0);
  199. case CARD_INIT:
  200. niccy_reset(cs);
  201. return(0);
  202. case CARD_TEST:
  203. return(0);
  204. }
  205. return(0);
  206. }
  207. static struct pci_dev *niccy_dev __initdata = NULL;
  208. #ifdef __ISAPNP__
  209. static struct pci_bus *pnp_c __devinitdata = NULL;
  210. #endif
  211. int __init
  212. setup_niccy(struct IsdnCard *card)
  213. {
  214. struct IsdnCardState *cs = card->cs;
  215. char tmp[64];
  216. strcpy(tmp, niccy_revision);
  217. printk(KERN_INFO "HiSax: Niccy driver Rev. %sn", HiSax_getrev(tmp));
  218. if (cs->typ != ISDN_CTYPE_NICCY)
  219. return (0);
  220. #ifdef __ISAPNP__
  221. if (!card->para[1] && isapnp_present()) {
  222. struct pci_bus *pb;
  223. struct pci_dev *pd;
  224. if ((pb = isapnp_find_card(
  225. ISAPNP_VENDOR('S', 'D', 'A'),
  226. ISAPNP_FUNCTION(0x0150), pnp_c))) {
  227. pnp_c = pb;
  228. pd = NULL;
  229. if (!(pd = isapnp_find_dev(pnp_c,
  230. ISAPNP_VENDOR('S', 'D', 'A'),
  231. ISAPNP_FUNCTION(0x0150), pd))) {
  232. printk(KERN_ERR "NiccyPnP: PnP error card found, no devicen");
  233. return (0);
  234. }
  235. pd->prepare(pd);
  236. pd->deactivate(pd);
  237. pd->activate(pd);
  238. card->para[1] = pd->resource[0].start;
  239. card->para[2] = pd->resource[1].start;
  240. card->para[0] = pd->irq_resource[0].start;
  241. if (!card->para[0] || !card->para[1] || !card->para[2]) {
  242. printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lxn",
  243. card->para[0], card->para[1], card->para[2]);
  244. pd->deactivate(pd);
  245. return(0);
  246. }
  247. } else {
  248. printk(KERN_INFO "NiccyPnP: no ISAPnP card foundn");
  249. }
  250. }
  251. #endif
  252. if (card->para[1]) {
  253. cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
  254. cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
  255. cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
  256. cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
  257. cs->hw.niccy.cfg_reg = 0;
  258. cs->subtyp = NICCY_PNP;
  259. cs->irq = card->para[0];
  260. if (check_region((cs->hw.niccy.isac), 2)) {
  261. printk(KERN_WARNING
  262. "HiSax: %s data port %x-%x already in usen",
  263. CardType[card->typ],
  264. cs->hw.niccy.isac,
  265. cs->hw.niccy.isac + 1);
  266. return (0);
  267. } else
  268. request_region(cs->hw.niccy.isac, 2, "niccy data");
  269. if (check_region((cs->hw.niccy.isac_ale), 2)) {
  270. printk(KERN_WARNING
  271. "HiSax: %s address port %x-%x already in usen",
  272. CardType[card->typ],
  273. cs->hw.niccy.isac_ale,
  274. cs->hw.niccy.isac_ale + 1);
  275. release_region(cs->hw.niccy.isac, 2);
  276. return (0);
  277. } else
  278. request_region(cs->hw.niccy.isac_ale, 2, "niccy addr");
  279. } else {
  280. #if CONFIG_PCI
  281. u_int pci_ioaddr;
  282. if (!pci_present()) {
  283. printk(KERN_ERR "Niccy: no PCI bus presentn");
  284. return(0);
  285. }
  286. cs->subtyp = 0;
  287. if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
  288. PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) {
  289. if (pci_enable_device(niccy_dev))
  290. return(0);
  291. /* get IRQ */
  292. if (!niccy_dev->irq) {
  293. printk(KERN_WARNING "Niccy: No IRQ for PCI card foundn");
  294. return(0);
  295. }
  296. cs->irq = niccy_dev->irq;
  297. cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0);
  298. if (!cs->hw.niccy.cfg_reg) {
  299. printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg foundn");
  300. return(0);
  301. }
  302. pci_ioaddr = pci_resource_start(niccy_dev, 1);
  303. if (!pci_ioaddr) {
  304. printk(KERN_WARNING "Niccy: No IO-Adr for PCI card foundn");
  305. return(0);
  306. }
  307. cs->subtyp = NICCY_PCI;
  308. } else {
  309. printk(KERN_WARNING "Niccy: No PCI card foundn");
  310. return(0);
  311. }
  312. cs->irq_flags |= SA_SHIRQ;
  313. cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
  314. cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
  315. cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
  316. cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
  317. if (check_region((cs->hw.niccy.isac), 4)) {
  318. printk(KERN_WARNING
  319. "HiSax: %s data port %x-%x already in usen",
  320. CardType[card->typ],
  321. cs->hw.niccy.isac,
  322. cs->hw.niccy.isac + 4);
  323. return (0);
  324. } else
  325. request_region(cs->hw.niccy.isac, 4, "niccy");
  326. if (check_region(cs->hw.niccy.cfg_reg, 0x40)) {
  327. printk(KERN_WARNING
  328.        "HiSax: %s pci port %x-%x already in usen",
  329. CardType[card->typ],
  330. cs->hw.niccy.cfg_reg,
  331. cs->hw.niccy.cfg_reg + 0x40);
  332. release_region(cs->hw.niccy.isac, 4);
  333. return (0);
  334. } else {
  335. request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci");
  336. }
  337. #else
  338. printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOSn");
  339. printk(KERN_WARNING "Niccy: unable to config NICCY PCIn");
  340. return (0);
  341. #endif /* CONFIG_PCI */
  342. }
  343. printk(KERN_INFO
  344. "HiSax: %s %s config irq:%d data:0x%X ale:0x%Xn",
  345. CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
  346. cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
  347. cs->readisac = &ReadISAC;
  348. cs->writeisac = &WriteISAC;
  349. cs->readisacfifo = &ReadISACfifo;
  350. cs->writeisacfifo = &WriteISACfifo;
  351. cs->BC_Read_Reg = &ReadHSCX;
  352. cs->BC_Write_Reg = &WriteHSCX;
  353. cs->BC_Send_Data = &hscx_fill_fifo;
  354. cs->cardmsg = &niccy_card_msg;
  355. cs->irq_func = &niccy_interrupt;
  356. ISACVersion(cs, "Niccy:");
  357. if (HscxVersion(cs, "Niccy:")) {
  358. printk(KERN_WARNING
  359.     "Niccy: wrong HSCX versions check IO addressn");
  360. release_io_niccy(cs);
  361. return (0);
  362. }
  363. return (1);
  364. }