~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Minix Cross Reference
Minix/kernel/memory.c


  1 /* This file contains the device dependent part of the drivers for the
  2  * following special files:
  3  *     /dev/null        - null device (data sink)
  4  *     /dev/mem         - absolute memory
  5  *     /dev/kmem        - kernel virtual memory
  6  *     /dev/ram         - RAM disk
  7  *
  8  * The file contains one entry point:
  9  *
 10  *   mem_task:  main entry when system is brought up
 11  *
 12  *  Changes:
 13  *      20 Apr  1992 by Kees J. Bot: device dependent/independent split
 14  */
 15 
 16 #include "kernel.h"
 17 #include "driver.h"
 18 #include <sys/ioctl.h>
 19 
 20 #define NR_RAMS            4    /* number of RAM-type devices */
 21 
 22 PRIVATE struct device m_geom[NR_RAMS];  /* Base and size of each RAM disk */
 23 PRIVATE int m_device;           /* current device */
 24 
 25 FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
 26 FORWARD _PROTOTYPE( int m_schedule, (int proc_nr, struct iorequest_s *iop) );
 27 FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) );
 28 FORWARD _PROTOTYPE( void m_init, (void) );
 29 FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) );
 30 FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
 31 
 32 
 33 /* Entry points to this driver. */
 34 PRIVATE struct driver m_dtab = {
 35   no_name,      /* current device's name */
 36   m_do_open,    /* open or mount */
 37   do_nop,       /* nothing on a close */
 38   m_ioctl,      /* specify ram disk geometry */
 39   m_prepare,    /* prepare for I/O on a given minor device */
 40   m_schedule,   /* do the I/O */
 41   nop_finish,   /* schedule does the work, no need to be smart */
 42   nop_cleanup,  /* nothing's dirty */
 43   m_geometry,   /* memory device "geometry" */
 44 };
 45 
 46 
 47 /*===========================================================================*
 48  *                              mem_task                                     *
 49  *===========================================================================*/
 50 PUBLIC void mem_task()
 51 {
 52   m_init();
 53   driver_task(&m_dtab);
 54 }
 55 
 56 
 57 /*===========================================================================*
 58  *                              m_prepare                                    *
 59  *===========================================================================*/
 60 PRIVATE struct device *m_prepare(device)
 61 int device;
 62 {
 63 /* Prepare for I/O on a device. */
 64 
 65   if (device < 0 || device >= NR_RAMS) return(NIL_DEV);
 66   m_device = device;
 67 
 68   return(&m_geom[device]);
 69 }
 70 
 71 
 72 /*===========================================================================*
 73  *                              m_schedule                                   *
 74  *===========================================================================*/
 75 PRIVATE int m_schedule(proc_nr, iop)
 76 int proc_nr;                    /* process doing the request */
 77 struct iorequest_s *iop;        /* pointer to read or write request */
 78 {
 79 /* Read or write /dev/null, /dev/mem, /dev/kmem, or /dev/ram. */
 80 
 81   int device, count, opcode;
 82   phys_bytes mem_phys, user_phys;
 83   struct device *dv;
 84 
 85   /* Type of request */
 86   opcode = iop->io_request & ~OPTIONAL_IO;
 87 
 88   /* Get minor device number and check for /dev/null. */
 89   device = m_device;
 90   dv = &m_geom[device];
 91 
 92   /* Determine address where data is to go or to come from. */
 93   user_phys = numap(proc_nr, (vir_bytes) iop->io_buf,
 94                                                 (vir_bytes) iop->io_nbytes);
 95   if (user_phys == 0) return(iop->io_nbytes = EINVAL);
 96 
 97   if (device == NULL_DEV) {
 98         /* /dev/null: Black hole. */
 99         if (opcode == DEV_WRITE) iop->io_nbytes = 0;
100         count = 0;
101   } else {
102         /* /dev/mem, /dev/kmem, or /dev/ram: Check for EOF */
103         if (iop->io_position >= dv->dv_size) return(OK);
104         count = iop->io_nbytes;
105         if (iop->io_position + count > dv->dv_size)
106                 count = dv->dv_size - iop->io_position;
107   }
108 
109   /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram */
110   mem_phys = dv->dv_base + iop->io_position;
111 
112   /* Book the number of bytes to be transferred in advance. */
113   iop->io_nbytes -= count;
114 
115   if (count == 0) return(OK);
116 
117   /* Copy the data. */
118   if (opcode == DEV_READ)
119         phys_copy(mem_phys, user_phys, (phys_bytes) count);
120   else
121         phys_copy(user_phys, mem_phys, (phys_bytes) count);
122 
123   return(OK);
124 }
125 
126 
127 /*============================================================================*
128  *                              m_do_open                                     *
129  *============================================================================*/
130 PRIVATE int m_do_open(dp, m_ptr)
131 struct driver *dp;
132 message *m_ptr;
133 {
134 /* Check device number on open.  Give I/O privileges to a process opening
135  * /dev/mem or /dev/kmem.
136  */
137 
138   if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
139 
140 #if (CHIP == INTEL)
141   if (m_device == MEM_DEV || m_device == KMEM_DEV)
142         enable_iop(proc_addr(m_ptr->PROC_NR));
143 #endif
144 
145   return(OK);
146 }
147 
148 
149 /*===========================================================================*
150  *                              m_init                                       *
151  *===========================================================================*/
152 PRIVATE void m_init()
153 {
154 #if (MACHINE != SUN)
155   /* Initialize this task. */
156   extern int _end;
157 
158   m_geom[KMEM_DEV].dv_base = vir2phys(0);
159   m_geom[KMEM_DEV].dv_size = vir2phys(&_end);
160 #else  
161   /*
162    * In smx, the kernel memory is regarded as beginning at 0 and
163    * extending to the end of the kernel data segment, even though
164    * a large area (from 0 to the start of the kernel text segment) lies
165    * outside the kernrel.  This way of doing this does have the advantage,
166    * however, that addresses of kernel variables can be used directly
167    * as offsets into /dev/kmem when extracting data from the kernel.
168    * A similar approach is used for /dev/mem.
169    */
170   struct proc *rp = BEG_PROC_ADDR;
171 
172   m_geom[KMEM_DEV].dv_base = 0;
173   m_geom[KMEM_DEV].dv_size = code_base + (rp->p_map[T].mem_len << CLICK_SHIFT)
174       + (rp->p_map[D].mem_len << CLICK_SHIFT);
175 #endif
176 
177 #if (CHIP == INTEL)
178   if (!protected_mode) {
179         m_geom[MEM_DEV].dv_size =   0x100000;   /* 1M for 8086 systems */
180   } else {
181 #if _WORD_SIZE == 2
182         m_geom[MEM_DEV].dv_size =  0x1000000;   /* 16M for 286 systems */
183 #else
184         m_geom[MEM_DEV].dv_size = 0xFFFFFFFF;   /* 4G-1 for 386 systems */
185 #endif
186   }
187 #else /* !(CHIP == INTEL) */
188 # if (MACHINE == SUN)
189   m_geom[MEM_DEV].dv_base = 0;   /* See KMEM_DEV comment */
190   m_geom[MEM_DEV].dv_size = code_base + (tot_mem_size << CLICK_SHIFT);
191 # else
192 #  if (CHIP == M68000)
193   m_geom[MEM_DEV].dv_size = MEM_BYTES;
194 #  else /* !(CHIP == M68000) */
195 #   error /* memory limit not set up */
196 #  endif /* !(CHIP == M68000) */
197 # endif
198 #endif /* !(CHIP == INTEL) */
199 }
200 
201 
202 /*===========================================================================*
203  *                              m_ioctl                                      *
204  *===========================================================================*/
205 PRIVATE int m_ioctl(dp, m_ptr)
206 struct driver *dp;
207 message *m_ptr;                 /* pointer to read or write message */
208 {
209 /* Set parameters for one of the RAM disks. */
210 
211   unsigned long bytesize;
212   unsigned base, size;
213   struct memory *memp;
214   static struct psinfo psinfo = { NR_TASKS, NR_PROCS, (vir_bytes) proc, 0, 0 };
215   phys_bytes psinfo_phys;
216 
217   switch (m_ptr->REQUEST) {
218   case MIOCRAMSIZE:
219         /* FS sets the RAM disk size. */
220         if (m_ptr->PROC_NR != FS_PROC_NR) return(EPERM);
221 
222         bytesize = m_ptr->POSITION * BLOCK_SIZE;
223         size = (bytesize + CLICK_SHIFT-1) >> CLICK_SHIFT;
224 
225         /* Find a memory chunk big enough for the RAM disk. */
226         memp= &mem[NR_MEMS];
227         while ((--memp)->size < size) {
228                 if (memp == mem) panic("RAM disk is too big", NO_NUM);
229         }
230         base = memp->base;
231         memp->base += size;
232         memp->size -= size;
233 
234         m_geom[RAM_DEV].dv_base = (unsigned long) base << CLICK_SHIFT;
235         m_geom[RAM_DEV].dv_size = bytesize;
236         break;
237   case MIOCSPSINFO:
238         /* MM or FS set the address of their process table. */
239         if (m_ptr->PROC_NR == MM_PROC_NR) {
240 #if (MACHINE == SUN)
241                 /*
242                  * Store physical address for Suns---see comment on
243                  * initialising m_geom[KMEM_DEV] and [MEM_DEV]as to why.
244                  */
245                 psinfo.mproc = numap(m_ptr->PROC_NR,
246                                      (vir_bytes) m_ptr->ADDRESS, 1);
247 #else
248                 psinfo.mproc = (vir_bytes) m_ptr->ADDRESS;
249 #endif
250         } else
251         if (m_ptr->PROC_NR == FS_PROC_NR) {
252 #if (MACHINE == SUN)
253                 psinfo.fproc = numap(m_ptr->PROC_NR,
254                                      (vir_bytes) m_ptr->ADDRESS, 1);
255 #else
256                 psinfo.fproc = (vir_bytes) m_ptr->ADDRESS;
257 #endif
258         } else {
259                 return(EPERM);
260         }
261         break;
262   case MIOCGPSINFO:
263         /* The ps program wants the process table addresses. */
264         psinfo_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
265                                                         sizeof(psinfo));
266         if (psinfo_phys == 0) return(EFAULT);
267         phys_copy(vir2phys(&psinfo), psinfo_phys, (phys_bytes) sizeof(psinfo));
268         break;
269   default:
270         return(do_diocntl(&m_dtab, m_ptr));
271   }
272   return(OK);
273 }
274 
275 
276 /*============================================================================*
277  *                              m_geometry                                    *
278  *============================================================================*/
279 PRIVATE void m_geometry(entry)
280 struct partition *entry;
281 {
282   /* Memory devices don't have a geometry, but the outside world insists. */
283   entry->cylinders = (m_geom[m_device].dv_size >> SECTOR_SHIFT) / (64 * 32);
284   entry->heads = 64;
285   entry->sectors = 32;
286 }
287 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.