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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) Eicon Technology Corporation, 2000.
  3.  *
  4.  * Eicon File Revision :    1.16  
  5.  *
  6.  * This software may be used and distributed according to the terms
  7.  * of the GNU General Public License, incorporated herein by reference.
  8.  *
  9.  */
  10. #define N_DATA
  11. #include <asm/io.h>
  12. #include <asm/system.h>
  13. #include <linux/slab.h>
  14. #include <linux/pci.h>
  15. #include <linux/delay.h>
  16. #undef N_DATA
  17. #include "uxio.h"
  18. static
  19. int log_on=0;
  20. int Divasdevflag = 0;
  21. //spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
  22. static
  23. ux_diva_card_t card_pool[MAX_CARDS];
  24. void UxPause(long int ms)
  25. {
  26. int timeout = jiffies + ((ms * HZ) / 1000);
  27. while (time_before(jiffies, timeout));
  28. }
  29. int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg)
  30. {
  31. int  i;
  32. ux_diva_card_t *c;
  33. if (cfg->bus_type != DIA_BUS_TYPE_PCI)
  34. {
  35. DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type));
  36. return -1;
  37. }
  38. for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++)
  39. {
  40. ;
  41. }
  42. if (i == DIM(card_pool))
  43. {
  44. DPRINTF(("divas hw: card_pool exhausted"));
  45. return -1;
  46. }
  47. c = *card = &card_pool[i];
  48. switch (cfg->bus_type)
  49. {
  50. case DIA_BUS_TYPE_PCI:
  51. c->bus_num = cfg->bus_num;
  52. c->func_num = cfg->func_num;
  53. c->io_base = cfg->io_base;
  54. c->reset_base = cfg->reset_base;
  55. c->card_type    = cfg->card_type;
  56. c->mapped = NULL;
  57. c->slot  = cfg->slot;
  58. c->irq  = (int) cfg->irq;
  59. c->pDRAM     = cfg->memory[DIVAS_RAM_MEMORY];
  60. c->pDEVICES  = cfg->memory[DIVAS_REG_MEMORY];
  61. c->pCONFIG   = cfg->memory[DIVAS_CFG_MEMORY];
  62. c->pSHARED   = cfg->memory[DIVAS_SHARED_MEMORY];
  63. c->pCONTROL   = cfg->memory[DIVAS_CTL_MEMORY];
  64. /* c->bus_type  = DIA_BUS_TYPE_PCI;
  65. c->bus_num  = cfg->bus_num & 0x3f;
  66. c->slot  = cfg->slot;
  67. c->irq  = (int) cfg->irq;
  68. c->int_priority = (int) cfg->int_priority;
  69. c->card_type    = cfg->card_type;
  70. c->io_base      = cfg->io_base;
  71. c->reset_base   = cfg->reset_base;
  72. c->pDRAM     = cfg->memory[DIVAS_RAM_MEMORY];
  73. c->pDEVICES  = cfg->memory[DIVAS_REG_MEMORY];
  74. c->pCONFIG   = cfg->memory[DIVAS_CFG_MEMORY];
  75. c->pSHARED   = cfg->memory[DIVAS_SHARED_MEMORY];
  76. DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
  77. DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
  78. DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
  79. c->cm_key = cm_getbrdkey("Divas", cfg->card_id);*/
  80. break;
  81. default:
  82. break;
  83. }
  84. c->in_use = TRUE;
  85. return 0;
  86. }
  87. void UxCardHandleFree(ux_diva_card_t *card)
  88. {
  89. card->in_use = FALSE;
  90. }
  91. #define PLX_IOBASE 0
  92. #define DIVAS_IOBASE 1
  93. void *UxCardMemAttach(ux_diva_card_t *card, int id)
  94. {
  95. if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER)
  96. {
  97. switch (id)
  98. {
  99. case DIVAS_SHARED_MEMORY:
  100. card->mapped = card->pSHARED;
  101. return card->pSHARED;
  102. break;
  103. case DIVAS_RAM_MEMORY:
  104. card->mapped = card->pDRAM;
  105. return card->pDRAM;
  106. break;
  107. case DIVAS_REG_MEMORY:
  108. card->mapped = card->pDEVICES;
  109. return card->pDEVICES;
  110. break;
  111. case DIVAS_CFG_MEMORY:
  112. card->mapped = card->pCONFIG;
  113. return card->pCONFIG;
  114. break;
  115. default:
  116. ASSERT(FALSE);
  117. card->mapped = NULL;
  118. return (void *) 0;
  119. }
  120. }
  121. else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
  122. {
  123. switch (id)
  124. {
  125. case PLX_IOBASE:
  126. return (void *) card->reset_base;
  127. break;
  128. case DIVAS_IOBASE:
  129. return (void *) card->io_base;
  130. break;
  131. default:
  132. ASSERT(FALSE);
  133. return 0;
  134. }
  135. }
  136. else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
  137. {
  138. switch (id)
  139. {
  140. case DIVAS_SHARED_MEMORY:
  141. card->mapped = card->pSHARED;
  142. return card->pSHARED;
  143. break;
  144. case DIVAS_RAM_MEMORY:
  145. card->mapped = card->pDRAM;
  146. return card->pDRAM;
  147. break;
  148. case DIVAS_REG_MEMORY:
  149. card->mapped = (void *) card->io_base;
  150. return (void *) card->io_base;
  151. break;
  152. case DIVAS_CTL_MEMORY:
  153. card->mapped = card->pCONTROL;
  154. return card->pCONTROL;
  155. break;
  156. default:
  157. // ASSERT(FALSE);
  158. DPRINTF(("divas: Trying to attach to mem %d", id));
  159. card->mapped = NULL;
  160. return (void *) 0;
  161. }
  162. } else
  163. DPRINTF(("divas: Tried to attach to unknown card"));
  164. /* Unknown card type */
  165. return NULL;
  166. }
  167. void UxCardMemDetach(ux_diva_card_t *card, void *address)
  168. {
  169. return; // Just a place holder. No un-mapping done.
  170. }
  171. void UxCardLog(int turn_on)
  172. {
  173. log_on = turn_on;
  174. }
  175. /*
  176.  * Control Register I/O Routines to be performed on Attached I/O ports
  177.  */
  178. void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte)
  179. {
  180. word base = (word) (dword) AttachedBase;
  181. base += offset;
  182. outb(the_byte, base);
  183. }
  184. void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word)
  185. {
  186. word base = (word) (dword) AttachedBase;
  187. base += offset;
  188. outw(the_word, base);
  189. }
  190. void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword)
  191. {
  192. word base = (word) (dword) AttachedBase;
  193. base += offset;
  194. outl(the_dword, base);
  195. }
  196. byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset)
  197. {
  198. word base = (word) (dword) AttachedBase;
  199. base += offset;
  200. return inb(base);
  201. }
  202. word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset)
  203. {
  204. word base = (word) (dword) AttachedBase;
  205. base += offset;
  206. return inw(base);
  207. }
  208. /*
  209.  * Memory mapped card I/O functions
  210.  */
  211. byte UxCardMemIn(ux_diva_card_t *card, void *address)
  212. {
  213. byte b;
  214. volatile byte* t = (byte*)address;
  215. b = *t;
  216. if (log_on)
  217. {
  218. byte *a = address;
  219. a -= (int) card->mapped;
  220. DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a));
  221.      }
  222.     return(b); 
  223. }
  224. word UxCardMemInW(ux_diva_card_t *card, void *address)
  225. {
  226. word w;
  227. volatile word* t = (word*)address;
  228.     w = *t;
  229. if (log_on)
  230.     {
  231. byte *a = address;
  232. a -= (int) card->mapped;
  233. DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a));
  234.     }
  235.     return (w);
  236. }
  237. dword UxCardMemInD(ux_diva_card_t *card, void *address)
  238. {
  239. dword dw;
  240. volatile dword* t = (dword*)address;
  241.     dw = *t;
  242. if (log_on)
  243.     {
  244. byte *a = address;
  245. a -= (int) card->mapped;
  246. DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a));
  247.     }
  248.     return (dw);
  249. }
  250. void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
  251. {
  252. volatile byte *pSource = address;
  253. byte *pDest = buffer;
  254. while (length--)
  255. {
  256. *pDest++ = *pSource++;
  257. }
  258. if (log_on)
  259.     {
  260. byte *a = address;
  261. a -= (int) card->mapped;
  262. pDest = buffer;
  263. DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)", 
  264. pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
  265. pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
  266. a));
  267.     }
  268.     return;
  269. }
  270. void UxCardMemOut(ux_diva_card_t *card, void *address, byte data)
  271. {
  272. volatile byte* t = (byte*)address;
  273. if (log_on)
  274. {
  275. byte *a = address;
  276. a -= (int) card->mapped;
  277. DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a));
  278. }
  279. *t = data;
  280.      return;
  281. }
  282. void UxCardMemOutW(ux_diva_card_t *card, void *address, word data)
  283. {
  284. volatile word* t = (word*)address;
  285. if (log_on)
  286. {
  287. byte *a = address;
  288. a -= (int) card->mapped;
  289. DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a));
  290. }
  291. *t = data;
  292.     return;
  293. }
  294. void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data)
  295. {
  296. volatile dword* t = (dword*)address;
  297. if (log_on)
  298. {
  299. byte *a = address;
  300. a -= (int) card->mapped;
  301. DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a));
  302. }
  303. *t = data;
  304.     return;
  305. }
  306. void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
  307. {
  308. byte  *pSource = buffer;
  309. byte *pDest = address;
  310. while (length--)
  311. {
  312. *pDest++ = *pSource++;
  313. }
  314. if (log_on)
  315.     {
  316. byte *a = address;
  317. a -= (int) card->mapped;
  318. pDest = buffer;
  319. DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)", 
  320. pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
  321. pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
  322. a));
  323.     }
  324.     return;
  325. }
  326. /*
  327.  * Memory mapped card I/O functions
  328.  */
  329. byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
  330. {
  331. byte the_byte;
  332.     outb(0xFF, card->io_base + 0xC);
  333. outw((word) (dword) address, card->io_base + 4);
  334. the_byte = inb(card->io_base);
  335. if (log_on)
  336.     {
  337. DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)", 
  338. the_byte & 0xff, address));
  339.     }
  340.     
  341. return the_byte;
  342. }
  343. word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
  344. {
  345. word the_word;
  346. outb(0xFF, card->io_base + 0xC);
  347. outw((word) (dword) address, card->io_base + 4);
  348. the_word = inw(card->io_base);
  349. if (log_on)
  350.     {
  351. DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)", 
  352. the_word & 0xffff, address));
  353.     }
  354. return the_word;
  355. }
  356. dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
  357. {
  358. dword the_dword;
  359. outb(0xFF, card->io_base + 0xC);
  360. outw((word) (dword) address, card->io_base + 4);
  361. the_dword = inl(card->io_base);
  362. if (log_on)
  363.     {
  364. DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)", 
  365. the_dword, address));
  366.     }
  367.     return the_dword;
  368. }
  369. void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
  370. {
  371. byte *pSource = address;
  372. byte *pDest = buffer;
  373. if ((word) (dword) address & 0x1)
  374. {
  375. outb(0xFF, card->io_base + 0xC);
  376. outw((word) (dword) pSource, card->io_base + 4);
  377. *pDest = (byte) inb(card->io_base);
  378. pDest++;
  379. pSource++;
  380. length--;
  381. if (!length)
  382.         {
  383.             return;
  384.         }
  385.     }
  386. outb(0xFF, card->io_base + 0xC);
  387. outw((word) (dword) pSource, card->io_base + 4);
  388. insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
  389. if (log_on)
  390.     {
  391. pDest = buffer;
  392. DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)", 
  393. pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
  394. pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
  395. address));
  396.     }
  397.     return;
  398. }
  399. /* Output */
  400. void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data)
  401. {
  402. if (log_on)
  403.     {
  404. DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)", 
  405. data & 0xff, address));
  406.     }
  407. outb(0xFF, card->io_base + 0xC);
  408. outw((word) (dword) address, card->io_base + 4);
  409. outb((byte) data & 0xFF, card->io_base);
  410.     return;
  411. }
  412. void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data)
  413. {
  414. if (log_on)
  415.     {
  416. DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)", 
  417. data & 0xffff, address));
  418.     }
  419. outb(0xFF, card->io_base + 0xC);
  420. outw((word) (dword) address, card->io_base + 4);
  421. outw((word) data & 0xFFFF, card->io_base);
  422.     return;
  423. }
  424. void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data)
  425. {
  426. if (log_on)
  427.     {
  428. DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address));
  429.     }
  430. outb(0xFF, card->io_base + 0xC);
  431. outw((word) (dword) address, card->io_base + 4);
  432. outl((dword) data & 0xFFFFFFFF, card->io_base);
  433.     return;
  434. }
  435. void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
  436. {
  437. byte  *pSource = buffer;
  438. byte *pDest = address;
  439. if ((word) (dword) address & 1)
  440. {
  441. outb(0xFF, card->io_base + 0xC);
  442. outw((word) (dword) pDest, card->io_base + 4);
  443. outb(*pSource, card->io_base);
  444. pSource++;
  445. pDest++;
  446. length--;
  447. if (!length)
  448.         {
  449. return;
  450.         }
  451. }
  452.     outb(0xFF, card->io_base + 0xC);
  453. outw((word) (dword) pDest, card->io_base + 4);
  454. outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
  455. if (log_on)
  456.     {
  457. pDest = buffer;
  458. DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)", 
  459. pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
  460. pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
  461. address));
  462.     }
  463.     return;
  464. }
  465. void  Divasintr(int arg, void *unused, struct pt_regs *unused_regs)
  466. {
  467. int i;
  468. card_t *card = NULL;
  469. ux_diva_card_t *ux_ref = NULL;
  470. for (i = 0; i < DivasCardNext; i++)
  471. {
  472. if (arg == DivasCards[i].cfg.irq)
  473. {
  474. card = &DivasCards[i];
  475. ux_ref = card->hw;
  476. if ((ux_ref) && (card->is_live))
  477. {
  478. (*ux_ref->user_isr)(ux_ref->user_isr_arg);
  479. }
  480. else 
  481. {
  482. DPRINTF(("divas: ISR couldn't locate card"));
  483. }
  484. }
  485. }
  486. return;
  487. }
  488. int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg)
  489. {
  490. int result;
  491.         card->user_isr = isr_fn;
  492.         card->user_isr_arg = isr_arg;
  493. result = request_irq(card->irq, Divasintr, SA_INTERRUPT | SA_SHIRQ, "Divas", (void *) isr_arg);
  494. return result;
  495. }
  496. void UxIsrRemove(ux_diva_card_t *card, void *dev_id)
  497. {
  498. free_irq(card->irq, card->user_isr_arg);
  499. }
  500. void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
  501. {
  502. switch (size)
  503. {
  504. case sizeof(byte):
  505. pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
  506. break;
  507. case sizeof(word):
  508. pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
  509. break;
  510. case sizeof(dword):
  511. pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
  512. break;
  513. default:
  514. printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWriten");
  515. }
  516. }
  517. void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
  518. {
  519. switch (size)
  520. {
  521. case sizeof(byte):
  522. pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
  523. break;
  524. case sizeof(word):
  525. pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
  526. break;
  527. case sizeof(dword):
  528. pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
  529. break;
  530. default:
  531. printk(KERN_WARNING "Divas: Invalid size in UxPciConfigReadn");
  532. }
  533. }
  534. void *UxAlloc(unsigned int size)
  535. {
  536. void *m;
  537. m = kmalloc(size, GFP_ATOMIC);
  538. return m;
  539. }
  540. void UxFree(void *ptr)
  541. {
  542. kfree(ptr);
  543. }
  544. long UxCardLock(ux_diva_card_t *card)
  545. {
  546. unsigned long flags;
  547.   //spin_lock_irqsave(&diva_lock, flags);
  548. save_flags(flags);
  549. cli();
  550. return flags;
  551. }
  552. void UxCardUnlock(ux_diva_card_t *card, long ipl)
  553. {
  554. //spin_unlock_irqrestore(&diva_lock, ipl);
  555. restore_flags(ipl);
  556. }
  557. dword UxTimeGet(void)
  558. {
  559. return jiffies;
  560. }
  561. long UxInterlockedIncrement(ux_diva_card_t *card, long *dst)
  562. {
  563. register volatile long *p;
  564. register long ret;
  565. int ipl;
  566. p =dst;
  567. ipl = UxCardLock(card);
  568. *p += 1;
  569. ret = *p;
  570. UxCardUnlock(card,ipl);
  571. return(ret);
  572. }
  573. long UxInterlockedDecrement(ux_diva_card_t *card, long *dst)
  574. {
  575. register volatile long *p;
  576. register long ret;
  577. int ipl;
  578. p =dst;
  579. ipl = UxCardLock(card);
  580. *p -= 1;
  581. ret = *p;
  582. UxCardUnlock(card,ipl);
  583. return(ret);
  584. }