--- linux/include/scsi/sg.h Tue Nov 14 16:58:43 2000 +++ linux/include/scsi/sg.h3017bus Fri Mar 2 18:11:39 2001 @@ -11,9 +11,11 @@ Version 2 and 3 extensions to driver: * Copyright (C) 1998 - 2000 Douglas Gilbert - Version: 3.0.17 (20001114) + Version: 3.0.17 bus (20010301) This version is for 2.2 series kernels. + Changes since 3.0.17 (20001114) + - add SG_FLAG_BUS_ADDR for IO memory to disk tranfers Changes since 3.0.16 (20000623) - bugfix: reserved size changed via procfs [M. Chouquet-Stringer] - cleanup for no procfs @@ -68,9 +70,9 @@ 2.1.34 2.2.10 to 2.2.13 2.1.36 2.2.14 and 2.2.15 2.1.38 2.2.16 - 2.1.39 2.2.17 + 2.1.39 2.2.17 and 2.2.18 3.0.x optional version 3 sg driver for 2.2 series - 3.1.x first appeared in lk 2.3.43 + 3.1.17 2.4.0 (version 3 first appeared in lk 2.3.43) Major new features in SG 3.x driver (cf SG 2.x drivers) - SG_IO ioctl() combines function if write() and read() @@ -175,6 +177,7 @@ #define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */ #define SG_FLAG_LUN_INHIBIT 2 /* default is to put device's lun into */ /* the 2nd byte of SCSI command */ +#define SG_FLAG_BUS_ADDR 0x10 /* dxferp assumed to be bus address */ #define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */ /* user space (debug indirect IO) */ --- linux/drivers/scsi/sg.c Tue Nov 14 15:59:34 2000 +++ linux/drivers/scsi/sg.c3017bus Fri Mar 2 18:12:29 2001 @@ -17,7 +17,7 @@ */ #include #ifdef CONFIG_PROC_FS - static char * sg_version_str = "Version: 3.0.17 (20001114)"; + static char * sg_version_str = "Version: 3.0.17 bus (20010301)"; #endif static int sg_version_num = 30017; /* 2 digits for each component */ /* @@ -1316,11 +1316,21 @@ int dxfer_len = (int)hp->dxfer_len; Sg_scatter_hold * req_schp = &srp->data; Sg_scatter_hold * rsv_schp = &sfp->reserve; + int new_interface = ('\0' == hp->interface_id) ? 0 : 1; SCSI_LOG_TIMEOUT(4, printk("sg_start_req: dxfer_len=%d\n", dxfer_len)); if ((dxfer_len <= 0) || (hp->dxfer_direction == SG_DXFER_NONE)) return 0; - if ((! sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) { + if (new_interface && (SG_FLAG_BUS_ADDR & hp->flags)) { + req_schp->k_use_sg = 0; + req_schp->bufflen = dxfer_len; + req_schp->buffer = hp->dxferp; + req_schp->buffer_mem_src = SG_USER_MEM; + req_schp->b_malloc_len = 0; + if(! capable(CAP_SYS_ADMIN)) + return -EACCES; + } + else if ((! sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) { sg_link_reserve(sfp, srp, dxfer_len); } else { @@ -1337,10 +1347,14 @@ { Sg_fd * sfp = srp->parentfp; Sg_scatter_hold * req_schp = &srp->data; + sg_io_hdr_t * hp = &srp->header; + int new_interface = ('\0' == hp->interface_id) ? 0 : 1; SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n", (int)srp->res_used)); - if (srp->res_used) + if (new_interface && (SG_FLAG_BUS_ADDR & hp->flags)) + req_schp->bufflen = 0; + else if (srp->res_used) sg_unlink_reserve(sfp, srp); else sg_remove_scat(req_schp); @@ -1467,7 +1481,8 @@ if (schp->bufflen < num_xfer) num_xfer = schp->bufflen; } - if ((num_xfer <= 0) || (new_interface && (SG_FLAG_NO_DXFER & hp->flags))) + if ((num_xfer <= 0) || (new_interface && + ((SG_FLAG_NO_DXFER | SG_FLAG_BUS_ADDR) & hp->flags))) return 0; SCSI_LOG_TIMEOUT(4, @@ -1616,7 +1631,8 @@ if (schp->bufflen < num_xfer) num_xfer = schp->bufflen; } - if ((num_xfer <= 0) || (new_interface && (SG_FLAG_NO_DXFER & hp->flags))) + if ((num_xfer <= 0) || (new_interface && + ((SG_FLAG_NO_DXFER | SG_FLAG_BUS_ADDR) & hp->flags))) return 0; SCSI_LOG_TIMEOUT(4,