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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Moxa C101 synchronous serial card driver for Linux
  3.  *
  4.  * Copyright (C) 2000 Krzysztof Halasa <khc@pm.waw.pl>
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * For information see http://hq.pm.waw.pl/hdlc/
  12.  *
  13.  * Sources of information:
  14.  *    Hitachi HD64570 SCA User's Manual
  15.  *    Moxa C101 User's Manual
  16.  */
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/slab.h>
  20. #include <linux/types.h>
  21. #include <linux/string.h>
  22. #include <linux/errno.h>
  23. #include <linux/init.h>
  24. #include <linux/netdevice.h>
  25. #include <linux/hdlc.h>
  26. #include <linux/delay.h>
  27. #include <asm/io.h>
  28. #include "hd64570.h"
  29. #define DEBUG_RINGS
  30. /* #define DEBUG_PKT */
  31. static const char* version = "Moxa C101 driver revision: 1.02 for Linux 2.4";
  32. static const char* devname = "C101";
  33. #define C101_PAGE 0x1D00
  34. #define C101_DTR 0x1E00
  35. #define C101_SCA 0x1F00
  36. #define C101_WINDOW_SIZE 0x2000
  37. #define C101_MAPPED_RAM_SIZE 0x4000
  38. #define RAM_SIZE (256 * 1024)
  39. #define CLOCK_BASE 9830400 /* 9.8304 MHz */
  40. #define PAGE0_ALWAYS_MAPPED
  41. static char *hw; /* pointer to hw=xxx command line string */
  42. typedef struct card_s {
  43. hdlc_device hdlc; /* HDLC device struct - must be first */
  44. spinlock_t lock; /* TX lock */
  45. int clkmode; /* clock mode */
  46. int clkrate; /* clock speed */
  47. int line; /* loopback only */
  48. u8 *win0base; /* ISA window base address */
  49. u32 phy_winbase; /* ISA physical base address */
  50. u16 buff_offset; /* offset of first buffer of first channel */
  51. u8 rxs, txs, tmc; /* SCA registers */
  52. u8 irq; /* IRQ (3-15) */
  53. u8 ring_buffers; /* number of buffers in a ring */
  54. u8 page;
  55. u8 rxin; /* rx ring buffer 'in' pointer */
  56. u8 txin; /* tx ring buffer 'in' and 'last' pointers */
  57. u8 txlast;
  58. u8 rxpart; /* partial frame received, next frame invalid*/
  59. struct card_s *next_card;
  60. }card_t;
  61. typedef card_t port_t;
  62. #define sca_in(reg, card)    readb((card)->win0base + C101_SCA + (reg))
  63. #define sca_out(value, reg, card)  writeb(value, (card)->win0base + C101_SCA + (reg))
  64. #define sca_inw(reg, card)    readw((card)->win0base + C101_SCA + (reg))
  65. #define sca_outw(value, reg, card) writew(value, (card)->win0base + C101_SCA + (reg))
  66. #define port_to_card(port)    (port)
  67. #define log_node(port)    (0)
  68. #define phy_node(port)    (0)
  69. #define winsize(card)    (C101_WINDOW_SIZE)
  70. #define win0base(card)    ((card)->win0base)
  71. #define winbase(card)          ((card)->win0base + 0x2000)
  72. #define get_port(card, port)    ((port) == 0 ? (card) : NULL)
  73. static inline u8 sca_get_page(card_t *card)
  74. {
  75. return card->page;
  76. }
  77. static inline void openwin(card_t *card, u8 page)
  78. {
  79. card->page = page;
  80. writeb(page, card->win0base + C101_PAGE);
  81. }
  82. #define close_windows(card) {} /* no hardware support */
  83. #include "hd6457x.c"
  84. static int c101_set_clock(port_t *port, int value)
  85. {
  86. u8 msci = get_msci(port);
  87. u8 rxs = port->rxs & CLK_BRG_MASK;
  88. u8 txs = port->txs & CLK_BRG_MASK;
  89. switch(value) {
  90. case CLOCK_EXT:
  91. rxs |= CLK_LINE_RX; /* RXC input */
  92. txs |= CLK_LINE_TX; /* TXC input */
  93. break;
  94. case CLOCK_INT:
  95. rxs |= CLK_BRG_RX; /* TX clock */
  96. txs |= CLK_RXCLK_TX; /* BRG output */
  97. break;
  98. case CLOCK_TXINT:
  99. rxs |= CLK_LINE_RX; /* RXC input */
  100. txs |= CLK_BRG_TX; /* BRG output */
  101. break;
  102. case CLOCK_TXFROMRX:
  103. rxs |= CLK_LINE_RX; /* RXC input */
  104. txs |= CLK_RXCLK_TX; /* RX clock */
  105. break;
  106. default:
  107. return -EINVAL;
  108. }
  109. port->rxs = rxs;
  110. port->txs = txs;
  111. sca_out(rxs, msci + RXS, port);
  112. sca_out(txs, msci + TXS, port);
  113. port->clkmode = value;
  114. return 0;
  115. }
  116. static int c101_open(hdlc_device *hdlc)
  117. {
  118. port_t *port = hdlc_to_port(hdlc);
  119. MOD_INC_USE_COUNT;
  120. writeb(1, port->win0base + C101_DTR);
  121. sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */
  122. sca_open(hdlc);
  123. c101_set_clock(port, port->clkmode);
  124. return 0;
  125. }
  126. static void c101_close(hdlc_device *hdlc)
  127. {
  128. port_t *port = hdlc_to_port(hdlc);
  129. sca_close(hdlc);
  130. writeb(0, port->win0base + C101_DTR);
  131. sca_out(CTL_NORTS, MSCI1_OFFSET + CTL, port);
  132. MOD_DEC_USE_COUNT;
  133. }
  134. static int c101_ioctl(hdlc_device *hdlc, struct ifreq *ifr, int cmd)
  135. {
  136. int value = ifr->ifr_ifru.ifru_ivalue;
  137. int result = 0;
  138. port_t *port = hdlc_to_port(hdlc);
  139. if(!capable(CAP_NET_ADMIN))
  140. return -EPERM;
  141. switch(cmd) {
  142. case HDLCSCLOCK:
  143. result = c101_set_clock(port, value);
  144. case HDLCGCLOCK:
  145. value = port->clkmode;
  146. break;
  147. case HDLCSCLOCKRATE:
  148. port->clkrate = value;
  149. sca_set_clock(port);
  150. case HDLCGCLOCKRATE:
  151. value = port->clkrate;
  152. break;
  153. case HDLCSLINE:
  154. result = sca_set_loopback(port, value);
  155. case HDLCGLINE:
  156. value = port->line;
  157. break;
  158. #ifdef DEBUG_RINGS
  159. case HDLCRUN:
  160. sca_dump_rings(hdlc);
  161. return 0;
  162. #endif /* DEBUG_RINGS */
  163. default:
  164. return -EINVAL;
  165. }
  166. ifr->ifr_ifru.ifru_ivalue = value;
  167. return result;
  168. }
  169. static void c101_destroy_card(card_t *card)
  170. {
  171. if (card->irq)
  172. free_irq(card->irq, card);
  173. if (card->win0base) {
  174. iounmap(card->win0base);
  175. release_mem_region(card->phy_winbase, C101_MAPPED_RAM_SIZE);
  176. }
  177. kfree(card);
  178. }
  179. static int c101_run(unsigned long irq, unsigned long winbase)
  180. {
  181. card_t *card;
  182. int result;
  183. if (irq<3 || irq>15 || irq == 6) /* FIXME */ {
  184. printk(KERN_ERR "c101: invalid IRQ valuen");
  185. return -ENODEV;
  186. }
  187. if (winbase < 0xC0000 || winbase > 0xDFFFF || (winbase & 0x3FFF) !=0) {
  188. printk(KERN_ERR "c101: invalid RAM valuen");
  189. return -ENODEV;
  190. }
  191. card = kmalloc(sizeof(card_t), GFP_KERNEL);
  192. if (card == NULL) {
  193. printk(KERN_ERR "c101: unable to allocate memoryn");
  194. return -ENOBUFS;
  195. }
  196. memset(card, 0, sizeof(card_t));
  197. if (request_irq(irq, sca_intr, 0, devname, card)) {
  198. printk(KERN_ERR "c101: could not allocate IRQn");
  199. c101_destroy_card(card);
  200. return(-EBUSY);
  201. }
  202. card->irq = irq;
  203. if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) {
  204. printk(KERN_ERR "c101: could not request RAM windown");
  205. c101_destroy_card(card);
  206. return(-EBUSY);
  207. }
  208. card->phy_winbase = winbase;
  209. card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE);
  210. if (!card->win0base) {
  211. printk(KERN_ERR "c101: could not map I/O addressn");
  212. c101_destroy_card(card);
  213. return -EBUSY;
  214. }
  215. /* 2 rings required for 1 port */
  216. card->ring_buffers = (RAM_SIZE -C101_WINDOW_SIZE) / (2 * HDLC_MAX_MRU);
  217. printk(KERN_DEBUG "c101: using %u packets ringsn",card->ring_buffers);
  218. card->buff_offset = C101_WINDOW_SIZE; /* Bytes 1D00-1FFF reserved */
  219. readb(card->win0base + C101_PAGE); /* Resets SCA? */
  220. udelay(100);
  221. writeb(0, card->win0base + C101_PAGE);
  222. writeb(0, card->win0base + C101_DTR); /* Power-up for RAM? */
  223. sca_init(card, 0);
  224. spin_lock_init(&card->lock);
  225. hdlc_to_dev(&card->hdlc)->irq = irq;
  226. hdlc_to_dev(&card->hdlc)->mem_start = winbase;
  227. hdlc_to_dev(&card->hdlc)->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1;
  228. hdlc_to_dev(&card->hdlc)->tx_queue_len = 50;
  229. card->hdlc.ioctl = c101_ioctl;
  230. card->hdlc.open = c101_open;
  231. card->hdlc.close = c101_close;
  232. card->hdlc.xmit = sca_xmit;
  233. result = register_hdlc_device(&card->hdlc);
  234. if (result) {
  235. printk(KERN_WARNING "c101: unable to register hdlc devicen");
  236. c101_destroy_card(card);
  237. return result;
  238. }
  239. sca_init_sync_port(card); /* Set up C101 memory */
  240. *new_card = card;
  241. new_card = &card->next_card;
  242. return 0;
  243. }
  244. static int __init c101_init(void)
  245. {
  246. if (hw == NULL) {
  247. #ifdef MODULE
  248. printk(KERN_INFO "c101: no card initializedn");
  249. #endif
  250. return -ENOSYS; /* no parameters specified, abort */
  251. }
  252. printk(KERN_INFO "%sn", version);
  253. do {
  254. unsigned long irq, ram;
  255. irq = simple_strtoul(hw, &hw, 0);
  256. if (*hw++ != ',')
  257. break;
  258. ram = simple_strtoul(hw, &hw, 0);
  259. if (*hw == ':' || *hw == 'x0')
  260. c101_run(irq, ram);
  261. if (*hw == 'x0')
  262. return 0;
  263. }while(*hw++ == ':');
  264. printk(KERN_ERR "c101: invalid hardware parametersn");
  265. return first_card ? 0 : -ENOSYS;
  266. }
  267. #ifndef MODULE
  268. static int __init c101_setup(char *str)
  269. {
  270. hw = str;
  271. return 1;
  272. }
  273. __setup("c101=", c101_setup);
  274. #endif
  275. static void __exit c101_cleanup(void)
  276. {
  277. card_t *card = first_card;
  278. while (card) {
  279. card_t *ptr = card;
  280. card = card->next_card;
  281. unregister_hdlc_device(&ptr->hdlc);
  282. c101_destroy_card(ptr);
  283. }
  284. }
  285. module_init(c101_init);
  286. module_exit(c101_cleanup);
  287. MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
  288. MODULE_DESCRIPTION("Moxa C101 serial port driver");
  289. MODULE_LICENSE("GPL");
  290. MODULE_PARM(hw, "s"); /* hw=irq,ram:irq,... */
  291. EXPORT_NO_SYMBOLS;