diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2007-06-27 02:40:39 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2007-06-27 02:40:39 +0000 |
commit | 3afa50f47b9af629ea07c4876fc013d4080d0eab (patch) | |
tree | 5714b4f83f80b598975e7391d230ad00d3b23f3a /archive | |
parent | ded737d99ef066a8aff068d73365aae2fb5bbba4 (diff) | |
download | sg3_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/Makefile | 8 | ||||
-rw-r--r-- | archive/README | 10 | ||||
-rw-r--r-- | archive/sg_bus_xfer.c | 231 | ||||
-rw-r--r-- | archive/sg_dd2048.c | 3 | ||||
-rw-r--r-- | archive/sg_dd512.c | 3 | ||||
-rw-r--r-- | archive/sg_dd_old.c | 2 | ||||
-rw-r--r-- | archive/sg_hold.c | 144 | ||||
-rw-r--r-- | archive/sg_include.h | 42 | ||||
-rw-r--r-- | archive/sg_poll.c | 2 | ||||
-rw-r--r-- | archive/sg_reset.c | 2 | ||||
-rw-r--r-- | archive/sgq_dd.c | 2 | ||||
-rw-r--r-- | archive/sgq_old_dd.c | 2 | ||||
-rw-r--r-- | archive/sgs_dd.c | 2 | ||||
-rw-r--r-- | archive/xsgp_dd.c | 2 |
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. |