2 * linux/kernel/chr_drv/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/mouse.h>
15 #include <linux/tpqic02.h>
16 #include <linux/malloc.h>
17 #include <linux/mman.h>
19 #include <asm/segment.h>
23 extern long soundcard_init(long mem_start
);
26 static int read_ram(struct inode
* inode
, struct file
* file
,char * buf
, int count
)
31 static int write_ram(struct inode
* inode
, struct file
* file
,char * buf
, int count
)
36 static int read_mem(struct inode
* inode
, struct file
* file
,char * buf
, int count
)
38 unsigned long p
= file
->f_pos
;
45 if (count
> high_memory
- p
)
46 count
= high_memory
- p
;
48 while (p
< PAGE_SIZE
&& count
> 0) {
55 memcpy_tofs(buf
,(void *) p
,count
);
61 static int write_mem(struct inode
* inode
, struct file
* file
,char * buf
, int count
)
63 unsigned long p
= file
->f_pos
;
70 if (count
> high_memory
- p
)
71 count
= high_memory
- p
;
73 while (p
< PAGE_SIZE
&& count
> 0) {
74 /* Hmm. Do something? */
80 memcpy_fromfs((void *) p
,buf
,count
);
82 file
->f_pos
+= written
;
86 static int mmap_mem(struct inode
* inode
, struct file
* file
,
87 unsigned long addr
, size_t len
, int prot
, unsigned long off
)
89 struct vm_area_struct
* mpnt
;
91 if (off
& 0xfff || off
+ len
< off
)
93 if (x86
> 3 && off
>= high_memory
)
95 if (remap_page_range(addr
, off
, len
, prot
))
97 /* try to create a dummy vmm-structure so that the rest of the kernel knows we are here */
98 mpnt
= (struct vm_area_struct
* ) kmalloc(sizeof(struct vm_area_struct
), GFP_KERNEL
);
102 mpnt
->vm_task
= current
;
103 mpnt
->vm_start
= addr
;
104 mpnt
->vm_end
= addr
+ len
;
105 mpnt
->vm_page_prot
= prot
;
106 mpnt
->vm_share
= NULL
;
107 mpnt
->vm_inode
= inode
;
109 mpnt
->vm_offset
= off
;
111 insert_vm_struct(current
, mpnt
);
112 merge_segments(current
->mmap
, NULL
, NULL
);
116 static int read_kmem(struct inode
*inode
, struct file
*file
, char *buf
, int count
)
120 read1
= read_mem(inode
, file
, buf
, count
);
123 read2
= vread(buf
+ read1
, (char *) file
->f_pos
, count
- read1
);
126 file
->f_pos
+= read2
;
127 return read1
+ read2
;
130 static int read_port(struct inode
* inode
,struct file
* file
,char * buf
, int count
)
132 unsigned int i
= file
->f_pos
;
135 while (count
-- > 0 && i
< 65536) {
136 put_fs_byte(inb(i
),tmp
);
144 static int write_port(struct inode
* inode
,struct file
* file
,char * buf
, int count
)
146 unsigned int i
= file
->f_pos
;
149 while (count
-- > 0 && i
< 65536) {
150 outb(get_fs_byte(tmp
),i
);
158 static int read_null(struct inode
* node
,struct file
* file
,char * buf
,int count
)
163 static int write_null(struct inode
* inode
,struct file
* file
,char * buf
, int count
)
168 static int read_zero(struct inode
* node
,struct file
* file
,char * buf
,int count
)
172 for (left
= count
; left
> 0; left
--) {
179 static int mmap_zero(struct inode
* inode
, struct file
* file
,
180 unsigned long addr
, size_t len
, int prot
, unsigned long off
)
182 struct vm_area_struct
*mpnt
;
186 if (zeromap_page_range(addr
, len
, prot
))
189 * try to create a dummy vmm-structure so that the
190 * rest of the kernel knows we are here
192 mpnt
= (struct vm_area_struct
*)kmalloc(sizeof(*mpnt
), GFP_KERNEL
);
196 mpnt
->vm_task
= current
;
197 mpnt
->vm_start
= addr
;
198 mpnt
->vm_end
= addr
+ len
;
199 mpnt
->vm_page_prot
= prot
;
200 mpnt
->vm_share
= NULL
;
201 mpnt
->vm_inode
= NULL
;
202 mpnt
->vm_offset
= off
;
204 insert_vm_struct(current
, mpnt
);
205 merge_segments(current
->mmap
, ignoff_mergep
, inode
);
209 static int read_full(struct inode
* node
,struct file
* file
,char * buf
,int count
)
214 static int write_full(struct inode
* inode
,struct file
* file
,char * buf
, int count
)
220 * Special lseek() function for /dev/null and /dev/zero. Most notably, you can fopen()
221 * both devices with "a" now. This was previously impossible. SRB.
224 static int null_lseek(struct inode
* inode
, struct file
* file
, off_t offset
, int orig
)
226 return file
->f_pos
=0;
229 * The memory devices use the full 32 bits of the offset, and so we cannot
230 * check against negative addresses: they are ok. The return value is weird,
231 * though, in that case (0).
233 * also note that seeking relative to the "end of file" isn't supported:
234 * it has no meaning, so it returns -EINVAL.
236 static int memory_lseek(struct inode
* inode
, struct file
* file
, off_t offset
, int orig
)
240 file
->f_pos
= offset
;
243 file
->f_pos
+= offset
;
253 #define write_kmem write_mem
254 #define mmap_kmem mmap_mem
255 #define zero_lseek null_lseek
256 #define write_zero write_null
258 static struct file_operations ram_fops
= {
262 NULL
, /* ram_readdir */
263 NULL
, /* ram_select */
264 NULL
, /* ram_ioctl */
266 NULL
, /* no special open code */
267 NULL
, /* no special release code */
271 static struct file_operations mem_fops
= {
275 NULL
, /* mem_readdir */
276 NULL
, /* mem_select */
277 NULL
, /* mem_ioctl */
279 NULL
, /* no special open code */
280 NULL
, /* no special release code */
284 static struct file_operations kmem_fops
= {
288 NULL
, /* kmem_readdir */
289 NULL
, /* kmem_select */
290 NULL
, /* kmem_ioctl */
292 NULL
, /* no special open code */
293 NULL
, /* no special release code */
297 static struct file_operations null_fops
= {
301 NULL
, /* null_readdir */
302 NULL
, /* null_select */
303 NULL
, /* null_ioctl */
304 NULL
, /* null_mmap */
305 NULL
, /* no special open code */
306 NULL
, /* no special release code */
310 static struct file_operations port_fops
= {
314 NULL
, /* port_readdir */
315 NULL
, /* port_select */
316 NULL
, /* port_ioctl */
317 NULL
, /* port_mmap */
318 NULL
, /* no special open code */
319 NULL
, /* no special release code */
323 static struct file_operations zero_fops
= {
327 NULL
, /* zero_readdir */
328 NULL
, /* zero_select */
329 NULL
, /* zero_ioctl */
331 NULL
, /* no special open code */
332 NULL
/* no special release code */
335 static struct file_operations full_fops
= {
339 NULL
, /* full_readdir */
340 NULL
, /* full_select */
341 NULL
, /* full_ioctl */
342 NULL
, /* full_mmap */
343 NULL
, /* no special open code */
344 NULL
/* no special release code */
347 static int memory_open(struct inode
* inode
, struct file
* filp
)
349 switch (MINOR(inode
->i_rdev
)) {
351 filp
->f_op
= &ram_fops
;
354 filp
->f_op
= &mem_fops
;
357 filp
->f_op
= &kmem_fops
;
360 filp
->f_op
= &null_fops
;
363 filp
->f_op
= &port_fops
;
366 filp
->f_op
= &zero_fops
;
369 filp
->f_op
= &full_fops
;
374 if (filp
->f_op
&& filp
->f_op
->open
)
375 return filp
->f_op
->open(inode
,filp
);
379 static struct file_operations memory_fops
= {
387 memory_open
, /* just a selector for the real open */
393 char* ftape_big_buffer
;
396 long chr_dev_init(long mem_start
, long mem_end
)
398 if (register_chrdev(MEM_MAJOR
,"mem",&memory_fops
))
399 printk("unable to get major %d for memory devs\n", MEM_MAJOR
);
400 mem_start
= tty_init(mem_start
);
401 #ifdef CONFIG_PRINTER
402 mem_start
= lp_init(mem_start
);
404 #if defined (CONFIG_BUSMOUSE) || defined (CONFIG_82C710_MOUSE) || \
405 defined (CONFIG_PSMOUSE) || defined (CONFIG_MS_BUSMOUSE) || \
406 defined (CONFIG_ATIXL_BUSMOUSE)
407 mem_start
= mouse_init(mem_start
);
410 mem_start
= soundcard_init(mem_start
);
412 #if CONFIG_TAPE_QIC02
413 mem_start
= tape_qic02_init(mem_start
);
416 * Rude way to allocate kernel memory buffer for tape device
419 /* allocate NR_FTAPE_BUFFERS 32Kb buffers at aligned address */
420 ftape_big_buffer
= (char*) ((mem_start
+ 0x7fff) & ~0x7fff);
421 printk( "ftape: allocated %d buffers alligned at: %p\n",
422 NR_FTAPE_BUFFERS
, ftape_big_buffer
);
423 mem_start
= (long) ftape_big_buffer
+ NR_FTAPE_BUFFERS
* 0x8000;