Advertisement
Guest User

Untitled

a guest
May 26th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.31 KB | None | 0 0
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/moduleparam.h>
  4. #include <linux/errno.h>
  5. #include <linux/types.h>
  6. #include <linux/proc_fs.h>
  7. #include <linux/fcntl.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/aio.h>
  10. #include <linux/cdev.h>
  11. #include <linux/delay.h>
  12. #include <linux/fs.h>
  13. #include <linux/proc_fs.h>
  14. #include <linux/cdev.h>
  15. #include <linux/kernel.h>
  16. #include <linux/kdev_t.h>
  17. #include <linux/slab.h>
  18. #include <linux/sched.h>
  19. #include <linux/mm.h>
  20. #include <linux/kfifo.h>
  21. #include <linux/ioctl.h>
  22. #include <linux/ioport.h>
  23. #include <linux/spinlock.h>
  24. #include <linux/wait.h>
  25.  
  26. #include <asm/uaccess.h>
  27. #include <asm/io.h>
  28. #include <asm/delay.h>
  29. #include <asm/errno.h>
  30. #include "serial_reg.h"
  31.  
  32. MODULE_LICENSE("Dual BSD/GPL");
  33. #define PORT_UART 0x3F8
  34. #define PORT_RANGE 8
  35. #define lsr PORT_UART+UART_LSR
  36. #define TAMFIFO 8
  37.  
  38. static int init(void);
  39. static void exit(void);
  40. irqreturn_t handler(int irq, void* cdevs);
  41. ssize_t as_read (struct file *, char __user *, size_t, loff_t *);
  42. ssize_t as_write (struct file *, const char __user *, size_t, loff_t *);
  43. int as_open (struct inode *, struct file *);
  44. int as_release (struct inode *, struct file *);
  45. void strcut(char *f, char *t, int i);
  46.  
  47. struct seri_dev_t {
  48. struct cdev cdev; // struct cdev for this device
  49. int cnt; // number of characters written to device
  50. wait_queue_head_t readQ;
  51. wait_queue_head_t writeQ;
  52. struct kfifo* fr;
  53. struct kfifo* fw;
  54. spinlock_t Rlock;
  55. spinlock_t Wlock;
  56. int Rflag;
  57. };
  58. struct seri_dev_t *cdevs;
  59.  
  60. dev_t dev;
  61. int status;
  62. struct cdev *cdp;
  63. struct file_operations as_fops = {
  64. .owner = THIS_MODULE,
  65. .read = as_read,
  66. .write = as_write,
  67. .open = as_open,
  68. .release = as_release,
  69. };
  70.  
  71. irqreturn_t handler(int irq, void* cdevs){
  72. struct seri_dev_t* cdev = (struct seri_dev_t*) cdevs;
  73. unsigned m;
  74. char c;
  75. int n;
  76. m = inb(PORT_UART + UART_IIR); // Check who made the interrupt
  77. if((m & UART_IIR_THRI)&&(kfifo_len(cdev->fw)>0))
  78. { // something to write, write
  79. n = kfifo_get(cdev->fw, &c, 1);
  80. if(n)
  81. {
  82. outb(c, PORT_UART + UART_TX);
  83. wake_up_interruptible(&(cdev->writeQ));
  84. }
  85. }
  86. if(m & UART_IIR_RDI)
  87. { // If receiving, read
  88. c = inb(PORT_UART + UART_RX);
  89. kfifo_put(cdev->fr, &c, 1);
  90. wake_up_interruptible(&(cdev->readQ));
  91. }
  92. return IRQ_HANDLED;
  93. }
  94.  
  95. static int init(void)
  96. {
  97. //Initialization UART
  98. int erro;
  99. unsigned lcr = 0, interrup=0;
  100. unsigned fifo=0;
  101. struct resource* region;
  102. region = request_region(PORT_UART, PORT_RANGE, "seri");
  103.  
  104. if(region==NULL){
  105. printk(KERN_ALERT "ERROR ALLOCATION SPACE\n");
  106. return -1;
  107. }
  108. //8-bit chars, 2 stop bits, parity even, activate DLatch
  109. lcr = UART_LCR_WLEN8|UART_LCR_STOP|UART_LCR_EPAR|UART_LCR_DLAB;
  110. outb(lcr, PORT_UART+UART_LCR);
  111.  
  112. outb(UART_DIV_1200, PORT_UART+UART_DLL); // LSB = bitrate we want
  113. outb(0x00, PORT_UART+UART_DLM); // MSB 8 bytes = 0
  114. while(!(inb(lsr) & UART_LSR_THRE)){
  115. schedule();
  116. }
  117. lcr &= ~UART_LCR_DLAB; // Bit from DLAB back to 0, while others remain (AND operation)
  118. outb(lcr, PORT_UART+UART_LCR);
  119.  
  120. //Initialization CDEV
  121. printk(KERN_ALERT "CHECKING IN\n");
  122. alloc_chrdev_region(&dev, 0, 1, "seri");
  123.  
  124. cdevs = kmalloc(sizeof(struct seri_dev_t), GFP_KERNEL);
  125. cdev_init(&(cdevs[0].cdev), &as_fops);
  126. cdevs[0].cdev.ops=&as_fops;
  127. cdevs[0].cdev.owner=THIS_MODULE;
  128.  
  129.  
  130. spin_lock_init(&(cdevs->Wlock));
  131. spin_lock_init(&(cdevs->Rlock));
  132. cdevs->fr =kfifo_alloc(TAMFIFO, GFP_KERNEL, &(cdevs->Rlock));
  133. cdevs->fw =kfifo_alloc(TAMFIFO, GFP_KERNEL, &(cdevs->Wlock));
  134. init_waitqueue_head(&(cdevs->readQ));
  135. init_waitqueue_head(&(cdevs->writeQ));
  136.  
  137.  
  138. if(cdev_add(&(cdevs[0].cdev), dev, 1)<0){
  139. printk(KERN_ALERT "ERROR ADDING CDEV!\n");
  140. }
  141.  
  142. else printk(KERN_ALERT "%d\n", MAJOR(dev));
  143.  
  144. erro = request_irq(4,handler, SA_INTERRUPT,"seri",(void*)cdevs);
  145. if(erro!=0){
  146. printk(KERN_ALERT "ERROR REQUEST IRQ\n");
  147. return -1;
  148. }
  149. interrup=UART_IER_THRI | UART_IER_RDI;
  150. outb(interrup,PORT_UART+UART_IER);
  151. fifo=UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
  152. outb(fifo, PORT_UART + UART_FCR);
  153. return 0;
  154. }
  155.  
  156. static void exit(void)
  157. {
  158. kfifo_free(cdevs->fw);
  159. kfifo_free(cdevs->fr);
  160. free_irq(4, (void*) cdevs);
  161. release_region(PORT_UART, PORT_RANGE);
  162. cdev_del(&(cdevs[0].cdev));
  163. unregister_chrdev_region(dev, 1);
  164. kfree(cdevs);
  165.  
  166. printk(KERN_ALERT "FREE\n");
  167. }
  168.  
  169. int as_open (struct inode * ino, struct file * filp){
  170. struct seri_dev_t *edevp;
  171. edevp = container_of(ino->i_cdev, struct seri_dev_t, cdev);
  172. filp->private_data = edevp;
  173. printk(KERN_ALERT "OPENED\n");
  174. edevp->cnt=0;
  175. nonseekable_open(ino, filp);
  176. return 0;
  177. }
  178. int as_release (struct inode *ino, struct file *filp){
  179. printk(KERN_ALERT "RELEASED\n");
  180. return 0;
  181. }
  182.  
  183. ssize_t as_read (struct file *filp, char __user * buff, size_t count, loff_t * f_pos){
  184. printk(KERN_ALERT "READING\n");
  185. /*O FIFO sempre a ser cheio automaticamente. Read chamado para copiar o que esta no FIFO para o buffer*/
  186. unsigned long err1;
  187. int erro, cnt=count, aux;
  188. char *in;
  189. struct seri_dev_t *cdev;
  190. cdev=filp->private_data;
  191. in = kmalloc(sizeof(char)*(cnt+1), GFP_KERNEL);
  192. while((aux=kfifo_len(cdevs->fr))<cnt){
  193. if(filp->f_flags & O_NONBLOCK)
  194. {
  195. if(kfifo_len(cdev->fr)<cnt)
  196. {
  197. kfree(in);
  198. printk(KERN_ALERT "O_NONBLOCK OUT\n");
  199. return -EAGAIN;
  200. }
  201. }
  202. erro=wait_event_interruptible(cdevs->readQ, ((kfifo_len(cdevs->fr))>aux));
  203. if(erro==-ERESTARTSYS){// CTRL-C
  204. printk(KERN_ALERT "WAIT OUTPUT ERROR\n");
  205. return -1;
  206. }
  207. }
  208. erro=kfifo_get(cdevs->fr, in, cnt);
  209. if(erro!=cnt){
  210. printk(KERN_ALERT "ERROR KFIFO_GET\n");
  211. return -1;
  212. }
  213. in[cnt]='\0';
  214. err1 = copy_to_user(buff, in, (cnt+1));
  215. if(err1 != 0){
  216. printk(KERN_ALERT "ERROR COPY_TO_USER\n");
  217. return EAGAIN;
  218. }
  219. kfree(in);
  220. return count;
  221. }
  222.  
  223. void strcut( char * f, char * t, int ind)
  224. {
  225. int c=0;
  226. while(f[c+ind]!=('\0'))
  227. {
  228. t[c]=f[ind+c];
  229. c++;
  230. }
  231. t[c]='\0';
  232. c=0;
  233. while(f[c]!=('\0'))
  234. {
  235. f[c]=t[c];
  236. c++;
  237. }
  238. f[c]='\0';
  239. }
  240.  
  241. ssize_t as_write (struct file *filp, const char __user *buff, size_t count, loff_t *f_pos){
  242. ssize_t s;
  243. int c, n, erro;
  244. char *tobuff, *aux, imp;
  245. struct seri_dev_t *cdev;
  246. cdev=filp->private_data;
  247.  
  248. tobuff=kmalloc(sizeof(char)*count, GFP_KERNEL);
  249. aux=kmalloc(sizeof(char)*count,GFP_KERNEL);
  250.  
  251. s=copy_from_user(tobuff, buff, strlen(buff));
  252. tobuff[count]='\0';
  253. if(s!=0){
  254. printk(KERN_ALERT "ERROR WRITING");
  255. return -1;
  256. }
  257. c=count+1;
  258.  
  259. while(c>0){
  260. if(filp->f_flags & O_NONBLOCK)
  261. {
  262. if(kfifo_len(cdev->fw)==TAMFIFO)
  263. {
  264. kfree(tobuff);
  265. kfree(aux);
  266. printk(KERN_ALERT "O_NONBLOCK OUT\n");
  267. return -EAGAIN;
  268. }
  269. }
  270. erro=wait_event_interruptible(cdevs->writeQ, (kfifo_len(cdev->fw) < TAMFIFO));
  271. if(erro==-ERESTARTSYS)//CTRL-C
  272. {
  273. printk( KERN_ALERT "ERROR WRITING\n");
  274. return -1;
  275. }
  276. n=kfifo_put(cdev->fw, tobuff, c);
  277. c = c-n;
  278. if(c!=0)
  279. {
  280. strcut(tobuff,aux,n);
  281. }
  282. if((inb(PORT_UART + UART_LSR) & UART_LSR_THRE))//Outb estรก vazio, ja mandou tudo do FIFO
  283. {
  284. erro = kfifo_get(cdev->fw, &imp, 1);
  285. if(erro!=0)
  286. {
  287.  
  288. outb(imp, PORT_UART + UART_TX);
  289.  
  290. }
  291. }
  292. }
  293. printk(KERN_ALERT "WROTE %s\n", tobuff);
  294. s=count;
  295. kfree(tobuff);
  296. kfree(aux);
  297. cdevs[0].cnt=count;
  298. return s;
  299. }
  300.  
  301. module_init(init);
  302. module_exit(exit);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement