📄 memory.c
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/kernel/memory.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
09700 /* This file contains the device dependent part of the drivers for the
09701 * following special files:
09702 * /dev/null - null device (data sink)
09703 * /dev/mem - absolute memory
09704 * /dev/kmem - kernel virtual memory
09705 * /dev/ram - RAM disk
09706 *
09707 * The file contains one entry point:
09708 *
09709 * mem_task: main entry when system is brought up
09710 *
09711 * Changes:
09712 * 20 Apr 1992 by Kees J. Bot: device dependent/independent split
09713 */
09714
09715 #include "kernel.h"
09716 #include "driver.h"
09717 #include <sys/ioctl.h>
09718
09719 #define NR_RAMS 4 /* number of RAM-type devices */
09720
09721 PRIVATE struct device m_geom[NR_RAMS]; /* Base and size of each RAM disk */
09722 PRIVATE int m_device; /* current device */
09723
09724 FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
09725 FORWARD _PROTOTYPE( int m_schedule, (int proc_nr, struct iorequest_s *iop) );
09726 FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) );
09727 FORWARD _PROTOTYPE( void m_init, (void) );
09728 FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) );
09729 FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
09730
09731
09732 /* Entry points to this driver. */
09733 PRIVATE struct driver m_dtab = {
09734 no_name, /* current device's name */
09735 m_do_open, /* open or mount */
09736 do_nop, /* nothing on a close */
09737 m_ioctl, /* specify ram disk geometry */
09738 m_prepare, /* prepare for I/O on a given minor device */
09739 m_schedule, /* do the I/O */
09740 nop_finish, /* schedule does the work, no need to be smart */
09741 nop_cleanup, /* nothing's dirty */
09742 m_geometry, /* memory device "geometry" */
09743 };
09744
09745
09746 /*===========================================================================*
09747 * mem_task *
09748 *===========================================================================*/
09749 PUBLIC void mem_task()
09750 {
09751 m_init();
09752 driver_task(&m_dtab);
09753 }
09756 /*===========================================================================*
09757 * m_prepare *
09758 *===========================================================================*/
09759 PRIVATE struct device *m_prepare(device)
09760 int device;
09761 {
09762 /* Prepare for I/O on a device. */
09763
09764 if (device < 0 || device >= NR_RAMS) return(NIL_DEV);
09765 m_device = device;
09766
09767 return(&m_geom[device]);
09768 }
09771 /*===========================================================================*
09772 * m_schedule *
09773 *===========================================================================*/
09774 PRIVATE int m_schedule(proc_nr, iop)
09775 int proc_nr; /* process doing the request */
09776 struct iorequest_s *iop; /* pointer to read or write request */
09777 {
09778 /* Read or write /dev/null, /dev/mem, /dev/kmem, or /dev/ram. */
09779
09780 int device, count, opcode;
09781 phys_bytes mem_phys, user_phys;
09782 struct device *dv;
09783
09784 /* Type of request */
09785 opcode = iop->io_request & ~OPTIONAL_IO;
09786
09787 /* Get minor device number and check for /dev/null. */
09788 device = m_device;
09789 dv = &m_geom[device];
09790
09791 /* Determine address where data is to go or to come from. */
09792 user_phys = numap(proc_nr, (vir_bytes) iop->io_buf,
09793 (vir_bytes) iop->io_nbytes);
09794 if (user_phys == 0) return(iop->io_nbytes = EINVAL);
09795
09796 if (device == NULL_DEV) {
09797 /* /dev/null: Black hole. */
09798 if (opcode == DEV_WRITE) iop->io_nbytes = 0;
09799 count = 0;
09800 } else {
09801 /* /dev/mem, /dev/kmem, or /dev/ram: Check for EOF */
09802 if (iop->io_position >= dv->dv_size) return(OK);
09803 count = iop->io_nbytes;
09804 if (iop->io_position + count > dv->dv_size)
09805 count = dv->dv_size - iop->io_position;
09806 }
09807
09808 /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram */
09809 mem_phys = dv->dv_base + iop->io_position;
09810
09811 /* Book the number of bytes to be transferred in advance. */
09812 iop->io_nbytes -= count;
09813
09814 if (count == 0) return(OK);
09815
09816 /* Copy the data. */
09817 if (opcode == DEV_READ)
09818 phys_copy(mem_phys, user_phys, (phys_bytes) count);
09819 else
09820 phys_copy(user_phys, mem_phys, (phys_bytes) count);
09821
09822 return(OK);
09823 }
09826 /*============================================================================*
09827 * m_do_open *
09828 *============================================================================*/
09829 PRIVATE int m_do_open(dp, m_ptr)
09830 struct driver *dp;
09831 message *m_ptr;
09832 {
09833 /* Check device number on open. Give I/O privileges to a process opening
09834 * /dev/mem or /dev/kmem.
09835 */
09836
09837 if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
09838
09839 if (m_device == MEM_DEV || m_device == KMEM_DEV)
09840 enable_iop(proc_addr(m_ptr->PROC_NR));
09841
09842 return(OK);
09843 }
09846 /*===========================================================================*
09847 * m_init *
09848 *===========================================================================*/
09849 PRIVATE void m_init()
09850 {
09851 /* Initialize this task. */
09852 extern int _end;
09853
09854 m_geom[KMEM_DEV].dv_base = vir2phys(0);
09855 m_geom[KMEM_DEV].dv_size = vir2phys(&_end);
09856
09857 #if (CHIP == INTEL)
09858 if (!protected_mode) {
09859 m_geom[MEM_DEV].dv_size = 0x100000; /* 1M for 8086 systems */
09860 } else {
09861 #if _WORD_SIZE == 2
09862 m_geom[MEM_DEV].dv_size = 0x1000000; /* 16M for 286 systems */
09863 #else
09864 m_geom[MEM_DEV].dv_size = 0xFFFFFFFF; /* 4G-1 for 386 systems */
09865 #endif
09866 }
09867 #endif
09868 }
09871 /*===========================================================================*
09872 * m_ioctl *
09873 *===========================================================================*/
09874 PRIVATE int m_ioctl(dp, m_ptr)
09875 struct driver *dp;
09876 message *m_ptr; /* pointer to read or write message */
09877 {
09878 /* Set parameters for one of the RAM disks. */
09879
09880 unsigned long bytesize;
09881 unsigned base, size;
09882 struct memory *memp;
09883 static struct psinfo psinfo = { NR_TASKS, NR_PROCS, (vir_bytes) proc, 0, 0 };
09884 phys_bytes psinfo_phys;
09885
09886 switch (m_ptr->REQUEST) {
09887 case MIOCRAMSIZE:
09888 /* FS sets the RAM disk size. */
09889 if (m_ptr->PROC_NR != FS_PROC_NR) return(EPERM);
09890
09891 bytesize = m_ptr->POSITION * BLOCK_SIZE;
09892 size = (bytesize + CLICK_SHIFT-1) >> CLICK_SHIFT;
09893
09894 /* Find a memory chunk big enough for the RAM disk. */
09895 memp= &mem[NR_MEMS];
09896 while ((--memp)->size < size) {
09897 if (memp == mem) panic("RAM disk is too big", NO_NUM);
09898 }
09899 base = memp->base;
09900 memp->base += size;
09901 memp->size -= size;
09902
09903 m_geom[RAM_DEV].dv_base = (unsigned long) base << CLICK_SHIFT;
09904 m_geom[RAM_DEV].dv_size = bytesize;
09905 break;
09906 case MIOCSPSINFO:
09907 /* MM or FS set the address of their process table. */
09908 if (m_ptr->PROC_NR == MM_PROC_NR) {
09909 psinfo.mproc = (vir_bytes) m_ptr->ADDRESS;
09910 } else
09911 if (m_ptr->PROC_NR == FS_PROC_NR) {
09912 psinfo.fproc = (vir_bytes) m_ptr->ADDRESS;
09913 } else {
09914 return(EPERM);
09915 }
09916 break;
09917 case MIOCGPSINFO:
09918 /* The ps program wants the process table addresses. */
09919 psinfo_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
09920 sizeof(psinfo));
09921 if (psinfo_phys == 0) return(EFAULT);
09922 phys_copy(vir2phys(&psinfo), psinfo_phys, (phys_bytes) sizeof(psinfo));
09923 break;
09924 default:
09925 return(do_diocntl(&m_dtab, m_ptr));
09926 }
09927 return(OK);
09928 }
09931 /*============================================================================*
09932 * m_geometry *
09933 *============================================================================*/
09934 PRIVATE void m_geometry(entry)
09935 struct partition *entry;
09936 {
09937 /* Memory devices don't have a geometry, but the outside world insists. */
09938 entry->cylinders = (m_geom[m_device].dv_size >> SECTOR_SHIFT) / (64 * 32);
09939 entry->heads = 64;
09940 entry->sectors = 32;
09941 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -