aboutsummaryrefslogtreecommitdiff
path: root/archive
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2007-06-27 02:40:39 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2007-06-27 02:40:39 +0000
commit3afa50f47b9af629ea07c4876fc013d4080d0eab (patch)
tree5714b4f83f80b598975e7391d230ad00d3b23f3a /archive
parentded737d99ef066a8aff068d73365aae2fb5bbba4 (diff)
downloadsg3_utils-3afa50f47b9af629ea07c4876fc013d4080d0eab.tar.gz
Load sg3_utils-0.93 into trunk/.
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@10 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'archive')
-rw-r--r--archive/Makefile8
-rw-r--r--archive/README10
-rw-r--r--archive/sg_bus_xfer.c231
-rw-r--r--archive/sg_dd2048.c3
-rw-r--r--archive/sg_dd512.c3
-rw-r--r--archive/sg_dd_old.c2
-rw-r--r--archive/sg_hold.c144
-rw-r--r--archive/sg_include.h42
-rw-r--r--archive/sg_poll.c2
-rw-r--r--archive/sg_reset.c2
-rw-r--r--archive/sgq_dd.c2
-rw-r--r--archive/sgq_old_dd.c2
-rw-r--r--archive/sgs_dd.c2
-rw-r--r--archive/xsgp_dd.c2
14 files changed, 442 insertions, 13 deletions
diff --git a/archive/Makefile b/archive/Makefile
index b1232a90..8f2b3b35 100644
--- a/archive/Makefile
+++ b/archive/Makefile
@@ -6,7 +6,7 @@ MANDIR=/usr/local/man
CC = gcc
LD = gcc
-EXECS = sgq_dd sg_poll sg_reset
+EXECS = sgq_dd sg_poll sg_reset sg_bus_xfer sg_hold
COMMON =
@@ -38,6 +38,12 @@ sgq_dd: sgq_dd.o ../sg_err.o ../llseek.o
sg_reset: sg_reset.o
$(LD) -o $@ $(LDFLAGS) $^
+sg_bus_xfer: sg_bus_xfer.o ../sg_err.o
+ $(LD) -o $@ $(LDFLAGS) $^
+
+sg_hold: sg_hold.o
+ $(LD) -o $@ $(LDFLAGS) $^
+
install: $(EXECS) $(COMMON)
install -d $(INSTDIR)
for name in $^; \
diff --git a/archive/README b/archive/README
index 7b1d8283..70df7849 100644
--- a/archive/README
+++ b/archive/README
@@ -16,10 +16,18 @@ been set up which builds:
POSIX threads (as does sgp_dd)]
- sg_reset [does SCSI bus/device/host resets if mid level SCSI patch
in place]
+ - sg_hold holds a sg device open and periodically sends a TEST
+ UNIT READY command to the device
- sg_poll [internal testing]
The sg_err.h and llseek.h headers have simply been copied from the parent
directory.
+A test program called sg_bus_xfer.c exercises a patch that adds a
+SG_FLAG_BUS_ADDR capability. This allows a bus address (e.g. PCI
+video card's frame buffer) to be passed through to a SCSI adapter
+to side step various buffer copies. See:
+http://www.torque.net/sg/mem2disk.html
+
Doug Gilbert
-13th January 2001
+22nd March 2001
diff --git a/archive/sg_bus_xfer.c b/archive/sg_bus_xfer.c
new file mode 100644
index 00000000..eaf6bcb5
--- /dev/null
+++ b/archive/sg_bus_xfer.c
@@ -0,0 +1,231 @@
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "sg_include.h"
+#include "sg_err.h"
+
+/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
+ device driver.
+* Copyright (C) 2001 D. Gilbert
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, or (at your option)
+* any later version.
+
+ This program tests the SG_FLAG_BUS_ADDR capability.
+ It is for moving data to and from fixed memory addresses (e.g. memory
+ mapped io used by video frame buffers) directly to a SCSI device via
+ the sg driver. The given address is passed straight through by sg to the
+ scsi adapter driver. The adapter typically does a "virtual to bus"
+ address transformation and gives the new address to its DMA engine.
+ Large amounts of data (in physically contiguous memory) can be moved
+ (quickly) in a single SCSI command.
+
+ This will probably only work on i386 architecture with PCI cards that
+ memory map their IO area (e.g. video frame buffer). On i386 the
+ "virt_to_bus" transformation involves subtracting 0xC0000000 from the
+ given address. So from the addresses seen in the lspci command,
+ subtracting 0x40000000 would be an appropriate correction (due to
+ 32 bit wrap around).
+
+ The SG_FLAG_BUS_ADDR logic is not in normal sg drivers, you need a
+ patch, see the sg web site.
+
+ Version 0.11 (20010210)
+*/
+
+#ifndef SG_FLAG_BUS_ADDR
+#define SG_FLAG_BUS_ADDR 0x10
+#endif
+
+
+#define S_RW_LEN 10 /* Use SCSI READ(10) and WRITE(10) */
+
+#define SGP_READ10 0x28
+#define SGP_WRITE10 0x2a
+
+/* #define SG_DEBUG */
+
+
+int get_num(char * buf)
+{
+ int res, num;
+ char c;
+
+ res = sscanf(buf, "%d%c", &num, &c);
+ if (0 == res)
+ return -1;
+ else if (1 == res)
+ return num;
+ else {
+ switch (c) {
+ case 'c':
+ case 'C':
+ return num;
+ case 'b':
+ case 'B':
+ return num * 512;
+ case 'k':
+ return num * 1024;
+ case 'K':
+ return num * 1000;
+ case 'm':
+ return num * 1024 * 1024;
+ case 'M':
+ return num * 1000000;
+ case 'g':
+ return num * 1024 * 1024 * 1024;
+ case 'G':
+ return num * 1000000000;
+ default:
+ fprintf(stderr, "unrecognized multiplier\n");
+ return -1;
+ }
+ }
+}
+
+int main(int argc, char * argv[])
+{
+ int sg_fd, res, j, m;
+ unsigned int k, num;
+ unsigned char rwCmdBlk[S_RW_LEN];
+ unsigned char sense_buffer[32];
+ int do_wr = -1; /* 1 -> write, 0 -> read */
+ unsigned long addr = ULONG_MAX;
+ int bs = 512;
+ int skip = -1;
+ int count = -1;
+ char * file_name = 0;
+ sg_io_hdr_t io_hdr;
+
+ for (j = 1; j < argc; ++j) {
+ if (0 == strncmp("-a=", argv[j], 3)) {
+ m = 3;
+ num = sscanf(argv[j] + m, "%lx", &addr);
+ if (1 != num) {
+ printf("Couldn't decode number after '-a=' switch\n");
+ file_name = 0;
+ break;
+ }
+ }
+ else if (0 == strncmp("-bs=", argv[j], 4)) {
+ m = 4;
+ bs = get_num(argv[j] + m);
+ if (-1 == bs) {
+ printf("Couldn't decode number after '-bs=' switch\n");
+ file_name = 0;
+ break;
+ }
+ }
+ else if (0 == strncmp("-skip=", argv[j], 6)) {
+ m = 6;
+ skip = get_num(argv[j] + m);
+ if (-1 == skip) {
+ printf("Couldn't decode number after '-skip=' switch\n");
+ file_name = 0;
+ break;
+ }
+ }
+ else if (0 == strncmp("-count=", argv[j], 7)) {
+ m = 7;
+ count = get_num(argv[j] + m);
+ if (-1 == count) {
+ printf("Couldn't decode number after '-count=' switch\n");
+ file_name = 0;
+ break;
+ }
+ }
+ else if (0 == strcmp("-r", argv[j]))
+ do_wr = 0;
+ else if (0 == strcmp("-w", argv[j]))
+ do_wr = 1;
+ else if (*argv[j] == '-') {
+ printf("Unrecognized switch: %s\n", argv[j]);
+ file_name = 0;
+ break;
+ }
+ else
+ file_name = argv[j];
+ }
+ if ((0 == file_name) || (count < 0) || (do_wr < 0) || (addr == ULONG_MAX)
+ || (skip < 0)) {
+ printf("Probabably missing parameter\n\n");
+ printf(
+ "Usage: 'sg_bus_xfer -r|w -a=hex_num [-bs=num] -skip=num"
+ " <sg_device>'\n");
+ printf(" where: -r|w read from (or write to) sg device\n");
+ printf(" -a=hex_num memory address (virtual ?)\n");
+ printf(" -bs=num blocks size in bytes (default 512)\n");
+ printf(" -skip=num num is blocks to skip/seek on sg dev\n");
+ printf(" -count=num num of blocks to xfer\n");
+ printf("\n BEWARE you could do damage with this command "
+ "(needs root access)\n");
+ printf("\n bs, skip and count may take k,K,m,M etc multipliers\n");
+ return 1;
+ }
+
+ sg_fd = open(file_name, O_RDWR);
+ if (sg_fd < 0) {
+ perror("sg_bus_xfer: open error");
+ return 1;
+ }
+ /* Don't worry, being very careful not to write to a none-sg file ... */
+ res = ioctl(sg_fd, SG_GET_VERSION_NUM, &k);
+ if ((res < 0) || (k < 30000)) {
+ printf("sg_bus_xfer: not a sg device, or driver prior to 3.x\n");
+ return 1;
+ }
+
+ memset(rwCmdBlk, 0, S_RW_LEN);
+ rwCmdBlk[0] = do_wr ? SGP_WRITE10 : SGP_READ10;
+ rwCmdBlk[2] = (unsigned char)((skip >> 24) & 0xFF);
+ rwCmdBlk[3] = (unsigned char)((skip >> 16) & 0xFF);
+ rwCmdBlk[4] = (unsigned char)((skip >> 8) & 0xFF);
+ rwCmdBlk[5] = (unsigned char)(skip & 0xFF);
+ rwCmdBlk[6] = (unsigned char)((count >> 16) & 0xff);
+ rwCmdBlk[7] = (unsigned char)((count >> 8) & 0xff);
+ rwCmdBlk[8] = (unsigned char)(count & 0xff);
+ memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = sizeof(rwCmdBlk);
+ io_hdr.mx_sb_len = sizeof(sense_buffer);
+ io_hdr.dxfer_direction = do_wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
+ io_hdr.dxfer_len = bs * count;
+ // io_hdr.dxferp = malloc(1024 * 1024); /* <<<<<<<<<<<<<<<< */
+ io_hdr.dxferp = (void *)addr;
+ io_hdr.cmdp = rwCmdBlk;
+ io_hdr.flags = SG_FLAG_BUS_ADDR;
+ io_hdr.sbp = sense_buffer;
+ io_hdr.timeout = 10000; /* 10000 millisecs == 10 seconds */
+
+ printf(" dxferp=%p len=%d\n", io_hdr.dxferp, bs * count);
+#ifdef SG_DEBUG
+ sg_print_command(rwCmdBlk);
+ printf(" dxferp=%p len=%d\n", io_hdr.dxferp, bs * count);
+ return 0;
+#endif
+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
+ perror("sg_bus_xfer: SG_IO failed");
+ return 1;
+ }
+
+ /* now for the error processing */
+ switch (sg_err_category3(&io_hdr)) {
+ case SG_ERR_CAT_CLEAN:
+ break;
+ case SG_ERR_CAT_RECOVERED:
+ printf("Recovered error, continuing\n");
+ break;
+ default: /* won't bother decoding other categories */
+ sg_chk_n_print3("SG_IO error", &io_hdr);
+ return 1;
+ }
+ return 0;
+}
diff --git a/archive/sg_dd2048.c b/archive/sg_dd2048.c
index 3988f59e..0a833c45 100644
--- a/archive/sg_dd2048.c
+++ b/archive/sg_dd2048.c
@@ -8,8 +8,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <linux/../scsi/sg.h> /* cope with silly includes */
-#include <linux/../scsi/scsi.h>
+#include "sg_include.h"
#include "sg_err.h"
/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
diff --git a/archive/sg_dd512.c b/archive/sg_dd512.c
index b8506256..18d0e452 100644
--- a/archive/sg_dd512.c
+++ b/archive/sg_dd512.c
@@ -8,8 +8,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <linux/../scsi/sg.h> /* cope with silly includes */
-#include <linux/../scsi/scsi.h>
+#include "sg_include.h"
#include "sg_err.h"
/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
diff --git a/archive/sg_dd_old.c b/archive/sg_dd_old.c
index fd70527b..7ff9ad62 100644
--- a/archive/sg_dd_old.c
+++ b/archive/sg_dd_old.c
@@ -8,7 +8,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <linux/../scsi/sg.h> /* cope with silly includes */
+#include "sg_include.h"
#include "sg_err.h"
/* A utility program for the Linux OS SCSI generic ("sg") device driver.
diff --git a/archive/sg_hold.c b/archive/sg_hold.c
new file mode 100644
index 00000000..da8a56af
--- /dev/null
+++ b/archive/sg_hold.c
@@ -0,0 +1,144 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "sg_include.h"
+
+/* This is a program that periodically executes a TEST UNIT READY
+ SCSI command using the SCSI generic (sg) driver.
+
+* Copyright (C) 2001 D. Gilbert
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, or (at your option)
+* any later version.
+
+ Invocation: sg_hold [-t<secs>] [-d] <sg_device>
+
+ Version 1.00 (20010312)
+
+6 byte TEST UNIT READY command:
+[0x00][ |lu][res ][res ][res ][res ]
+
+*/
+#define TUR_CMD_LEN 6
+
+
+int main(int argc, char * argv[])
+{
+ int sg_fd, k, j, res;
+ unsigned char turCmdBlk [TUR_CMD_LEN] =
+ {0x00, 0, 0, 0, 0, 0};
+ sg_io_hdr_t io_hdr;
+ char * file_name = 0;
+ char ebuff[128];
+ unsigned char sense_buffer[32];
+ int sleep_period = 1;
+ int debug = 0;
+ size_t len;
+
+ for (k = 1; k < argc; ++k) {
+ if (0 == memcmp("-t", argv[k], 2)) {
+ len = strlen(argv[k]);
+ if (len > 2)
+ res = sscanf(argv[k] + 2, "%d", &sleep_period);
+ else if (++k < argc)
+ res = sscanf(argv[k], "%d", &sleep_period);
+ else
+ res = 0;
+ if ((1 != res) || (sleep_period < 1)) {
+ file_name = 0;
+ printf("Bad '-t' argument\n");
+ break;
+ }
+ }
+ else if (0 == memcmp("-d", argv[k], 2))
+ debug = 1;
+ else if (*argv[k] == '-') {
+ printf("Unrecognized switch: %s\n", argv[k]);
+ file_name = 0;
+ break;
+ }
+ else if (0 == file_name)
+ file_name = argv[k];
+ else {
+ printf("too many arguments\n");
+ file_name = 0;
+ break;
+ }
+ }
+ if (0 == file_name) {
+ printf("Usage: 'sg_hold [-t<secs>] [-d] <sg_device>'\n");
+ printf(" where: -t<secs> time in seconds between TURs "
+ "(default: 1 sec)\n");
+ printf(" -d output message with each TUR\n");
+ return 1;
+ }
+
+ if ((sg_fd = open(file_name, O_RDONLY)) < 0) {
+ sprintf(ebuff, "sg_hold: error opening file: %s", file_name);
+ perror(ebuff);
+ return 1;
+ }
+ /* Just to be safe, check we have a new sg device by trying an ioctl */
+ if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
+ printf("sg_hold: %s doesn't seem to be an new sg device\n",
+ file_name);
+ close(sg_fd);
+ return 1;
+ }
+
+ for (j = 1; ; ++j) {
+ /* Prepare TEST UNIT READY command */
+ memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+ io_hdr.interface_id = 'S';
+ io_hdr.cmd_len = sizeof(turCmdBlk);
+ io_hdr.mx_sb_len = sizeof(sense_buffer);
+ io_hdr.dxfer_direction = SG_DXFER_NONE;
+ io_hdr.cmdp = turCmdBlk;
+ io_hdr.sbp = sense_buffer;
+ io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */
+ io_hdr.pack_id = j; /* marching pack_id starting at 1 */
+
+ if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
+ perror("sg_hold: Test Unit Ready SG_IO ioctl error");
+ close(sg_fd);
+ return 1;
+ }
+
+ /* now for the error processing */
+ if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
+ if (io_hdr.sb_len_wr > 0) {
+ printf("TEST UNIT READY sense data: ");
+ for (k = 0; k < io_hdr.sb_len_wr; ++k) {
+ if ((k > 0) && (0 == (k % 10)))
+ printf("\n ");
+ printf("0x%02x ", sense_buffer[k]);
+ }
+ printf("\n");
+ }
+ else if (io_hdr.masked_status)
+ printf("TEST UNIT READY SCSI status=0x%x\n", io_hdr.status);
+ else if (io_hdr.host_status)
+ printf("TEST UNIT READY host_status=0x%x\n",
+ io_hdr.host_status);
+ else if (io_hdr.driver_status)
+ printf("TEST UNIT READY driver_status=0x%x\n",
+ io_hdr.driver_status);
+ else
+ printf("TEST UNIT READY unexpected error\n");
+ printf("Test Unit Ready failed so unit may _not_ be ready!\n");
+ }
+ else if (debug)
+ printf("Test Unit Ready successful so unit is ready!\n");
+
+ sleep(sleep_period);
+ }
+ close(sg_fd);
+ return 0;
+}
diff --git a/archive/sg_include.h b/archive/sg_include.h
new file mode 100644
index 00000000..5baca3cc
--- /dev/null
+++ b/archive/sg_include.h
@@ -0,0 +1,42 @@
+#ifdef SG_KERNEL_INCLUDES
+ #include "/usr/src/linux/include/scsi/sg.h"
+ #include "/usr/src/linux/include/scsi/scsi.h"
+#else
+ #ifdef SG_TRICK_GNU_INCLUDES
+ #include <linux/../scsi/sg.h>
+ #include <linux/../scsi/scsi.h>
+ #else
+ #include <scsi/sg.h>
+ #include <scsi/scsi.h>
+ #endif
+#endif
+
+/*
+ Getting the correct include files for the sg interface can be an ordeal.
+ In a perfect world, one would just write:
+ #include <scsi/sg.h>
+ #include <scsi/scsi.h>
+ This would include the files found in the /usr/include/scsi directory.
+ Those files are maintained with the GNU library which may or may not
+ agree with the kernel and version of sg driver that is running. Any
+ many cases this will not matter. However in some it might, for example
+ glibc 2.1's include files match the sg driver found in the lk 2.2
+ series. Hence if glibc 2.1 is used with lk 2.4 then the additional
+ sg v3 interface will not be visible.
+ If this is a problem then defining SG_KERNEL_INCLUDES will access the
+ kernel supplied header files (assuming they are in the normal place).
+ The GNU library maintainers and various kernel people don't like
+ this approach (but it does work).
+ The technique selected by defining SG_TRICK_GNU_INCLUDES worked (and
+ was used) prior to glibc 2.2 . Prior to that version /usr/include/linux
+ was a symbolic link to /usr/src/linux/include/linux .
+
+ There are other approaches if this include "mixup" causes pain. These
+ would involve include files being copied or symbolic links being
+ introduced.
+
+ Sorry about the inconvenience. Typically neither SG_KERNEL_INCLUDES
+ nor SG_TRICK_GNU_INCLUDES is defined.
+
+ dpg 20010415
+*/
diff --git a/archive/sg_poll.c b/archive/sg_poll.c
index ed9c7af2..8d3fe135 100644
--- a/archive/sg_poll.c
+++ b/archive/sg_poll.c
@@ -13,7 +13,7 @@
#include <sys/poll.h>
#include <sys/ipc.h>
#include <sys/sem.h>
-#include <linux/../scsi/sg.h> /* cope with silly includes */
+#include "sg_include.h"
#include "sg_err.h"
/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
diff --git a/archive/sg_reset.c b/archive/sg_reset.c
index d88ca54e..eafb84be 100644
--- a/archive/sg_reset.c
+++ b/archive/sg_reset.c
@@ -7,7 +7,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <linux/../scsi/sg.h> /* cope with silly includes */
+#include "sg_include.h"
/* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg")
device driver.
diff --git a/archive/sgq_dd.c b/archive/sgq_dd.c
index 905e7eaf..5b1b3f08 100644
--- a/archive/sgq_dd.c
+++ b/archive/sgq_dd.c
@@ -14,9 +14,9 @@
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/poll.h>
-#include <linux/../scsi/sg.h> /* cope with silly includes */
#include <linux/major.h>
typedef unsigned char u_char; /* horrible, for scsi.h */
+#include "sg_include.h"
#include "sg_err.h"
#include "llseek.h"
diff --git a/archive/sgq_old_dd.c b/archive/sgq_old_dd.c
index 2af81058..2ef041dd 100644
--- a/archive/sgq_old_dd.c
+++ b/archive/sgq_old_dd.c
@@ -9,7 +9,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <linux/../scsi/sg.h> /* cope with silly includes */
+#include "sg_include.h"
#include "sg_err.h"
/* A utility program for the Linux OS SCSI generic ("sg") device driver.
diff --git a/archive/sgs_dd.c b/archive/sgs_dd.c
index 51aa694d..b9b4e60e 100644
--- a/archive/sgs_dd.c
+++ b/archive/sgs_dd.c
@@ -13,7 +13,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <linux/../scsi/sg.h> /* cope with silly includes */
+#include "sg_include.h"
#include "sg_err.h"
/* Test code for the extensions to the Linux OS SCSI generic ("sg")
diff --git a/archive/xsgp_dd.c b/archive/xsgp_dd.c
index fbf70896..389ca590 100644
--- a/archive/xsgp_dd.c
+++ b/archive/xsgp_dd.c
@@ -10,7 +10,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <linux/../scsi/sg.h> /* cope with silly includes */
+#include "sg_include.h"
#include "sg_err.h"
/* A utility program for the Linux OS SCSI generic ("sg") device driver.