SCore-D Device Driver Sample Code

This document describes an example of a SCore-D device program that realizes a simple null device.

Device Server Process

The first part of the device program is a main loop waiting for device open request or device shutdown request. At the very beginning of the main function, the device_initialize() function should be called. Each I/O request has a tag indicating which I/O operation is requested. In this main loop, only IO_MESG_OPEN for device open request and IO_MESG_TERM for device server shutdown request are acceptable.

Upon receiving an IO_MESG_OPEN request, a device server process forks a child process in which actual I/O requests are handled.

#include <score_device.h>

int main( int argc, char **argv ) {
  struct sockaddr	addr;
  pid_t			pid;
  int			addrsize;
  int			fd;
  int			tag;
  int			cell;
  ioarg_t		offset0, offset1;

  if(device_initialize(argc, argv) < 0) device_terminate( 3 );
  device_log("Device Initialized !!");

  while(1) {
    addrsize = sizeof(struct sockaddr);
    if((fd = accept(fd_listen, &addr, &addrsize)) < 0) {
      if(errno == EINTR) continue; /* in case of SIGCHLD */
      device_log("Accept error");
      device_terminate(1);
    }
    set_tcp_nodelay(fd);
    if(read_device_op( &tag, &cell, &offset0, &offset1, fd ) != 0) {
      device_log("Error in read device-op");
      break;
    }
    switch(tag) {
    case IO_MESG_OPEN:
      if((pid = fork()) == 0) { /* if device process */
	null_device(fd);
      } else if (pid > 0) {	/* if device server process */
	if(write_device_ack(fd, NORMAL_END, cell) != 0) {
	  device_log("Error in write device ack");
	}
	close(fd);
      } else {			/* if error in fork() */
	if(write_device_ack( fd, EIO, cell ) != 0) {
	  device_log("Error in write device ack");
	}
	device_log("Cannot fork device process");
      }
      break;
    case IO_MESG_TERM:
      device_log("device shutdown");
      device_terminate(0);
      break;
    default:
      device_log("Unknown I/O message tag (%d) (cell=%d,off=%d,wh=%d)",
		 tag, cell, offset, whence);
      device_terminate(1);
      break;
    }
  }
  return(0);
}

Device Process

In a device process, there can be a loop which is waiting for an I/O request and then processes it. In this example for the null device, a write request (IO_MESG_WRITE) is a no operation, and a read request fills the corresponding I/O cell with zeros.
#include <score_device.h>

void null_device (int fd) {
  int		tag;
  int		cell;
  ioarg_t	offset0, offset1;
  char		pseudo_dev[IO_BUFFER_SIZE];
  char		*iobuf;
  int		length;
  
  while(1) {
    if(read_device_op( &tag, &cell, &offset0, &offset1, fd) != 0) {
      device_log("Error in read device-op");
      device_terminate(1);
    }
    switch(tag) {
    case IO_MESG_WRITE:
      length = get_iocell(cell, &iobuf);
      /* actual write operation here */
      if(write_device_ack(fd, NORMAL_END, cell) != 0) {
	device_log("Error in write device ack");
      }
      break;
    case IO_MESG_READ:
      length = get_iocell(cell, &iobuf);
      bzero(iobuf, length);
      set_iocell_length(cell, length);
      if(write_device_ack(fd, NORMAL_END, cell) != 0) {
	device_log("Error in write device ack");
      }
      break;
    case IO_MESG_CLOSE:
      if(write_device_ack( fd, NORMAL_END, cell) != 0) {
	device_log("Error in write device ack");
      }
      close(fd);
      device_terminate(0);
      break;
    default:
      device_log("Unknown I/O message tag");
      device_terminate(1);
      break;
    }
  }
}

$Id: sample-device.html,v 1.1.1.1 2002/02/12 02:00:13 kameyama Exp $