2 * linux/drivers/char/mem.c 4 * Copyright (C) 1991, 1992 Linus Torvalds 7 #include <linux/config.h> 8 #include <linux/types.h> 9 #include <linux/errno.h> 10 #include <linux/sched.h> 11 #include <linux/kernel.h> 12 #include <linux/major.h> 13 #include <linux/tty.h> 14 #include <linux/miscdevice.h> 15 #include <linux/tpqic02.h> 16 #include <linux/ftape.h> 17 #include <linux/malloc.h> 18 #include <linux/mman.h> 20 #include <linux/random.h> 22 #include <asm/segment.h> 24 #include <asm/pgtable.h> 27 voidsoundcard_init(void); 33 static intread_ram(struct inode
* inode
,struct file
* file
,char* buf
,int count
) 38 static intwrite_ram(struct inode
* inode
,struct file
* file
,const char* buf
,int count
) 43 static intread_mem(struct inode
* inode
,struct file
* file
,char* buf
,int count
) 45 unsigned long p
= file
->f_pos
; 51 if(MAP_NR(p
) >=MAP_NR(high_memory
)) 53 if(count
> high_memory
- p
) 54 count
= high_memory
- p
; 56 #if defined(__i386__)/* we don't have page 0 mapped on x86.. */ 57 while(p
< PAGE_OFFSET
+ PAGE_SIZE
&& count
>0) { 65 memcpy_tofs(buf
, (void*) p
, count
); 71 static intwrite_mem(struct inode
* inode
,struct file
* file
,const char* buf
,int count
) 73 unsigned long p
= file
->f_pos
; 79 if(MAP_NR(p
) >=MAP_NR(high_memory
)) 81 if(count
> high_memory
- p
) 82 count
= high_memory
- p
; 84 #if defined(__i386__)/* we don't have page 0 mapped on x86.. */ 85 while(PAGE_OFFSET
+ p
< PAGE_SIZE
&& count
>0) { 86 /* Hmm. Do something? */ 93 memcpy_fromfs((void*) p
, buf
, count
); 95 file
->f_pos
+= written
; 99 static intmmap_mem(struct inode
* inode
,struct file
* file
,struct vm_area_struct
* vma
) 101 if(vma
->vm_offset
& ~PAGE_MASK
) 103 #if defined(__i386__) 105 * hmm.. This disables high-memory caching, as the XFree86 team 106 * wondered about that at one time. 107 * The surround logic should disable caching for the high device 108 * addresses anyway, but right now this seems still needed. 110 if(x86
>3&& vma
->vm_offset
>= high_memory
) 111 pgprot_val(vma
->vm_page_prot
) |= _PAGE_PCD
; 113 if(remap_page_range(vma
->vm_start
, vma
->vm_offset
, vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
)) 115 vma
->vm_inode
= inode
; 120 static intread_kmem(struct inode
*inode
,struct file
*file
,char*buf
,int count
) 124 read1
=read_mem(inode
, file
, buf
, count
); 127 read2
=vread(buf
+ read1
, (char*) ((unsigned long) file
->f_pos
), count
- read1
); 130 file
->f_pos
+= read2
; 131 return read1
+ read2
; 134 static intread_port(struct inode
* inode
,struct file
* file
,char* buf
,int count
) 136 unsigned int i
= file
->f_pos
; 139 while(count
-- >0&& i
<65536) { 140 put_user(inb(i
),tmp
); 148 static intwrite_port(struct inode
* inode
,struct file
* file
,const char* buf
,int count
) 150 unsigned int i
= file
->f_pos
; 151 const char* tmp
= buf
; 153 while(count
-- >0&& i
<65536) { 154 outb(get_user(tmp
),i
); 162 static intread_null(struct inode
* node
,struct file
* file
,char* buf
,int count
) 167 static intwrite_null(struct inode
* inode
,struct file
* file
,const char* buf
,int count
) 172 static intread_zero(struct inode
* node
,struct file
* file
,char* buf
,int count
) 176 for(left
= count
; left
>0; left
--) { 183 static intmmap_zero(struct inode
* inode
,struct file
* file
,struct vm_area_struct
* vma
) 185 if(vma
->vm_flags
& VM_SHARED
) 187 if(zeromap_page_range(vma
->vm_start
, vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
)) 192 static intread_full(struct inode
* node
,struct file
* file
,char* buf
,int count
) 197 static intwrite_full(struct inode
* inode
,struct file
* file
,const char* buf
,int count
) 203 * Special lseek() function for /dev/null and /dev/zero. Most notably, you can fopen() 204 * both devices with "a" now. This was previously impossible. SRB. 207 static intnull_lseek(struct inode
* inode
,struct file
* file
, off_t offset
,int orig
) 209 return file
->f_pos
=0; 212 * The memory devices use the full 32/64 bits of the offset, and so we cannot 213 * check against negative addresses: they are ok. The return value is weird, 214 * though, in that case (0). 216 * also note that seeking relative to the "end of file" isn't supported: 217 * it has no meaning, so it returns -EINVAL. 219 static intmemory_lseek(struct inode
* inode
,struct file
* file
, off_t offset
,int orig
) 223 file
->f_pos
= offset
; 226 file
->f_pos
+= offset
; 236 #define write_kmem write_mem 237 #define mmap_kmem mmap_mem 238 #define zero_lseek null_lseek 239 #define write_zero write_null 241 static struct file_operations ram_fops
= { 245 NULL
,/* ram_readdir */ 246 NULL
,/* ram_select */ 249 NULL
,/* no special open code */ 250 NULL
,/* no special release code */ 254 static struct file_operations mem_fops
= { 258 NULL
,/* mem_readdir */ 259 NULL
,/* mem_select */ 262 NULL
,/* no special open code */ 263 NULL
,/* no special release code */ 267 static struct file_operations kmem_fops
= { 271 NULL
,/* kmem_readdir */ 272 NULL
,/* kmem_select */ 273 NULL
,/* kmem_ioctl */ 275 NULL
,/* no special open code */ 276 NULL
,/* no special release code */ 280 static struct file_operations null_fops
= { 284 NULL
,/* null_readdir */ 285 NULL
,/* null_select */ 286 NULL
,/* null_ioctl */ 288 NULL
,/* no special open code */ 289 NULL
,/* no special release code */ 293 static struct file_operations port_fops
= { 297 NULL
,/* port_readdir */ 298 NULL
,/* port_select */ 299 NULL
,/* port_ioctl */ 301 NULL
,/* no special open code */ 302 NULL
,/* no special release code */ 306 static struct file_operations zero_fops
= { 310 NULL
,/* zero_readdir */ 311 NULL
,/* zero_select */ 312 NULL
,/* zero_ioctl */ 314 NULL
,/* no special open code */ 315 NULL
/* no special release code */ 318 static struct file_operations full_fops
= { 322 NULL
,/* full_readdir */ 323 NULL
,/* full_select */ 324 NULL
,/* full_ioctl */ 326 NULL
,/* no special open code */ 327 NULL
/* no special release code */ 330 static intmemory_open(struct inode
* inode
,struct file
* filp
) 332 switch(MINOR(inode
->i_rdev
)) { 334 filp
->f_op
= &ram_fops
; 337 filp
->f_op
= &mem_fops
; 340 filp
->f_op
= &kmem_fops
; 343 filp
->f_op
= &null_fops
; 346 filp
->f_op
= &port_fops
; 349 filp
->f_op
= &zero_fops
; 352 filp
->f_op
= &full_fops
; 355 filp
->f_op
= &random_fops
; 358 filp
->f_op
= &urandom_fops
; 363 if(filp
->f_op
&& filp
->f_op
->open
) 364 return filp
->f_op
->open(inode
,filp
); 368 static struct file_operations memory_fops
= { 376 memory_open
,/* just a selector for the real open */ 381 intchr_dev_init(void) 383 if(register_chrdev(MEM_MAJOR
,"mem",&memory_fops
)) 384 printk("unable to get major %d for memory devs\n", MEM_MAJOR
); 387 #ifdef CONFIG_PRINTER 390 #if defined (CONFIG_BUSMOUSE) || defined(CONFIG_UMISC) || \ 391 defined (CONFIG_PSMOUSE) || defined (CONFIG_MS_BUSMOUSE) || \ 392 defined (CONFIG_ATIXL_BUSMOUSE) || defined(CONFIG_SOFT_WATCHDOG) || \ 399 #if CONFIG_QIC02_TAPE