Skip to content

Instantly share code, notes, and snippets.

@mhansen
Created October 22, 2009 22:53
Show Gist options
  • Select an option

  • Save mhansen/216427 to your computer and use it in GitHub Desktop.

Select an option

Save mhansen/216427 to your computer and use it in GitHub Desktop.
#include "../drivers.h"
#include "../libdriver/driver.h"
#include "proc.h"
extern int errno; /* error number for PM calls */
PRIVATE int p_device; /* current device */
FORWARD _PROTOTYPE( char *p_name, (void) );
FORWARD _PROTOTYPE( struct device *p_prepare, (int device) );
FORWARD _PROTOTYPE( int p_transfer, (int proc_nr, int opcode, u64_t position,
iovec_t *iov, unsigned nr_req, int safe));
FORWARD _PROTOTYPE( int p_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void p_geometry, (struct partition *entry) );
/* Entry points to this driver. */
PRIVATE struct driver p_dtab = {
p_name, /* current device's name */
p_do_open, /* open or mount */
do_nop, /* nothing on a close */
nop_ioctl, /* no ioctl */
p_prepare, /* prepare for I/O on a given minor device */
p_transfer, /* do the I/O */
nop_cleanup, /* no need to clean up */
p_geometry, /* memory device "geometry" */
nop_signal, /* system signals */
nop_alarm,
nop_cancel,
nop_select,
NULL,
NULL
};
/* There is no physical device here, so return a dummy device when asked */
PRIVATE struct device dummy_dev;
#define PROC_BUFSIZE 8192 /* size in bytes of the largest file expected */
PRIVATE char proc_buffer[PROC_BUFSIZE];
/* call vector table - defined in proto.h */
extern void (*pr_vec[NR_DEVS]) (char *buffer, int bufSize);
/******************************************************************************/
/* p_transfer : This is where the main action of the driver happens */
/******************************************************************************/
PRIVATE int p_transfer(proc_nr, opcode, pos64, iov, nr_req, safe)
int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER_S or DEV_SCATTER_S */
u64_t pos64; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
int safe; /* safe copies */
{
/* Read or write one the driver's minor devices. */
unsigned bytes_asked_for, bytes_to_copy;
vir_bytes user_vir, vir_offset = 0;
int s, file_length;
off_t file_position;
if(!safe) {
printf("m_transfer: unsafe?\n");
return EPERM;
}
file_position= cv64ul(pos64);
while (nr_req > 0) {
/* How much to transfer and where to / from. */
bytes_asked_for = iov->iov_size;
user_vir = iov->iov_addr;
/* only service read requests */
if (opcode == DEV_GATHER_S) {
/* Fill proc_buffer with file-specific data to return.
Delegate to a different function for each device */
pr_vec[p_device](proc_buffer, PROC_BUFSIZE);
/* we have the data, now copy just as much
as was asked for, or as much as we have */
file_length = strlen(proc_buffer);
if (file_position >= file_length) return OK; /* At EOF */
if (file_position + bytes_asked_for > file_length)
bytes_to_copy = file_length - file_position;
else bytes_to_copy = bytes_asked_for;
s = sys_safecopyto(proc_nr, user_vir, vir_offset,
(vir_bytes) proc_buffer, bytes_to_copy, D);
if (s != OK) report ("PROC", "sys_safecopyto failed", s);
/* Book the number of bytes transferred. */
file_position += bytes_to_copy;
vir_offset += bytes_to_copy;
iov->iov_size -= bytes_to_copy;
}
if (iov->iov_size == 0 || /* this request is finished */
opcode == DEV_SCATTER_S) { /* this is a write request */
iov++; nr_req--; vir_offset = 0; /* move on to the next request */
}
}
return(OK);
}
/*===========================================================================*
* main *
*===========================================================================*/
PUBLIC int main(void)
{
/* Main program. Initialize the proc driver and start the main loop. */
struct sigaction sa;
sa.sa_handler = SIG_MESS;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGTERM,&sa,NULL)<0) panic("PROC","sigaction failed", errno);
driver_task(&p_dtab);
return(OK);
}
/*===========================================================================*
* p_name *
*===========================================================================*/
PRIVATE char *p_name()
{
/* Return a name for the current device. */
static char name[] = "proc";
return name;
}
/*===========================================================================*
* p_prepare *
*===========================================================================*/
PRIVATE struct device *p_prepare(device)
int device;
{
/* Prepare for I/O on a device: check if the minor device number is ok. */
if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
p_device = device;
return(&dummy_dev);
}
/*===========================================================================*
* p_do_open *
*===========================================================================*/
PRIVATE int p_do_open(dp, m_ptr)
struct driver *dp;
message *m_ptr;
{
/* Check device number on open. */
if (p_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
return(OK);
}
/*===========================================================================*
* p_geometry *
*===========================================================================*/
PRIVATE void p_geometry(entry)
struct partition *entry;
{
/* /proc doesn't have a geometry, but the outside world insists. */
entry->cylinders = div64u(dummy_dev.dv_size, SECTOR_SIZE) / (64 * 32);
entry->heads = 64;
entry->sectors = 32;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment