diff --git a/drivers/memory/memory.c b/drivers/memory/memory.c index 4b57ade42..63ff16c71 100644 --- a/drivers/memory/memory.c +++ b/drivers/memory/memory.c @@ -46,11 +46,14 @@ PRIVATE struct kinfo kinfo; /* kernel information */ extern int errno; /* error number for PM calls */ +PRIVATE int openct[NR_DEVS]; + FORWARD _PROTOTYPE( char *m_name, (void) ); FORWARD _PROTOTYPE( struct device *m_prepare, (int device) ); FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, u64_t position, iovec_t *iov, unsigned nr_req, int safe)); FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) ); +FORWARD _PROTOTYPE( int m_do_close, (struct driver *dp, message *m_ptr) ); FORWARD _PROTOTYPE( void m_init, (void) ); FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr, int safe)); FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) ); @@ -59,7 +62,7 @@ FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) ); PRIVATE struct driver m_dtab = { m_name, /* current device's name */ m_do_open, /* open or mount */ - do_nop, /* nothing on a close */ + m_do_close, /* nothing on a close */ m_ioctl, /* specify ram disk geometry */ m_prepare, /* prepare for I/O on a given minor device */ m_transfer, /* do the I/O */ @@ -307,9 +310,40 @@ message *m_ptr; return r; } } + + if(m_device < 0 || m_device >= NR_DEVS) { + panic("MEM","wrong m_device",m_device); + } + + openct[m_device]++; + return(OK); } +/*===========================================================================* + * m_do_close * + *===========================================================================*/ +PRIVATE int m_do_close(dp, m_ptr) +struct driver *dp; +message *m_ptr; +{ + int r; + + if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO); + + if(m_device < 0 || m_device >= NR_DEVS) { + panic("MEM","wrong m_device",m_device); + } + + if(openct[m_device] < 1) { + panic("MEM","closed too often",NO_NUM); + } + openct[m_device]--; + + return(OK); +} + + /*===========================================================================* * m_init * *===========================================================================*/ @@ -343,6 +377,9 @@ PRIVATE void m_init() dev_zero[i] = '\0'; } + for(i = 0; i < NR_DEVS; i++) + openct[i] = 0; + /* Set up memory range for /dev/mem. */ m_geom[MEM_DEV].dv_base = cvul64(0); m_geom[MEM_DEV].dv_size = cvul64(0xffffffff); @@ -393,9 +430,20 @@ int safe; if(m_vaddrs[dev] && !cmp64(dv->dv_size, cvul64(ramdev_size))) { return(OK); } + /* openct is 1 for the ioctl(). */ + if(openct[dev] != 1) { + printf("MEM: MIOCRAMSIZE: %d in use (count %d)\n", + dev, openct[dev]); + return(EBUSY); + } if(m_vaddrs[dev]) { - printf("MEM: MIOCRAMSIZE: %d already has a ramdisk\n", dev); - return(EPERM); + u32_t size; + if(ex64hi(dv->dv_size)) { + panic("MEM","huge old ramdisk", NO_NUM); + } + size = ex64lo(dv->dv_size); + munmap((void *) m_vaddrs[dev], size); + m_vaddrs[dev] = (vir_bytes) NULL; } #if DEBUG