このデバイスドライバは下記のUSB関連機器を操作するためのものです。
- USB-SCSIアダプタ: Logitec LUB-SC
- CAMACコントローラ: Kinetic Model 3929
- VMEコントローラのKEK製(佐藤モジュール)
また、使用したPC/Linuxは下記の通りです。
- OS : Linux2.4.0
- コンパイラ:egcs-1.1.2 release
このドライバはKEKの
仲吉さん
と
佐藤さん
のドライバを基に
スキャナーのドライバ(/usr/src/linux/drivers/usb/scanner.c)を
参考にして作成されました。
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/malloc.h>
#include <linux/smp_lock.h>
//#define DEBUG
#include <linux/usb.h>
MODULE_AUTHOR("Y.Yasu, Yoshiji.YASU@kek.jp, http://www-online.kek.jp/~yasu/");
MODULE_DESCRIPTION("USB VME and CAMAC device driver");
#define IS_EP_BULK(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOI
NT_DIR_MASK) == USB_DIR_IN)
#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPO
INT_DIR_MASK) == USB_DIR_OUT)
#define IOCTL_LOAD_CDB _IOW('u', 0, int)
#define IOCTL_LOAD_SCSI_ID _IOW('u', 1, int)
#define VMECAM_MAX_MNR 16 /* We're allocated 16 minors */
#define VMECAM_BASE_MNR 128 /* USB VMECAM start at minor 128 */
#define MAX_CDB 20
#define USB_VMECAM_MINOR(X) MINOR((X)->i_rdev) - VMECAM_BASE_MNR
struct vmecam_usb_data {
struct usb_device *vmecam_dev;
unsigned int ifnum; /* Interface number of the USB device */
kdev_t vmecam_minor; /* VMECAM minor - used in disconnect() */
int scsi_id; /* SCSI ID */
char isopen; /* Not zero if the device is open */
char present; /* Not zero if device is present */
char *buf; /* transfer buffers */
unsigned int bulk_in_ep, bulk_out_ep, intr_ep; /* Endpoint assignments */
wait_queue_head_t wait_q; /* read timeouts */
struct semaphore gen_lock; /* lock to prevent concurrent reads or writes */
};
static struct vmecam_usb_data *p_vmecam_table[VMECAM_MAX_MNR] = { NULL, };
static struct usb_driver vmecam_driver;
static struct usb_device_id vmecam_device_ids [] = {
{ USB_DEVICE(0x789, 0x4) }, /* LOGITEC */
{ } /* Terminating entry */
};
int send_scsi_id_by_dev( struct usb_device *dev, int id)
{
unsigned int pipe;
__u8 requesttype = 0x40;
__u8 request = 0x05;
__u16 value = 0x0107;
__u16 index = 0x0000;
__u16 size = 0;
int timeout = 3*HZ; /* 5sec */
int r;
pipe = usb_rcvctrlpipe(dev, 0);
dbg("send_scsi_id id=%d", id);
value = ( id << 8 ) | 7;
r = usb_control_msg(dev, pipe, request, requesttype, value,
index, NULL, size, timeout);
if( r != 0 ) {
err("send_scsi_id ERR=%d", r);
return -1;
}
return 0;
}
int send_cdb(struct file *file, unsigned char *cdb, unsigned short size)
{
struct usb_device *dev;
unsigned int pipe;
__u8 requesttype = 0x21;
__u8 request = 0x00;
__u16 value = 0x0000;
__u16 index = 0x0000;
int timeout = 10*HZ; /* 5sec */
int result;
dev = ((struct vmecam_usb_data *)(file->private_data))->vmecam_dev;
pipe = usb_sndctrlpipe(dev, 0);
result = usb_control_msg(dev, pipe, request, requesttype,
value, index, cdb, size, timeout);
dbg("send_cdb: cdb[0]:%x cdb[1]:%x cdb[2]:%x cdb[3]:%x cdb[4]:%x cdb[5]:%x", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5]);
if( result >= 0 ){
return 0;
}
if( result == -EPIPE )
usb_clear_halt(dev, pipe);
return result;
}
static int
open_vmecam(struct inode * inode, struct file * file)
{
struct vmecam_usb_data *vmecam;
struct usb_device *dev;
kdev_t vmecam_minor;
int err=0;
lock_kernel();
vmecam_minor = USB_VMECAM_MINOR(inode);
dbg("open_vmecam: vmecam_minor:%d", vmecam_minor);
if (!p_vmecam_table[vmecam_minor]) {
err("open_vmecam(%d): Unable to access minor data", vmecam_minor);
err = -ENODEV;
goto out_error;
}
vmecam = p_vmecam_table[vmecam_minor];
dev = vmecam->vmecam_dev;
if (!dev) {
err("open_vmecam(%d): Vmecam device not present", vmecam_minor);
err = -ENODEV;
goto out_error;
}
if (!vmecam->present) {
err("open_vmecam(%d): Vmecam is not present", vmecam_minor);
err = -ENODEV;
goto out_error;
}
if (vmecam->isopen) {
err("open_vmecam(%d): Vmecam device is already open", vmecam_minor);
err = -EBUSY;
goto out_error;
}
init_waitqueue_head(&vmecam->wait_q);
vmecam->isopen = 1;
file->private_data = vmecam; /* Used by the read and write metheds */
MOD_INC_USE_COUNT;
out_error:
unlock_kernel();
return err;
}
static int
close_vmecam(struct inode * inode, struct file * file)
{
struct vmecam_usb_data *vmecam;
kdev_t vmecam_minor;
vmecam_minor = USB_VMECAM_MINOR (inode);
dbg("close_vmecam: vmecam_minor:%d", vmecam_minor);
if (!p_vmecam_table[vmecam_minor]) {
err("close_vmecam(%d): invalid vmecam_minor", vmecam_minor);
return -ENODEV;
}
vmecam = p_vmecam_table[vmecam_minor];
vmecam->isopen = 0;
file->private_data = NULL;
MOD_DEC_USE_COUNT;
return 0;
}
static int
ioctl_vmecam(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct vmecam_usb_data *vmecam;
struct usb_device *dev;
int result;
kdev_t vmecam_minor;
int cdb_buf_len;
unsigned char cdb_buf[MAX_CDB];
int scsi_id;
vmecam_minor = USB_VMECAM_MINOR(inode);
if (!p_vmecam_table[vmecam_minor]) {
err("ioctl_vmecam(%d): invalid vmecam_minor", vmecam_minor);
return -ENODEV;
}
vmecam = p_vmecam_table[vmecam_minor];
dev = vmecam->vmecam_dev;
switch (cmd)
{
case IOCTL_LOAD_CDB :
if(copy_from_user(&cdb_buf_len, (void *)arg, sizeof(int)))
return -EFAULT;
if(copy_from_user(cdb_buf, (void *)(arg+4), cdb_buf_len))
return -EFAULT;
result = send_cdb(file, cdb_buf, cdb_buf_len);
break;
case IOCTL_LOAD_SCSI_ID :
if(copy_from_user(&scsi_id, (void *)arg, sizeof(int)))
return -EFAULT;
if( (result = send_scsi_id_by_dev(dev, scsi_id) ) != 0 )
break;
vmecam->scsi_id = scsi_id;
break;
default :
result = -ENOIOCTLCMD;
}
return result;
}
ssize_t
read_write( int direction, struct file * file, char * buffer, size_t count)
{
struct vmecam_usb_data *vmecam;
struct usb_device *dev;
ssize_t actual;
kdev_t vmecam_minor;
unsigned int pipe;
int result = 0;
ssize_t ret = 0;
vmecam = file->private_data;
vmecam_minor = vmecam->vmecam_minor;
dev = vmecam->vmecam_dev;
down(&(vmecam->gen_lock));
if (signal_pending(current)) {
ret = -EINTR;
goto read_write_end;
}
if (!(vmecam->buf = (char *)kmalloc(count, GFP_KERNEL))) {
err("vmecam: read_write: Out of memory.");
ret = -EFAULT;
goto read_write_end;
}
if( direction ) { // write
if (copy_from_user(vmecam->buf, buffer, count)) {
ret = -EFAULT;
goto read_write_end1;
}
pipe = usb_sndbulkpipe(dev, vmecam->bulk_out_ep);
result = usb_bulk_msg(dev,pipe,
vmecam->buf, count, &actual, 10*HZ);
dbg("write stats(%d): result:%d count:%d actual:%d", vmecam_minor, result, count, actual);
} else { // read
pipe = usb_rcvbulkpipe(dev, vmecam->bulk_in_ep);
result = usb_bulk_msg(dev, pipe,
vmecam->buf, count, &actual, 10*HZ);
dbg("read stats(%d): result:%d count:%d actual:%d", vmecam_minor, result, count, actual);
}
if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */
warn("vmecam: read_write: NAK recieved.");
ret = -ETIME;
goto read_write_end1;
} else if (result < 0) { /* We should not get any I/O errors */
warn("vmecam: read_write(%d): funky result: %d. Please notify the maintainer
.", vmecam_minor, result);
ret = -EIO;
goto read_write_end1;
}
if( !direction ) { // read
if( copy_to_user(buffer, vmecam->buf, actual) ) {
ret = -EFAULT;
goto read_write_end1;
}
}
read_write_end1:
kfree(vmecam->buf);
read_write_end:
up(&(vmecam->gen_lock));
if( ret )
return ret;
else
return actual;
}
static ssize_t
write_vmecam(struct file * file, const char * buffer,
size_t count, loff_t *ppos)
{
int direction = 1;
return read_write(direction, file, (char *)buffer, count);
}
static ssize_t
read_vmecam(struct file * file, char * buffer,
size_t count, loff_t *ppos)
{
int direction = 0;
return read_write(direction, file, buffer, count);
}
static void *
probe_vmecam(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
struct vmecam_usb_data *vmecam;
struct usb_interface_descriptor *interface;
struct usb_endpoint_descriptor *endpoint;
int ep_cnt;
kdev_t vmecam_minor;
char valid_device = 0;
unsigned int have_bulk_in, have_bulk_out;
int ix;
/*
* 1. Check Vendor/Product
* 2. Determine/Assign Bulk Endpoints
*/
for (ix=0; ixdescriptor.idVendor == vmecam_device_ids [ix].idVendor) &&
(dev->descriptor.idProduct == vmecam_device_ids [ix].idProduct)) {
valid_device = 1;
break;
}
}
if (!valid_device)
return NULL; /* We didn't find anything pleasing */
if (dev->descriptor.bNumConfigurations != 1) {
info("probe_vmecam: Only one device configuration is supported.");
return NULL;
}
if (dev->config[0].bNumInterfaces != 1) {
info("probe_vmecam: Only one device interface is supported.");
return NULL;
}
interface = dev->config[0].interface[ifnum].altsetting;
endpoint = interface[ifnum].endpoint;
dbg("probe_vmecam: Number of Endpoints:%d", (int) interface->bNumEndpoints);
if ((interface->bNumEndpoints != 2)) {
info("probe_vmecam: Only two endpoints supported.");
return NULL;
}
ep_cnt = have_bulk_in = have_bulk_out = 0;
while (ep_cnt < interface->bNumEndpoints) {
if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_cnt])) {
have_bulk_in = endpoint[ep_cnt].bEndpointAddress;
dbg("probe_vmecam: bulk_in_ep:%d", have_bulk_in);
ep_cnt++;
continue;
}
if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
have_bulk_out = endpoint[ep_cnt].bEndpointAddress;
dbg("probe_vmecam: bulk_out_ep:%d", have_bulk_out);
ep_cnt++;
continue;
}
info("probe_vmecam: Undetected endpoint. Notify the maintainer.");
return NULL; /* Shouldn't ever get here unless we have something weird */
}
for (vmecam_minor = 0; vmecam_minor < VMECAM_MAX_MNR; vmecam_minor++) {
if (!p_vmecam_table[vmecam_minor])
break;
}
/* Check to make sure that the last slot isn't already taken */
if (p_vmecam_table[vmecam_minor]) {
err("probe_vmecam: No more minor devices remaining.");
return NULL;
}
if (!(vmecam = kmalloc (sizeof (struct vmecam_usb_data), GFP_KERNEL))) {
err("probe_vmecam: Out of memory.");
return NULL;
}
memset (vmecam, 0, sizeof(struct vmecam_usb_data));
dbg ("probe_vmecam(%d): Address of vmecam:%p", vmecam_minor, vmecam);
vmecam->bulk_in_ep = have_bulk_in;
vmecam->bulk_out_ep = have_bulk_out;
vmecam->present = 1;
vmecam->vmecam_dev = dev;
vmecam->vmecam_minor = vmecam_minor;
vmecam->isopen = 0;
init_MUTEX(&(vmecam->gen_lock));
return p_vmecam_table[vmecam_minor] = vmecam;
}
static void
disconnect_vmecam(struct usb_device *dev, void *ptr)
{
struct vmecam_usb_data *vmecam = (struct vmecam_usb_data *) ptr;
if( vmecam->isopen )
MOD_DEC_USE_COUNT;
usb_driver_release_interface(&vmecam_driver,
&vmecam->vmecam_dev->actconfig->interface[vmecam->ifnum]);
dbg("disconnect_vmecam: De-allocating minor:%d", vmecam->vmecam_minor);
p_vmecam_table[vmecam->vmecam_minor] = NULL;
kfree (vmecam);
}
static struct
file_operations usb_vmecam_fops = {
read: read_vmecam,
write: write_vmecam,
ioctl: ioctl_vmecam,
open: open_vmecam,
release: close_vmecam,
};
static struct
usb_driver vmecam_driver = {
name: "usbvmecam",
probe: probe_vmecam,
disconnect: disconnect_vmecam,
fops: &usb_vmecam_fops,
minor: VMECAM_BASE_MNR,
id_table: NULL, /* This would be vmecam_device_ids, but we
need to check every USB device, in case
we match a user defined vendor/product ID. */
};
void __exit
usb_vmecam_exit(void)
{
usb_deregister(&vmecam_driver);
}
int __init
usb_vmecam_init (void)
{
if (usb_register(&vmecam_driver) < 0)
return -1;
info("USB VMECAM support registered.");
return 0;
}
module_init(usb_vmecam_init);
module_exit(usb_vmecam_exit);
INCDIR = -I/usr/src/linux/include
VERSIONINC = -include /usr/src/linux/include/linux/modversions.h
CFLAGS = -O2 -Wall -c -D__KERNEL__ -DMODULE -Wall $(INCDIR) $(VERSIONINC)
DRIVER = usb-vmecam
TEST = simple-usb
all: $(DRIVER).o $(TEST)-vme $(TEST)-camac
$(DRIVER).o: $(DRIVER).c
gcc $(CFLAGS) $(DRIVER).c
device:
mknod -m 666 /dev/usbvmecam0 c 180 128
mknod -m 666 /dev/usbvmecam1 c 180 129
$(TEST)-vme: $(TEST)-vme.c
gcc -o $(TEST)-vme $(TEST)-vme.c
$(TEST)-camac: $(TEST)-camac.c
gcc -o $(TEST)-camac $(TEST)-camac.c
clean:
rm -f *.o *~ core $(TEST)-vme $(TEST)-camac
usbvmecamデバイスドライバを使ったCAMACプログラム
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#define IOCTL_LOAD_CDB _IOW('u', 0, int)
#define IOCTL_LOAD_SCSI_ID _IOW('u', 1, int)
#define NAFGEN(n,a,f) ((((n<<4) + a) << 5) + f)
void setcdb_scsi_inquiry( unsigned char *cdb, int len)
{
cdb[0] = 0x12; // inquiry comand
cdb[1] = cdb[2] = cdb[5] = 0;
cdb[3] = (len>>8)&0xff;
cdb[4] = len&0xff;
}
void setcdb_scsi_request_sense( unsigned char *cdb, int len)
{
cdb[0] = 0x03; // SCSI REQUEST SENSE COMMAND
cdb[1] = cdb[2] = cdb[3] = cdb[5] = 0;
cdb[4] = 0x12;
}
void setcdb_camac_single( unsigned char *cdb, int mode, int naf)
{
cdb[0] = 0x09; // single action
cdb[1] = 0; // must be zero
cdb[2] = mode; // 16bit:2 24bit:0
cdb[3] = ((naf & 0xff00) >>8);
cdb[4] = naf & 0x00ff;
cdb[5]=0;
}
void setcdb_camac_block( unsigned char *cdb, int mode, int naf, int len)
{
cdb[0] = 0x22; // block action
cdb[1] = 0; // must be zero
cdb[2] = mode; // 16bit:2 24bit:0,
cdb[3] = ((naf & 0xff00) >>8);
cdb[4] = naf & 0x00ff;
cdb[5] = ((len & 0xff0000) >> 16);
cdb[6] = ((len & 0x00ff00) >> 8);
cdb[7] = ( len & 0x0000ff);
cdb[8] = 0;
cdb[9] = 0;
}
static int cam_fd;
static int cdbbuf[6];
int CAMOPN( int minor, int scsi_id )
{
char filename[16];
strcpy(filename, "/dev/usbvmecam");
filename[14] = minor;
filename[15] = 0;
if((cam_fd = open(filename, O_RDWR)) == -1 )
return -1;
if( ioctl(cam_fd, IOCTL_LOAD_SCSI_ID, &scsi_id) == -1 )
return -1;
return 0;
}
int CAMCLS ( void )
{
if( close(cam_fd) == -1 )
return -1;
return 0;
}
int SCSIinquiry(int len, unsigned char *buffer)
{
int status;
cdbbuf[0] = 6; // size of CDB for SCSI inquiry
setcdb_scsi_inquiry((unsigned char *)&cdbbuf[1], len);
if( ioctl(cam_fd, IOCTL_LOAD_CDB, cdbbuf) == -1 )
return -1;
if( (status = read(cam_fd, buffer, len)) < 0 )
return status;
return 0;
}
int SCSIsense(int len, unsigned char *buffer)
{
int status;
cdbbuf[0] = 6; // size of CDB for SCSI request sense
setcdb_scsi_request_sense((unsigned char *)&cdbbuf[1], len);
if( ioctl(cam_fd, IOCTL_LOAD_CDB, cdbbuf) == -1 )
return -1;
if( (status = read(cam_fd, buffer, len)) < 0 )
return status;
return 0;
}
int readQX()
{
unsigned char buf[0x12];
int key, code, qual;
if( SCSIsense(0x12, buf) )
return -1;
code = buf[12] & 0xff;
key = buf[2] & 0x0f;
qual = buf[13] & 0xff;
// printf("code = %x, key = %x, qual = %x\n", buf[12], buf[2], buf[13]);
// printf("code = %x, key = %x, qual = %x\n", code, key, qual);
if( key == 0x09 && code == 0x80 && qual == 0x06 )
return 1;
else if( key == 0x09 && code == 0x80 && qual == 0x05 )
return 0;
else if( key == 0x00 && code == 0x00 && qual == 0x00 )
return 3;
else
return 0;
}
int CAMAC( int naf, int *data, int *q, int *x)
{
int status, qx, function;
cdbbuf[0] = 6; // size of CDB for CAMAC single
setcdb_camac_single( (unsigned char *)&cdbbuf[1], 0, naf);
if( ioctl(cam_fd, IOCTL_LOAD_CDB, cdbbuf) == -1 )
return -1;
function = naf & 0x1f;
if( function < 8 ) { // read
if( (status = read(cam_fd, data, 4)) < 0 )
return status;
} else if( function >15 && function < 24 ) { // write
if( (status = write(cam_fd, data, 4)) < 0 )
return status;
}
if( (qx = readQX()) < 0)
return qx;
*q = (qx >> 1);
*x = (qx & 1);
return 0;
}
int CDMA( int mode, int naf, int *buffer, int len, int *retlen)
{
int status;
cdbbuf[0] = 10; // size of CDB for CAMAC block action
setcdb_camac_block( (unsigned char *)&cdbbuf[1], mode, naf, len );
if( ioctl(cam_fd, IOCTL_LOAD_CDB, cdbbuf) == -1 )
return -1;
if( (naf & 0x1f) < 8 ) // read
if( (status = read(cam_fd, buffer, len*4 )) < 0 )
return status;
else if( !( naf & 8 ) )
if( (status = write(cam_fd, buffer, len*4)) < 0 )
return status;
return 0;
}
#define MEM 4
main( int argc, char **argv )
{
int data, q, x, retlen;
int databuf[8000];
unsigned char buffer[37];
int i, sid, status;
char minor;
int ccclear = NAFGEN(MEM, 0, 9);
int ccwrite = NAFGEN(MEM, 0, 16);
int ccread = NAFGEN(MEM, 0, 0 );
if(argc > 1)
minor = *argv[1];
else
minor = '0';
if(argc > 2)
sid = atoi(argv[2]);
else
sid = 0; // SCSI_ID = 0
CAMOPN( minor, sid );
SCSIinquiry(36, buffer);
buffer[36] = 0;
printf("SCSIinquiry message = %s\n", &buffer[8]);
// CGENZ
if( (status = CAMAC(NAFGEN(30,0,1),&data,&q,&x) ) != 0 )
return status;
data |= 1;
if( (status = CAMAC(NAFGEN(30,0,17),&data,&q,&x) ) != 0 )
return status;
printf("CGENZ done : X = %d Q = %d\n", x, q);
// CGENC
if( (status = CAMAC(NAFGEN(30,0,1),&data,&q,&x) ) != 0 )
return status;
data |= 2;
if( (status = CAMAC(NAFGEN(30,0,17),&data,&q,&x) ) != 0 )
return status;
printf("CGENC done\n");
// CREMI
if( (status = CAMAC(NAFGEN(30,0,1),&data,&q,&x) ) != 0 )
return status;
data &= ~4;
if( (status = CAMAC(NAFGEN(30,0,17),&data,&q,&x) ) != 0 )
status;
printf("CREMI done : X = %d Q = %d\n", x, q);
CAMAC(ccclear ,&data,&q,&x);
for(i = 0; i < 8000; i++) {
CAMAC(ccwrite ,&i,&q,&x);
}
CAMAC(ccclear ,&data,&q,&x);
for(i = 0; i < 8000; i++)
CAMAC(ccread ,&data,&q,&x);
CAMCLS();
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#define IOCTL_LOAD_CDB _IOW('u', 0, int)
#define IOCTL_LOAD_SCSI_ID _IOW('u', 1, int)
void setcdb_scsi_inquiry( unsigned char *cdb, int len)
{
cdb[0] = 0x12; // inquiry comand
cdb[1] = cdb[2] = cdb[5] = 0;
cdb[3] = (len>>8)&0xff;
cdb[4] = len&0xff;
}
void setcdb_vme_write( unsigned char *cdb, int vme_addr, int len)
{
cdb[0] = 0x2a; // write command
cdb[1] = cdb[6] = cdb[9] = 0;
cdb[2] = (vme_addr>>24)&0xff;
cdb[3] = (vme_addr>>16)&0xff;
cdb[4] = (vme_addr>>8)&0xff;
cdb[5] = vme_addr&0xff;
cdb[7] = (len>>8)&0xff;
cdb[8] = len&0xff;
}
void setcdb_vme_read( unsigned char *cdb, int vme_addr, int len)
{
cdb[0] = 0x28; // read command
cdb[1] = cdb[6] = cdb[9] = 0;
cdb[2] = (vme_addr>>24)&0xff;
cdb[3] = (vme_addr>>16)&0xff;
cdb[4] = (vme_addr>>8)&0xff;
cdb[5] = vme_addr&0xff;
cdb[7] = (len>>8)&0xff;
cdb[8] = len&0xff;
}
static int vme_fd;
static int cdbbuf[6];
int VMEOPN ( char minor, int scsi_id )
{
char filename[16];
strcpy(filename, "/dev/usbvmecam");
filename[14] = minor;
filename[15] = 0;
if((vme_fd = open(filename, O_RDWR)) == -1 )
return -1;
if( ioctl(vme_fd, IOCTL_LOAD_SCSI_ID, &scsi_id) == -1 )
return -1;
return 0;
}
int VMECLS ( void )
{
if( close(vme_fd) == -1 )
return -1;
return 0;
}
int SCSIinquiry(int len, unsigned char *buffer)
{
int status;
cdbbuf[0] = 6; // size of CDB for SCSI inquiry
setcdb_scsi_inquiry((unsigned char *)&cdbbuf[1], len);
if( ioctl(vme_fd, IOCTL_LOAD_CDB, cdbbuf) == -1 )
return -1;
if( (status = read(vme_fd, buffer, len)) < 0 )
return status;
return 0;
}
int VMEwrite(int len, int vme_addr, unsigned char *buffer)
{
int status;
cdbbuf[0] = 10; // size of CDB for VME write
setcdb_vme_write((unsigned char *)&cdbbuf[1], vme_addr, len);
if( ioctl(vme_fd, IOCTL_LOAD_CDB, cdbbuf) == -1 )
return -1;
if( (status = write(vme_fd, buffer, len)) < 0 )
return status;
return 0;
}
int VMEread(int len, int vme_addr, unsigned char *buffer)
{
int status;
cdbbuf[0] = 10; // size of CDB for SCSI inquiry
setcdb_vme_read((unsigned char *)&cdbbuf[1], vme_addr, len);
if( ioctl(vme_fd, IOCTL_LOAD_CDB, cdbbuf) == -1 )
return -1;
if( (status = read(vme_fd, buffer, len)) < 0 )
return status;
return 0;
}
#define INTREG_ADDR 0xFFFF8F00
#define LAT0 (INTREG_ADDR + 0)
#define LAT1 (INTREG_ADDR + 2)
#define FF (INTREG_ADDR + 4)
#define IN (INTREG_ADDR + 6)
#define PULSE (INTREG_ADDR + 8)
#define OUT (INTREG_ADDR + 10)
#define CSR0 (INTREG_ADDR + 12)
#define CSR1 (INTREG_ADDR + 14)
short swap16( short data )
{
char tmp;
union swap {
char c[2];
short s;
} swap_data;
swap_data.s = data;
tmp = swap_data.c[1];
swap_data.c[1] = swap_data.c[0];
swap_data.c[0] = tmp;
return swap_data.s;
}
int swap32( int data )
{
char tmp;
union swap {
char c[4];
int s;
} swap_data;
swap_data.s = data;
tmp = swap_data.c[0];
swap_data.c[0] = swap_data.c[3];
swap_data.c[3] = tmp;
tmp = swap_data.c[1];
swap_data.c[1] = swap_data.c[2];
swap_data.c[2] = tmp;
return swap_data.s;
}
void print_data16( short data )
{
short result = swap16(data);
printf("data = %x\n", result&0xff);
}
main( int argc, char **argv) {
int vme_addr;
int sid;
short data;
unsigned char buffer[37];
int i;
char minor;
if(argc > 1)
minor = *argv[1];
else
minor = '0';
if(argc > 2)
sid = atoi(argv[2]);
else
sid = 0; // SCSI_ID = 0
VMEOPN( minor, sid );
SCSIinquiry(36, buffer);
buffer[36] = 0;
printf("SCSIinquiry message = %s\n", &buffer[8]);
data = swap16(0xf);
VMEwrite(2, OUT, (unsigned char *)&data);
data = swap16(0xf);
VMEwrite(2, CSR0, (unsigned char *)&data);
data = swap16(0xf);
VMEwrite(2, CSR1, (unsigned char *)&data);
data = 0;
VMEread(2, LAT0, (unsigned char *)&data);
print_data16(data);
VMEread(2, LAT1, (unsigned char *)&data);
print_data16(data);
VMEread(2, FF, (unsigned char *)&data);
print_data16(data);
VMEread(2, IN, (unsigned char *)&data);
print_data16(data);
VMEread(2, PULSE, (unsigned char *)&data);
print_data16(data);
VMEread(2, OUT, (unsigned char *)&data);
print_data16(data);
VMEread(2, CSR0, (unsigned char *)&data);
print_data16(data);
VMEread(2, CSR1, (unsigned char *)&data);
print_data16(data);
VMECLS();
}