home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / drivers / char / mem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  8.3 KB  |  376 lines

  1. /*
  2.  *  linux/kernel/chr_drv/mem.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  *
  6.  * This file is subject to the terms and conditions of the GNU General Public
  7.  * License.  See the file README.legal in the main directory of this archive
  8.  * for more details.
  9.  */
  10.  
  11. /*
  12.  * 680x0 support by Hamish Macdonald
  13.  */
  14.  
  15. #include <linux/config.h>
  16. #include <linux/types.h>
  17. #include <linux/errno.h>
  18. #include <linux/sched.h>
  19. #include <linux/kernel.h>
  20. #include <linux/major.h>
  21. #include <linux/tty.h>
  22. #include <linux/mouse.h>
  23. /* #include <linux/soundcard.h> */
  24. #include <linux/tpqic02.h>
  25. #include <linux/malloc.h>
  26. #include <linux/mman.h>
  27.  
  28. #include <asm/segment.h>
  29.  
  30. #ifdef CONFIG_SOUND
  31. extern long soundcard_init(long mem_start);
  32. #endif
  33.   
  34. static int read_ram(struct inode * inode, struct file * file,char * buf, int count)
  35. {
  36.     return -EIO;
  37. }
  38.  
  39. static int write_ram(struct inode * inode, struct file * file,char * buf, int count)
  40. {
  41.     return -EIO;
  42. }
  43.  
  44. static int read_mem(struct inode * inode, struct file * file,char * buf, int count)
  45. {
  46.     unsigned long p = file->f_pos;
  47.     int read;
  48.  
  49.     if (count < 0)
  50.         return -EINVAL;
  51.     count = valid_addr (p, count);
  52.     if (count == 0)
  53.         return -EINVAL;
  54.     read = 0;
  55.     while (p < PAGE_SIZE && count > 0) {
  56.         put_fs_byte(0,buf);
  57.         buf++;
  58.         p++;
  59.         count--;
  60.         read++;
  61.     }
  62.     memcpy_tofs(buf,(void *) p,count);
  63.     read += count;
  64.     file->f_pos += read;
  65.     return read;
  66. }
  67.  
  68. static int write_mem(struct inode * inode, struct file * file,char * buf, int count)
  69. {
  70.     unsigned long p = file->f_pos;
  71.     int written;
  72.  
  73.     if (count < 0)
  74.         return -EINVAL;
  75.     count = valid_addr (p, count);
  76.     if (count == 0)
  77.         return -EINVAL;
  78.     written = 0;
  79.     while (p < PAGE_SIZE && count > 0) {
  80.         /* Hmm. Do something? */
  81.         buf++;
  82.         p++;
  83.         count--;
  84.         written++;
  85.     }
  86.     memcpy_fromfs((void *) p,buf,count);
  87.     written += count;
  88.     file->f_pos += written;
  89.     return count;
  90. }
  91.  
  92. static int mmap_mem(struct inode * inode, struct file * file,
  93.     unsigned long addr, size_t len, int prot, unsigned long off)
  94. {
  95.     struct vm_area_struct * mpnt;
  96.  
  97.     if (off & 0xfff || off + len < off)
  98.         return -ENXIO;
  99.     if (remap_page_range(addr, off, len, prot))
  100.         return -EAGAIN;
  101. /* try to create a dummy vmm-structure so that the rest of the kernel knows we are here */
  102.     mpnt = (struct vm_area_struct * ) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
  103.     if (!mpnt)
  104.         return 0;
  105.  
  106.     mpnt->vm_task = current;
  107.     mpnt->vm_start = addr;
  108.     mpnt->vm_end = addr + len;
  109.     mpnt->vm_page_prot = prot;
  110.     mpnt->vm_share = NULL;
  111.     mpnt->vm_inode = inode;
  112.     inode->i_count++;
  113.     mpnt->vm_offset = off;
  114.     mpnt->vm_ops = NULL;
  115.     insert_vm_struct(current, mpnt);
  116.     merge_segments(current->mmap, NULL, NULL);
  117.     return 0;
  118. }
  119.  
  120. static int read_kmem(struct inode *inode, struct file *file, char *buf, int count)
  121. {
  122.     int read1, read2;
  123.  
  124.     read1 = read_mem(inode, file, buf, count);
  125.     if (read1 < 0)
  126.         return read1;
  127.     read2 = vread(buf + read1, (char *) file->f_pos, count - read1);
  128.     if (read2 < 0)
  129.         return read2;
  130.     file->f_pos += read2;
  131.     return read1 + read2;
  132. }
  133.  
  134. static int read_port(struct inode * inode,struct file * file,char * buf, int count)
  135. {
  136.     return -EIO;
  137. }
  138.  
  139. static int write_port(struct inode * inode,struct file * file,char * buf, int count)
  140. {
  141.     return -EIO;
  142. }
  143.  
  144. static int read_null(struct inode * node,struct file * file,char * buf,int count)
  145. {
  146.     return 0;
  147. }
  148.  
  149. static int write_null(struct inode * inode,struct file * file,char * buf, int count)
  150. {
  151.     return count;
  152. }
  153.  
  154. static int read_zero(struct inode * node,struct file * file,char * buf,int count)
  155. {
  156.     int left;
  157.  
  158.     for (left = count; left > 0; left--) {
  159.         put_fs_byte(0,buf);
  160.         buf++;
  161.     }
  162.     return count;
  163. }
  164.  
  165. static int mmap_zero(struct inode * inode, struct file * file,
  166.     unsigned long addr, size_t len, int prot, unsigned long off)
  167. {
  168.     struct vm_area_struct *mpnt;
  169.  
  170.     if (PAGE_IS_RW(prot))
  171.         return -EINVAL;
  172.     if (zeromap_page_range(addr, len, prot))
  173.         return -EAGAIN;
  174.     /*
  175.      * try to create a dummy vmm-structure so that the
  176.      * rest of the kernel knows we are here
  177.      */
  178.     mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
  179.     if (!mpnt)
  180.         return 0;
  181.  
  182.     mpnt->vm_task = current;
  183.     mpnt->vm_start = addr;
  184.     mpnt->vm_end = addr + len;
  185.     mpnt->vm_page_prot = prot;
  186.     mpnt->vm_share = NULL;
  187.     mpnt->vm_inode = inode;
  188.     inode->i_count++;
  189.     mpnt->vm_offset = off;
  190.     mpnt->vm_ops = NULL;
  191.     insert_vm_struct(current, mpnt);
  192.     merge_segments(current->mmap, ignoff_mergep, inode);
  193.     return 0;
  194. }
  195.  
  196. /*
  197.  * Special lseek() function for /dev/null and /dev/zero.  Most notably, you can fopen()
  198.  * both devices with "a" now.  This was previously impossible.  SRB.
  199.  */
  200.  
  201. static int null_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
  202. {
  203.     return file->f_pos=0;
  204. }
  205. /*
  206.  * The memory devices use the full 32 bits of the offset, and so we cannot
  207.  * check against negative addresses: they are ok. The return value is weird,
  208.  * though, in that case (0).
  209.  *
  210.  * also note that seeking relative to the "end of file" isn't supported:
  211.  * it has no meaning, so it returns -EINVAL.
  212.  */
  213. static int memory_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
  214. {
  215.     switch (orig) {
  216.         case 0:
  217.             file->f_pos = offset;
  218.             return file->f_pos;
  219.         case 1:
  220.             file->f_pos += offset;
  221.             return file->f_pos;
  222.         default:
  223.             return -EINVAL;
  224.     }
  225.     if (file->f_pos < 0)
  226.         return 0;
  227.     return file->f_pos;
  228. }
  229.  
  230. #define write_kmem    write_mem
  231. #define mmap_kmem    mmap_mem
  232. #define zero_lseek    null_lseek
  233. #define write_zero    write_null
  234.  
  235. static struct file_operations ram_fops = {
  236.     memory_lseek,
  237.     read_ram,
  238.     write_ram,
  239.     NULL,        /* ram_readdir */
  240.     NULL,        /* ram_select */
  241.     NULL,        /* ram_ioctl */
  242.     NULL,        /* ram_mmap */
  243.     NULL,        /* no special open code */
  244.     NULL,        /* no special release code */
  245.     NULL        /* fsync */
  246. };
  247.  
  248. static struct file_operations mem_fops = {
  249.     memory_lseek,
  250.     read_mem,
  251.     write_mem,
  252.     NULL,        /* mem_readdir */
  253.     NULL,        /* mem_select */
  254.     NULL,        /* mem_ioctl */
  255.     mmap_mem,
  256.     NULL,        /* no special open code */
  257.     NULL,        /* no special release code */
  258.     NULL        /* fsync */
  259. };
  260.  
  261. static struct file_operations kmem_fops = {
  262.     memory_lseek,
  263.     read_kmem,
  264.     write_kmem,
  265.     NULL,        /* kmem_readdir */
  266.     NULL,        /* kmem_select */
  267.     NULL,        /* kmem_ioctl */
  268.     mmap_kmem,
  269.     NULL,        /* no special open code */
  270.     NULL,        /* no special release code */
  271.     NULL        /* fsync */
  272. };
  273.  
  274. static struct file_operations null_fops = {
  275.     null_lseek,
  276.     read_null,
  277.     write_null,
  278.     NULL,        /* null_readdir */
  279.     NULL,        /* null_select */
  280.     NULL,        /* null_ioctl */
  281.     NULL,        /* null_mmap */
  282.     NULL,        /* no special open code */
  283.     NULL,        /* no special release code */
  284.     NULL        /* fsync */
  285. };
  286.  
  287. static struct file_operations port_fops = {
  288.     memory_lseek,
  289.     read_port,
  290.     write_port,
  291.     NULL,        /* port_readdir */
  292.     NULL,        /* port_select */
  293.     NULL,        /* port_ioctl */
  294.     NULL,        /* port_mmap */
  295.     NULL,        /* no special open code */
  296.     NULL,        /* no special release code */
  297.     NULL        /* fsync */
  298. };
  299.  
  300. static struct file_operations zero_fops = {
  301.     zero_lseek,
  302.     read_zero,
  303.     write_zero,
  304.     NULL,        /* zero_readdir */
  305.     NULL,        /* zero_select */
  306.     NULL,        /* zero_ioctl */
  307.     mmap_zero,        /* zero_mmap */
  308.     NULL,        /* no special open code */
  309.     NULL,        /* no special release code */
  310.     NULL        /* fsync */
  311. };
  312.  
  313. static int memory_open(struct inode * inode, struct file * filp)
  314. {
  315.     switch (MINOR(inode->i_rdev)) {
  316.         case 0:
  317.             filp->f_op = &ram_fops;
  318.             break;
  319.         case 1:
  320.             filp->f_op = &mem_fops;
  321.             break;
  322.         case 2:
  323.             filp->f_op = &kmem_fops;
  324.             break;
  325.         case 3:
  326.             filp->f_op = &null_fops;
  327.             break;
  328.         case 4:
  329.             filp->f_op = &port_fops;
  330.             break;
  331.         case 5:
  332.             filp->f_op = &zero_fops;
  333.             break;
  334.         default:
  335.             return -ENODEV;
  336.     }
  337.     if (filp->f_op && filp->f_op->open)
  338.         return filp->f_op->open(inode,filp);
  339.     return 0;
  340. }
  341.  
  342. static struct file_operations memory_fops = {
  343.     NULL,        /* lseek */
  344.     NULL,        /* read */
  345.     NULL,        /* write */
  346.     NULL,        /* readdir */
  347.     NULL,        /* select */
  348.     NULL,        /* ioctl */
  349.     NULL,        /* mmap */
  350.     memory_open,    /* just a selector for the real open */
  351.     NULL,        /* release */
  352.     NULL        /* fsync */
  353. };
  354.  
  355. long chr_dev_init(long mem_start, long mem_end)
  356. {
  357.     if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
  358.         printk("unable to get major %d for memory devs\n", MEM_MAJOR);
  359.     mem_start = tty_init(mem_start);
  360. #ifdef CONFIG_PRINTER
  361.     mem_start = lp_init(mem_start);
  362. #endif
  363. #if defined (CONFIG_BUSMOUSE) || defined (CONFIG_82C710_MOUSE) || \
  364.     defined (CONFIG_PSMOUSE) || defined (CONFIG_MS_BUSMOUSE) || \
  365.     defined (CONFIG_ATIXL_BUSMOUSE) || defined (CONFIG_AMIGAMOUSE)
  366.     mem_start = mouse_init(mem_start);
  367. #endif
  368. #ifdef CONFIG_SOUND
  369.       mem_start = soundcard_init(mem_start);
  370. #endif
  371. #if CONFIG_TAPE_QIC02
  372.       mem_start = tape_qic02_init(mem_start);
  373. #endif
  374.     return mem_start;
  375. }
  376.