diff options
author | davem <davem> | 2002-01-15 18:04:30 +0000 |
---|---|---|
committer | davem <davem> | 2002-01-15 18:04:30 +0000 |
commit | 826db16337e3fe95ee644e8021f03dad7b68197f (patch) | |
tree | 46f424fed6a581f4ffeb8515b3e6b93ff7345d8c | |
parent | ea0b7d568ac44bb6967505042b91fd8ab3f7d4a5 (diff) | |
download | netdev-vger-cvs-826db16337e3fe95ee644e8021f03dad7b68197f.tar.gz |
Revert 2.4.x changes.
-rw-r--r-- | drivers/scsi/osst.c | 208 | ||||
-rw-r--r-- | drivers/scsi/osst.h | 4 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 307 | ||||
-rw-r--r-- | include/scsi/sg.h | 91 |
4 files changed, 161 insertions, 449 deletions
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 36b57bfbd..4c8d0a95e 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -16,15 +16,15 @@ Copyright 1992 - 2000 Kai Makisara email Kai.Makisara@metla.fi - $Header: /home/cvsroot/Driver/osst.c,v 1.65 2001/11/11 20:38:56 riede Exp $ + $Header: /home/cvsroot/Driver/osst.c,v 1.61 2001/06/03 21:55:12 riede Exp $ Microscopic alterations - Rik Ling, 2000/12/21 Last modified: Wed Feb 2 22:04:05 2000 by makisara@kai.makisara.local Some small formal changes - aeb, 950809 */ -static const char * cvsid = "$Id: osst.c,v 1.65 2001/11/11 20:38:56 riede Exp $"; -const char * osst_version = "0.9.10"; +static const char * cvsid = "$Id: osst.c,v 1.61 2001/06/03 21:55:12 riede Exp $"; +const char * osst_version = "0.9.8"; /* The "failure to reconnect" firmware bug */ #define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/ @@ -226,20 +226,20 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt) SRpnt->sr_cmnd[0] != MODE_SENSE && SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */ if (driver_byte(result) & DRIVER_SENSE) { - printk(KERN_WARNING "osst%d:W: Command with sense data: ", dev); - print_req_sense("osst:", SRpnt); + printk(KERN_WARNING "osst%d:W: Error with sense data: ", dev); + print_req_sense("osst", SRpnt); } else { static int notyetprinted = 1; printk(KERN_WARNING - "osst%d:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", + "osst%d:W: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n", dev, result, suggestion(result), driver_byte(result) & DRIVER_MASK, host_byte(result)); if (notyetprinted) { notyetprinted = 0; printk(KERN_INFO - "osst%d:I: This warning may be caused by your scsi controller,\n", dev); + "osst%d:I: This error may be caused by your scsi controller,\n", dev); printk(KERN_INFO "osst%d:I: it has been reported with some Buslogic cards.\n", dev); } @@ -271,10 +271,11 @@ static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt) /* Wakeup from interrupt */ static void osst_sleep_done (Scsi_Cmnd * SCpnt) { - unsigned int dev = TAPE_NR(SCpnt->request.rq_dev); + unsigned int dev; OS_Scsi_Tape * STp; - if (os_scsi_tapes && (STp = os_scsi_tapes[dev])) { + if ((dev = TAPE_NR(SCpnt->request.rq_dev)) < osst_template.nr_dev) { + STp = os_scsi_tapes[dev]; if ((STp->buffer)->writing && (SCpnt->sense_buffer[0] & 0x70) == 0x70 && (SCpnt->sense_buffer[2] & 0x40)) { @@ -481,8 +482,7 @@ static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet memset(page_address(STp->buffer->sg[i].page), 0, STp->buffer->sg[i].length); strcpy(STp->buffer->b_data, "READ ERROR ON FRAME"); - } else - STp->buffer->buffer_bytes = OS_FRAME_SIZE; + } return 1; } if (STp->buffer->syscall_result) { @@ -621,10 +621,8 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned if (!SRpnt) return (-EBUSY); while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) && - (( SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 && - (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) || - ( SRpnt->sr_sense_buffer[2] == 6 && SRpnt->sr_sense_buffer[12] == 0x28 && - SRpnt->sr_sense_buffer[13] == 0 ) )) { + SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 && + (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) { #if DEBUG if (debugging) { printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait ready\n", dev); @@ -632,7 +630,7 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned debugging = 0; } #endif - set_current_state(TASK_INTERRUPTIBLE); + current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ / 10); memset(cmd, 0, MAX_COMMAND_SIZE); @@ -660,66 +658,6 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned return 0; } -/* - * Wait for a tape to be inserted in the unit - */ -static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout) -{ - unsigned char cmd[MAX_COMMAND_SIZE]; - Scsi_Request * SRpnt; - long startwait = jiffies; -#if DEBUG - int dbg = debugging; - int dev = TAPE_NR(STp->devt); - - printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait for medium\n", dev); -#endif - - memset(cmd, 0, MAX_COMMAND_SIZE); - cmd[0] = TEST_UNIT_READY; - - SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE); - *aSRpnt = SRpnt; - if (!SRpnt) return (-EBUSY); - - while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) && - SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 0x3a && - SRpnt->sr_sense_buffer[13] == 0 ) { -#if DEBUG - if (debugging) { - printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait medium\n", dev); - printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev); - debugging = 0; - } -#endif - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); - - memset(cmd, 0, MAX_COMMAND_SIZE); - cmd[0] = TEST_UNIT_READY; - - SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE); - } - *aSRpnt = SRpnt; -#if DEBUG - debugging = dbg; -#endif - if ( STp->buffer->syscall_result && SRpnt->sr_sense_buffer[2] != 2 && - SRpnt->sr_sense_buffer[12] != 4 && SRpnt->sr_sense_buffer[13] == 1) { -#if DEBUG - printk(OSST_DEB_MSG "osst%d:D: Abnormal exit from onstream wait medium\n", dev); - printk(OSST_DEB_MSG "osst%d:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev, - STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2], - SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]); -#endif - return 0; - } -#if DEBUG - printk(OSST_DEB_MSG "osst%d:D: Normal exit from onstream wait medium\n", dev); -#endif - return 1; -} - static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame) { int retval; @@ -758,7 +696,7 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt) result = osst_write_error_recovery(STp, aSRpnt, 0); result |= osst_wait_ready(STp, aSRpnt, 5 * 60); - STp->ps[STp->partition].rw = OS_WRITING_COMPLETE; + STp->ps[STp->partition].rw = ST_IDLE; return (result); } @@ -807,7 +745,7 @@ static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, notyetprinted--; } #endif - set_current_state(TASK_INTERRUPTIBLE); + current->state = TASK_INTERRUPTIBLE; schedule_timeout (HZ / OSST_POLL_PER_SEC); } #if DEBUG @@ -965,8 +903,6 @@ static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in #endif if ( osst_initiate_read(STp, aSRpnt) || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) { - if (STp->raw) - return (-EIO); position = osst_get_frame_position(STp, aSRpnt); if (position >= 0xbae && position < 0xbb8) position = 0xbb8; @@ -1032,7 +968,7 @@ static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, in if (cnt > 1) { STp->recover_count++; STp->recover_erreg++; - printk(KERN_WARNING "osst%d:I: Don't worry, Read error at position %d recovered\n", + printk(KERN_WARNING "osst%d:I: Read error at position %d recovered\n", dev, STp->read_error_frame); } STp->read_count++; @@ -1589,10 +1525,7 @@ static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending); else retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending); - printk(KERN_WARNING "osst%d:%s: %sWrite error%srecovered\n", dev, - retval?"E" :"I", - retval?"" :"Don't worry, ", - retval?" not ":" "); + printk(KERN_WARNING "osst%d:I: Write error%srecovered\n", dev, retval?" not ":" "); break; case OS_WRITE_LAST_MARK: printk(KERN_ERR "osst%d:E: Bad frame in update last marker, fatal\n", dev); @@ -1663,7 +1596,7 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request * mt_count, last_mark_ppos); #endif if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) { - osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos); + osst_set_frame_position(STp, aSRpnt, last_mark_ppos, 0); if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { #if DEBUG printk(OSST_DEB_MSG @@ -1695,7 +1628,7 @@ static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request * #if DEBUG printk(OSST_DEB_MSG "osst%d:D: Positioning to last mark at %d\n", dev, last_mark_ppos); #endif - osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos); + osst_set_frame_position(STp, aSRpnt, last_mark_ppos, 0); cnt++; if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { #if DEBUG @@ -1822,7 +1755,7 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Reque #endif return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count); } else { - osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos); + osst_set_frame_position(STp, aSRpnt, next_mark_ppos, 0); if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { #if DEBUG printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", @@ -1862,7 +1795,7 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Reque #endif return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count); } - osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos); + osst_set_frame_position(STp, aSRpnt, STp->first_mark_ppos, 0); if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { #if DEBUG printk(OSST_DEB_MSG @@ -1894,7 +1827,7 @@ static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Reque #if DEBUG else printk(OSST_DEB_MSG "osst%d:D: Positioning to next mark at %d\n", dev, next_mark_ppos); #endif - osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos); + osst_set_frame_position(STp, aSRpnt, next_mark_ppos, 0); cnt++; if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) { #if DEBUG @@ -2531,7 +2464,7 @@ static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt) } #if DEBUG - printk(KERN_INFO "osst%d:D: Drive Block Size changed to 32.5K\n", dev); + printk(KERN_INFO "osst%d:D: Block Size changed to 32.5K\n", dev); /* * In debug mode, we want to see as many errors as possible * to test the error recovery mechanism. @@ -3469,7 +3402,6 @@ static ssize_t osst_read(struct file * filp, char * buf, size_t count, loff_t *p if (retval) goto out; STps->rw = ST_IDLE; - /* FIXME -- this may leave the tape without EOD and up2date headers */ } if ((count % STp->block_size) != 0) { @@ -3882,10 +3814,6 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned i ioctl_result = osst_flush_write_buffer(STp, &SRpnt); else ioctl_result = 0; -#if DEBUG - if (debugging) - printk(OSST_DEB_MSG "osst%d:D: Writing %ld filemark(s).\n", dev, arg); -#endif for (i=0; i<arg; i++) ioctl_result |= osst_write_filemark(STp, &SRpnt); if (fileno >= 0) fileno += arg; @@ -3905,9 +3833,14 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned i cmd[4] = arg; timeout = STp->timeout; #if DEBUG - if (debugging) - printk(OSST_DEB_MSG "osst%d:D: Writing %d setmark(s).\n", dev, + if (debugging) { + if (cmd_in == MTWEOF) + printk(OSST_DEB_MSG "osst%d:D: Writing %d filemarks.\n", dev, + cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); + else + printk(OSST_DEB_MSG "osst%d:D: Writing %d setmarks.\n", dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); + } #endif if (fileno >= 0) fileno += arg; @@ -3920,12 +3853,8 @@ static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned i case MTRETEN: cmd[0] = START_STOP; cmd[1] = 1; /* Don't wait for completion */ - if (cmd_in == MTLOAD) { - if (STp->ready == ST_NO_TAPE) - cmd[4] = 4; /* open tray */ - else + if (cmd_in == MTLOAD) cmd[4] = 1; /* load */ - } if (cmd_in == MTRETEN) cmd[4] = 3; /* retension then mount */ if (cmd_in == MTOFFL) @@ -4064,7 +3993,7 @@ os_bypass: printk(OSST_DEB_MSG "osst%d:D: IOCTL (%d) Result=%d\n", dev, cmd_in, ioctl_result); #endif - if (!ioctl_result) { /* success */ + if (!ioctl_result) { if (cmd_in == MTFSFM) { fileno--; @@ -4141,8 +4070,6 @@ os_bypass: if (cmd_in == MTLOCK) STp->door_locked = ST_LOCK_FAILS; - if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60)) - ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60); } *aSRpnt = SRpnt; @@ -4183,7 +4110,6 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) __MOD_INC_USE_COUNT(STp->device->host->hostt->module); if (osst_template.module) __MOD_INC_USE_COUNT(osst_template.module); - STp->device->access_count++; if (mode != STp->current_mode) { #if DEBUG @@ -4200,8 +4126,6 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY); STp->raw = (minor(inode->i_rdev) & 0x40) != 0; - if (STp->raw) - STp->header_ok = 0; /* Allocate a buffer for this user */ need_dma_buffer = STp->restr_dma; @@ -4292,7 +4216,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) STp->nbr_partitions = 1; /* This guess will be updated later if necessary */ for (i=0; i < ST_NBR_PARTITIONS; i++) { STps = &(STp->ps[i]); - STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */ + STps->rw = ST_IDLE; /* FIXME - seems to be redundant... */ STps->eof = ST_NOEOF; STps->at_sm = 0; STps->last_block_valid = FALSE; @@ -4340,8 +4264,8 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) STp->door_locked = ST_LOCKED_AUTO; } if (!STp->frame_in_buffer) { - STp->block_size = (STm->default_blksize > 0) ? - STm->default_blksize : OS_DATA_SIZE; + STp->block_size = (STp->raw) ? OS_FRAME_SIZE : ( + (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE); STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0; } STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size; @@ -4434,6 +4358,8 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) return 0; } + STp->min_block = STp->max_block = (-1); + osst_configure_onstream(STp, &SRpnt); /* STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0; FIXME */ @@ -4460,9 +4386,11 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) } else STp->buffer->aux = NULL; /* this had better never happen! */ - STp->block_size = STp->raw ? OS_FRAME_SIZE : ( + STp->block_size = (STp->raw) ? OS_FRAME_SIZE : ( (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE); - STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size; + STp->min_block = 512; + STp->max_block = OS_DATA_SIZE; + STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size; STp->buffer->buffer_bytes = STp->buffer->read_pointer = STp->frame_in_buffer = 0; @@ -4520,8 +4448,6 @@ err_out: STp->buffer = NULL; } STp->in_use = 0; - STp->header_ok = 0; - STp->device->access_count--; if (STp->device->host->hostt->module) __MOD_DEC_USE_COUNT(STp->device->host->hostt->module); @@ -4558,7 +4484,7 @@ static int os_scsi_tape_flush(struct file * filp) if (result != 0 && result != (-ENOSPC)) goto out; } - if ( STps->rw >= ST_WRITING && !(STp->device)->was_reset) { + if ( STps->rw == ST_WRITING && !(STp->device)->was_reset) { #if DEBUG if (debugging) { @@ -4568,17 +4494,16 @@ static int os_scsi_tape_flush(struct file * filp) dev, STp->nbr_waits, STp->nbr_finished); } #endif - if (STp->write_type != OS_WRITE_NEW_MARK) { - /* true unless the user wrote the filemark for us */ - result = osst_flush_drive_buffer(STp, &SRpnt); - if (result < 0) goto out; - result = osst_write_filemark(STp, &SRpnt); - if (result < 0) goto out; - if (STps->drv_file >= 0) - STps->drv_file++ ; - STps->drv_block = 0; - } + result = osst_flush_drive_buffer(STp, &SRpnt); + if (result < 0) goto out; + result = osst_write_filemark(STp, &SRpnt); + if (result < 0) goto out; + + if (STps->drv_file >= 0) + STps->drv_file++ ; + STps->drv_block = 0; + result = osst_write_eod(STp, &SRpnt); osst_write_header(STp, &SRpnt, !(STp->rew_at_close)); @@ -4662,12 +4587,7 @@ static int os_scsi_tape_close(struct inode * inode, struct file * filp) if (STp->buffer != NULL) STp->buffer->in_use = 0; - if (STp->raw) - STp->header_ok = 0; - STp->in_use = 0; - STp->device->access_count--; - if (STp->device->host->hostt->module) __MOD_DEC_USE_COUNT(STp->device->host->hostt->module); if(osst_template.module) @@ -4717,10 +4637,7 @@ static int osst_ioctl(struct inode * inode,struct file * file, cmd_type = _IOC_TYPE(cmd_in); cmd_nr = _IOC_NR(cmd_in); -#if DEBUG - printk(OSST_DEB_MSG "osst%d:D: Ioctl %d,%d in %s mode\n", dev, - cmd_type, cmd_nr, STp->raw?"raw":"normal"); -#endif + if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) { struct mtop mtc; @@ -4803,8 +4720,8 @@ static int osst_ioctl(struct inode * inode,struct file * file, } } - if (mtc.mt_op != MTNOP && mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM && - mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETBLK && + if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK && + mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTWSM && mtc.mt_op != MTSETDRVBUFFER && mtc.mt_op != MTSETPART) STps->rw = ST_IDLE; /* Prevent automatic WEOF and fsf */ @@ -4856,10 +4773,7 @@ static int osst_ioctl(struct inode * inode,struct file * file, } if (mtc.mt_op == MTSEEK) { - if (STp->raw) - i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0); - else - i = osst_seek_sector(STp, &SRpnt, mtc.mt_count); + i = osst_seek_sector(STp, &SRpnt, mtc.mt_count); if (!STp->can_partitions) STp->ps[0].rw = ST_IDLE; retval = i; @@ -4964,10 +4878,7 @@ static int osst_ioctl(struct inode * inode,struct file * file, retval = (-EINVAL); goto out; } - if (STp->raw) - blk = osst_get_frame_position(STp, &SRpnt); - else - blk = osst_get_sector(STp, &SRpnt); + blk = osst_get_sector(STp, &SRpnt); if (blk < 0) { retval = blk; goto out; @@ -5061,7 +4972,7 @@ static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma ) tb = NULL; break; } - tb->sg[segs].page = NULL; + tb->sg[segs].page = NULL; tb->sg[segs].length = b_size; got += b_size; segs++; @@ -5513,8 +5424,6 @@ static int osst_attach(Scsi_Device * SDp) tpnt->partition = 0; tpnt->new_partition = 0; tpnt->nbr_partitions = 0; - tpnt->min_block = 512; - tpnt->max_block = OS_DATA_SIZE; tpnt->timeout = OSST_TIMEOUT; tpnt->long_timeout = OSST_LONG_TIMEOUT; @@ -5554,7 +5463,6 @@ static int osst_attach(Scsi_Device * SDp) tpnt->current_mode = 0; tpnt->modes[0].defined = TRUE; - tpnt->modes[2].defined = TRUE; tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = FALSE; init_MUTEX(&tpnt->lock); diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h index 089433262..f3ecb546e 100644 --- a/drivers/scsi/osst.h +++ b/drivers/scsi/osst.h @@ -1,5 +1,5 @@ /* - * $Header: /home/cvsroot/Driver/osst.h,v 1.12 2001/10/11 00:30:15 riede Exp $ + * $Header: /home/cvsroot/Driver/osst.h,v 1.11 2001/01/26 01:54:49 riede Exp $ */ #include <asm/byteorder.h> @@ -638,5 +638,3 @@ typedef struct { #define OS_WRITE_HEADER 4 #define OS_WRITE_FILLER 5 -/* Additional rw state */ -#define OS_WRITING_COMPLETE 3 diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 05b5dae41..909b8c6cb 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -19,9 +19,9 @@ */ #include <linux/config.h> #ifdef CONFIG_PROC_FS - static char sg_version_str[] = "Version: 3.1.22 (20011128)"; + static char sg_version_str[] = "Version: 3.1.20 (20010814)"; #endif - static int sg_version_num = 30122; /* 2 digits for each component */ + static int sg_version_num = 30120; /* 2 digits for each component */ /* * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First @@ -82,8 +82,6 @@ static void sg_proc_cleanup(void); #include <linux/iobuf.h> #endif -#define SG_NEW_KIOVEC 0 /* use alloc_kiovec(), not alloc_kiovec_sz() */ - int sg_big_buff = SG_DEF_RESERVED_SIZE; /* N.B. This variable is readable and writeable via /proc/scsi/sg/def_reserved_size . Each time sg_open() is called a buffer @@ -138,10 +136,10 @@ static struct Scsi_Device_Template sg_template = typedef struct sg_scatter_hold /* holding area for scsi scatter gather info */ { unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */ - unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */ + unsigned short sglist_len; /* size of malloc'd scatter-gather list */ unsigned bufflen; /* Size of (aggregate) data buffer */ unsigned b_malloc_len; /* actual len malloc'ed in buffer */ - void * buffer; /* Data buffer or scatter list + mem_src_arr */ + void * buffer; /* Data buffer or scatter list,12 bytes each*/ struct kiobuf * kiobp; /* for direct IO information */ char mapped; /* indicates kiobp has locked pages */ char buffer_mem_src; /* heap whereabouts of 'buffer' */ @@ -184,7 +182,6 @@ typedef struct sg_fd /* holds the state of a file descriptor */ char cmd_q; /* 1 -> allow command queuing, 0 -> don't */ char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */ char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ - char mmap_called; /* 0 -> mmap() never called on this fd */ } Sg_fd; /* 2760 bytes long on i386 */ typedef struct sg_device /* holds the state of each scsi generic device */ @@ -206,8 +203,7 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt); static int sg_start_req(Sg_request * srp); static void sg_finish_rem_req(Sg_request * srp); static int sg_build_indi(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size); -static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, - int tablesize); +static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp); static ssize_t sg_new_read(Sg_fd * sfp, char * buf, size_t count, Sg_request * srp); static ssize_t sg_new_write(Sg_fd * sfp, const char * buf, size_t count, @@ -237,14 +233,13 @@ static Sg_request * sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request * sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); static int sg_res_in_use(Sg_fd * sfp); +static void sg_clr_srpnt(Scsi_Request * SRpnt); static int sg_ms_to_jif(unsigned int msecs); -static inline unsigned sg_jif_to_ms(int jifs); +static unsigned sg_jif_to_ms(int jifs); static int sg_allow_access(unsigned char opcode, char dev_type); static int sg_build_dir(Sg_request * srp, Sg_fd * sfp, int dxfer_len); static void sg_unmap_and(Sg_scatter_hold * schp, int free_also); static Sg_device * sg_get_dev(int dev); -static inline int sg_alloc_kiovec(int nr, struct kiobuf **bufp, int *szp); -static inline void sg_free_kiovec(int nr, struct kiobuf **bufp, int *szp); #ifdef CONFIG_PROC_FS static int sg_last_dev(void); #endif @@ -620,20 +615,6 @@ static ssize_t sg_new_write(Sg_fd * sfp, const char * buf, size_t count, sg_remove_request(sfp, srp); return -ENOSYS; } - if (hp->flags & SG_FLAG_MMAP_IO) { - if (hp->dxfer_len > sfp->reserve.bufflen) { - sg_remove_request(sfp, srp); - return -ENOMEM; /* MMAP_IO size must fit in reserve buffer */ - } - if (hp->flags & SG_FLAG_DIRECT_IO) { - sg_remove_request(sfp, srp); - return -EINVAL; /* either MMAP_IO or DIRECT_IO (not both) */ - } - if (sg_res_in_use(sfp)) { - sg_remove_request(sfp, srp); - return -EBUSY; /* reserve buffer already being used */ - } - } timeout = sg_ms_to_jif(srp->header.timeout); if ((! hp->cmdp) || (hp->cmd_len < 6) || (hp->cmd_len > sizeof(cmnd))) { sg_remove_request(sfp, srp); @@ -734,9 +715,7 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp, (void *)SRpnt->sr_buffer, hp->dxfer_len, sg_cmd_done_bh, timeout, SG_DEFAULT_RETRIES); /* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1) generic_unplug_device(q); -#endif return 0; } @@ -870,7 +849,7 @@ static int sg_ioctl(struct inode * inode, struct file * filp, result = get_user(val, (int *)arg); if (result) return result; if (val != sfp->reserve.bufflen) { - if (sg_res_in_use(sfp) || sfp->mmap_called) + if (sg_res_in_use(sfp)) return -EBUSY; sg_remove_scat(&sfp->reserve); sg_build_reserve(sfp, val); @@ -1051,136 +1030,6 @@ static int sg_fasync(int fd, struct file * filp, int mode) return (retval < 0) ? retval : 0; } -static void sg_rb_correct4mmap(Sg_scatter_hold * rsv_schp, int startFinish) -{ - void * page_ptr; - struct page * page; - int k, m; - - SCSI_LOG_TIMEOUT(3, printk("sg_rb_correct4mmap: startFinish=%d, " - "scatg=%d\n", startFinish, rsv_schp->k_use_sg)); - /* N.B. correction _not_ applied to base page of aech allocation */ - if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */ - struct scatterlist * sclp = rsv_schp->buffer; - - for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) { - for (m = PAGE_SIZE; m < sclp->length; m += PAGE_SIZE) { - page = sclp->page; - if (startFinish) - get_page(page); /* increment page count */ - else { - if (page_count(page) > 0) - put_page_testzero(page); /* decrement page count */ - } - } - } - } - else { /* reserve buffer is just a single allocation */ - for (m = PAGE_SIZE; m < rsv_schp->bufflen; m += PAGE_SIZE) { - page_ptr = (unsigned char *)rsv_schp->buffer + m; - page = virt_to_page(page_ptr); - if (startFinish) - get_page(page); /* increment page count */ - else { - if (page_count(page) > 0) - put_page_testzero(page); /* decrement page count */ - } - } - } -} - -static struct page * sg_vma_nopage(struct vm_area_struct *vma, - unsigned long addr, int unused) -{ - Sg_fd * sfp; - struct page * page = NOPAGE_SIGBUS; - void * page_ptr = NULL; - unsigned long offset; - Sg_scatter_hold * rsv_schp; - - if ((NULL == vma) || (! (sfp = (Sg_fd *)vma->vm_private_data))) - return page; - rsv_schp = &sfp->reserve; - offset = addr - vma->vm_start; - if (offset >= rsv_schp->bufflen) - return page; - SCSI_LOG_TIMEOUT(3, printk("sg_vma_nopage: offset=%lu, scatg=%d\n", - offset, rsv_schp->k_use_sg)); - if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */ - int k; - unsigned long sa = vma->vm_start; - unsigned long len; - struct scatterlist * sclp = rsv_schp->buffer; - - for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); - ++k, ++sclp) { - len = vma->vm_end - sa; - len = (len < sclp->length) ? len : sclp->length; - if (offset < len) { - get_page(sclp->page); /* increment page count */ - break; - } - sa += len; - offset -= len; - } - } - else { /* reserve buffer is just a single allocation */ - page_ptr = (unsigned char *)rsv_schp->buffer + offset; - page = virt_to_page(page_ptr); - get_page(page); /* increment page count */ - } - return page; -} - -static struct vm_operations_struct sg_mmap_vm_ops = { - nopage : sg_vma_nopage, -}; - -static int sg_mmap(struct file * filp, struct vm_area_struct *vma) -{ - Sg_fd * sfp; - unsigned long req_sz = vma->vm_end - vma->vm_start; - Sg_scatter_hold * rsv_schp; - - if ((! filp) || (! vma) || (! (sfp = (Sg_fd *)filp->private_data))) - return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_mmap starting, vm_start=%p, len=%d\n", - (void *)vma->vm_start, (int)req_sz)); - if (vma->vm_pgoff) - return -EINVAL; /* want no offset */ - rsv_schp = &sfp->reserve; - if (req_sz > rsv_schp->bufflen) - return -ENOMEM; /* cannot map more than reserved buffer */ - - if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */ - int k; - unsigned long sa = vma->vm_start; - unsigned long len; - struct scatterlist * sclp = rsv_schp->buffer; - - for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end); - ++k, ++sclp) { - if ((unsigned long)sclp->offset & (PAGE_SIZE - 1)) - return -EFAULT; /* non page aligned memory ?? */ - len = vma->vm_end - sa; - len = (len < sclp->length) ? len : sclp->length; - sa += len; - } - } - else { /* reserve buffer is just a single allocation */ - if ((unsigned long)rsv_schp->buffer & (PAGE_SIZE - 1)) - return -EFAULT; /* non page aligned memory ?? */ - } - if (0 == sfp->mmap_called) { - sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */ - sfp->mmap_called = 1; - } - vma->vm_flags |= (VM_RESERVED | VM_IO); - vma->vm_private_data = sfp; - vma->vm_ops = &sg_mmap_vm_ops; - return 0; -} - /* This function is a "bottom half" handler that is called by the * mid level when a command is completed (or has failed). */ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt) @@ -1227,14 +1076,7 @@ static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt) srp->data.sglist_len = SRpnt->sr_sglist_len; srp->data.bufflen = SRpnt->sr_bufflen; srp->data.buffer = SRpnt->sr_buffer; - /* now clear out request structure */ - SRpnt->sr_use_sg = 0; - SRpnt->sr_sglist_len = 0; - SRpnt->sr_bufflen = 0; - SRpnt->sr_buffer = NULL; - SRpnt->sr_underflow = 0; - SRpnt->sr_request.rq_dev = mk_kdev(0, 0); /* "sg" _disowns_ command blk */ - + sg_clr_srpnt(SRpnt); srp->my_cmdp = NULL; srp->done = 1; read_unlock(&sg_dev_arr_lock); @@ -1310,7 +1152,6 @@ static struct file_operations sg_fops = { poll: sg_poll, ioctl: sg_ioctl, open: sg_open, - mmap: sg_mmap, release: sg_release, fasync: sg_fasync, }; @@ -1335,7 +1176,7 @@ static int sg_init() if(!sg_registered) { if (devfs_register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) { - printk(KERN_ERR "Unable to get major %d for generic SCSI device\n", + printk("Unable to get major %d for generic SCSI device\n", SCSI_GENERIC_MAJOR); write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return 1; @@ -1348,7 +1189,7 @@ static int sg_init() sg_dev_arr = (Sg_device **)kmalloc(sg_template.dev_max * sizeof(Sg_device *), GFP_ATOMIC); if (NULL == sg_dev_arr) { - printk(KERN_ERR "sg_init: no space for sg_dev_arr\n"); + printk("sg_init: no space for sg_dev_arr\n"); write_unlock_irqrestore(&sg_dev_arr_lock, iflags); return 1; } @@ -1371,8 +1212,8 @@ static int __init sg_def_reserved_size_setup(char *str) sg_big_buff = tmp; return 1; } else { - printk(KERN_WARNING "sg_def_reserved_size : usage " - "sg_def_reserved_size=n (n could be 65536, 131072 or 262144)\n"); + printk("sg_def_reserved_size : usage sg_def_reserved_size=n " + "(n could be 65536, 131072 or 262144)\n"); return 0; } } @@ -1397,7 +1238,7 @@ static int sg_attach(Scsi_Device * scsidp) if (NULL == tmp_da) { scsidp->attached--; write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - printk(KERN_ERR "sg_attach: device array cannot be resized\n"); + printk("sg_attach: device array cannot be resized\n"); return 1; } memset(tmp_da, 0, tmp_dev_max * sizeof(Sg_device *)); @@ -1412,7 +1253,7 @@ static int sg_attach(Scsi_Device * scsidp) if (k > MINORMASK) { scsidp->attached--; write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - printk(KERN_WARNING "Unable to attach sg device <%d, %d, %d, %d>" + printk("Unable to attach sg device <%d, %d, %d, %d>" " type=%d, minor number exceed %d\n", scsidp->host->host_no, scsidp->channel, scsidp->id, scsidp->lun, scsidp->type, MINORMASK); @@ -1425,7 +1266,7 @@ static int sg_attach(Scsi_Device * scsidp) if (NULL == sdp) { scsidp->attached--; write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - printk(KERN_ERR "sg_attach: Sg_device cannot be allocated\n"); + printk("sg_attach: Sg_device cannot be allocated\n"); return 1; } @@ -1452,8 +1293,8 @@ static int sg_attach(Scsi_Device * scsidp) case TYPE_WORM: case TYPE_TAPE: break; default: - printk(KERN_NOTICE "Attached scsi generic sg%d at scsi%d, channel" - " %d, id %d, lun %d, type %d\n", k, scsidp->host->host_no, + printk("Attached scsi generic sg%d at scsi%d, channel %d, id %d," + " lun %d, type %d\n", k, scsidp->host->host_no, scsidp->channel, scsidp->id, scsidp->lun, scsidp->type); } return 0; @@ -1530,10 +1371,7 @@ static void sg_detach(Scsi_Device * scsidp) MODULE_AUTHOR("Douglas Gilbert"); MODULE_DESCRIPTION("SCSI generic (sg) driver"); - -#ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); -#endif MODULE_PARM(def_reserved_size, "i"); MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); @@ -1579,8 +1417,9 @@ static int sg_start_req(Sg_request * srp) if (res <= 0) /* -ve -> error, 0 -> done, 1 -> try indirect */ return res; } - if ((! sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) + if ((! sg_res_in_use(sfp)) && (dxfer_len <= rsv_schp->bufflen)) { sg_link_reserve(sfp, srp, dxfer_len); + } else { res = sg_build_indi(req_schp, sfp, dxfer_len); if (res) { @@ -1606,24 +1445,23 @@ static void sg_finish_rem_req(Sg_request * srp) sg_remove_request(sfp, srp); } -static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, - int tablesize) +static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp) { int mem_src, ret_sz; + int sg_bufflen = PAGE_SIZE; int elem_sz = sizeof(struct scatterlist) + sizeof(char); - /* scatter gather array, followed by mem_src_arr (array of chars) */ - int sg_bufflen = tablesize * elem_sz; - int mx_sc_elems = tablesize; + int mx_sc_elems = (sg_bufflen / elem_sz) - 1; mem_src = SG_HEAP_KMAL; - schp->buffer = sg_malloc(sfp, sg_bufflen, &ret_sz, &mem_src); + schp->buffer = (struct scatterlist *)sg_malloc(sfp, sg_bufflen, + &ret_sz, &mem_src); + schp->buffer_mem_src = (char)mem_src; if (! schp->buffer) return -ENOMEM; else if (ret_sz != sg_bufflen) { sg_bufflen = ret_sz; - mx_sc_elems = sg_bufflen / elem_sz; + mx_sc_elems = (sg_bufflen / elem_sz) - 1; } - schp->buffer_mem_src = (char)mem_src; schp->sglist_len = sg_bufflen; memset(schp->buffer, 0, sg_bufflen); return mx_sc_elems; /* number of scat_gath elements allocated */ @@ -1632,15 +1470,13 @@ static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, static void sg_unmap_and(Sg_scatter_hold * schp, int free_also) { #ifdef SG_ALLOW_DIO_CODE - int nbhs = 0; - if (schp && schp->kiobp) { if (schp->mapped) { unmap_kiobuf(schp->kiobp); schp->mapped = 0; } if (free_also) { - sg_free_kiovec(1, &schp->kiobp, &nbhs); + free_kiovec(1, &schp->kiobp); schp->kiobp = NULL; } } @@ -1658,12 +1494,10 @@ static int sg_build_dir(Sg_request * srp, Sg_fd * sfp, int dxfer_len) sg_io_hdr_t * hp = &srp->header; Sg_scatter_hold * schp = &srp->data; int sg_tablesize = sfp->parentdp->sg_tablesize; - int nbhs = 0; - res = sg_alloc_kiovec(1, &schp->kiobp, &nbhs); + res = alloc_kiovec(1, &schp->kiobp); if (0 != res) { - SCSI_LOG_TIMEOUT(5, printk("sg_build_dir: sg_alloc_kiovec res=%d\n", - res)); + SCSI_LOG_TIMEOUT(5, printk("sg_build_dir: alloc_kiovec res=%d\n", res)); return 1; } res = map_user_kiobuf((SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0, @@ -1693,7 +1527,7 @@ static int sg_build_dir(Sg_request * srp, Sg_fd * sfp, int dxfer_len) hp->info |= SG_INFO_DIRECT_IO; return 0; } - mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize); + mx_sc_elems = sg_build_sgat(schp, sfp); if (mx_sc_elems <= 1) { sg_unmap_and(schp, 1); sg_remove_scat(schp); @@ -1701,7 +1535,7 @@ static int sg_build_dir(Sg_request * srp, Sg_fd * sfp, int dxfer_len) } mem_src_arr = schp->buffer + (mx_sc_elems * sizeof(struct scatterlist)); for (k = 0, sclp = schp->buffer, rem_sz = dxfer_len; - (rem_sz > 0) && (k < mx_sc_elems); + (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems); ++k, ++sclp) { offset = (0 == k) ? kp->offset : 0; num = (rem_sz > (PAGE_SIZE - offset)) ? (PAGE_SIZE - offset) : @@ -1712,8 +1546,8 @@ static int sg_build_dir(Sg_request * srp, Sg_fd * sfp, int dxfer_len) mem_src_arr[k] = SG_USER_MEM; rem_sz -= num; SCSI_LOG_TIMEOUT(5, - printk("sg_build_dir: k=%d, a=0x%p, off=%d, len=%d, ms=%d\n", - k, page_address(sclp->page), sclp->offset, num, mem_src_arr[k])); + printk("sg_build_dir: k=%d, a=0x%p, len=%d, ms=%d\n", + k, page_address(sclp->page) + sclp->offset, num, mem_src_arr[k])); } schp->k_use_sg = k; SCSI_LOG_TIMEOUT(5, @@ -1775,14 +1609,14 @@ static int sg_build_indi(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) char * mem_src_arr; /* N.B. ret_sz and mem_src carried into this block ... */ - mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize); + mx_sc_elems = sg_build_sgat(schp, sfp); if (mx_sc_elems < 0) return mx_sc_elems; /* most likely -ENOMEM */ mem_src_arr = schp->buffer + (mx_sc_elems * sizeof(struct scatterlist)); for (k = 0, sclp = schp->buffer, rem_sz = blk_size; - (rem_sz > 0) && (k < mx_sc_elems); + (k < sg_tablesize) && (rem_sz > 0) && (k < mx_sc_elems); ++k, rem_sz -= ret_sz, ++sclp) { if (first) first = 0; @@ -1793,14 +1627,14 @@ static int sg_build_indi(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) if (! p) break; } - sclp->page = virt_to_page(p); + sclp->page = virt_to_page(p); sclp->offset = ((unsigned long)p & ~PAGE_MASK); sclp->length = ret_sz; mem_src_arr[k] = mem_src; SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d, ms=%d\n", - k, page_address(sclp->page), ret_sz, mem_src)); + k, page_address(sclp->page) + sclp->offset, ret_sz, mem_src)); } /* end of for loop */ schp->k_use_sg = k; SCSI_LOG_TIMEOUT(5, @@ -1830,8 +1664,7 @@ static int sg_write_xfer(Sg_request * srp) if (schp->bufflen < num_xfer) num_xfer = schp->bufflen; } - if ((num_xfer <= 0) || - (new_interface && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags))) + if ((num_xfer <= 0) || (new_interface && (SG_FLAG_NO_DXFER & hp->flags))) return 0; SCSI_LOG_TIMEOUT(4, @@ -1873,7 +1706,7 @@ static int sg_write_xfer(Sg_request * srp) for (; (k < schp->k_use_sg) && p; ++k, ++sclp, ksglen = (int)sclp->length, - p = page_address(sclp->page) + sclp->offset) { + p = page_address(sclp->page) + sclp->offset) { ok = (SG_USER_MEM != mem_src_arr[k]); if (usglen <= 0) break; @@ -1934,7 +1767,7 @@ static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind, static char * sg_get_sgat_msa(Sg_scatter_hold * schp) { int elem_sz = sizeof(struct scatterlist) + sizeof(char); - int mx_sc_elems = schp->sglist_len / elem_sz; + int mx_sc_elems = (schp->sglist_len / elem_sz) - 1; return schp->buffer + (sizeof(struct scatterlist) * mx_sc_elems); } @@ -1951,9 +1784,9 @@ static void sg_remove_scat(Sg_scatter_hold * schp) mem_src = mem_src_arr[k]; SCSI_LOG_TIMEOUT(5, printk("sg_remove_scat: k=%d, a=0x%p, len=%d, ms=%d\n", - k, page_address(sclp->page), sclp->length, mem_src)); + k, page_address(sclp->page) + sclp->offset, sclp->length, mem_src)); sg_free(page_address(sclp->page) + sclp->offset, sclp->length, mem_src); - sclp->page = NULL; + sclp->page = NULL; sclp->length = 0; } sg_free(schp->buffer, schp->sglist_len, schp->buffer_mem_src); @@ -1981,8 +1814,7 @@ static int sg_read_xfer(Sg_request * srp) if (schp->bufflen < num_xfer) num_xfer = schp->bufflen; } - if ((num_xfer <= 0) || - (new_interface && ((SG_FLAG_NO_DXFER | SG_FLAG_MMAP_IO) & hp->flags))) + if ((num_xfer <= 0) || (new_interface && (SG_FLAG_NO_DXFER & hp->flags))) return 0; SCSI_LOG_TIMEOUT(4, @@ -2024,7 +1856,7 @@ static int sg_read_xfer(Sg_request * srp) for (; (k < schp->k_use_sg) && p; ++k, ++sclp, ksglen = (int)sclp->length, - p = page_address(sclp->page) + sclp->offset) { + p = page_address(sclp->page) + sclp->offset) { ok = (SG_USER_MEM != mem_src_arr[k]); if (usglen <= 0) break; @@ -2358,8 +2190,6 @@ static void __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) if (sfp->reserve.bufflen > 0) { SCSI_LOG_TIMEOUT(6, printk("__sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", (int)sfp->reserve.bufflen, (int)sfp->reserve.k_use_sg)); - if (sfp->mmap_called) - sg_rb_correct4mmap(&sfp->reserve, 0); /* undo correction */ sg_remove_scat(&sfp->reserve); } sfp->parentdp = NULL; @@ -2408,7 +2238,7 @@ static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) /* MOD_INC's to inhibit unloading sg and associated adapter driver */ if (sg_template.module) __MOD_INC_USE_COUNT(sg_template.module); - if (sdp->device->host->hostt->module) + if (sdp->device->host->hostt->module) __MOD_INC_USE_COUNT(sdp->device->host->hostt->module); SCSI_LOG_TIMEOUT(1, printk( "sg_remove_sfp: worrisome, %d writes pending\n", dirty)); @@ -2482,8 +2312,7 @@ static char * sg_low_malloc(int rqSz, int lowDma, int mem_src, int * retSzp) if (retSzp) *retSzp = resSz; } else - printk(KERN_ERR "sg_low_malloc: bad mem_src=%d, rqSz=%df\n", - mem_src, rqSz); + printk("sg_low_malloc: bad mem_src=%d, rqSz=%df\n", mem_src, rqSz); return resp; } @@ -2518,7 +2347,7 @@ static char * sg_malloc(const Sg_fd * sfp, int size, int * retSzp, if (resp && retSzp) *retSzp = size; break; case SG_HEAP_KMAL: - l_ms = SG_HEAP_KMAL; /* was SG_HEAP_PAGE */ + l_ms = SG_HEAP_PAGE; resp = sg_low_malloc(size, low_dma, l_ms, 0); if (resp) break; @@ -2537,15 +2366,6 @@ static char * sg_malloc(const Sg_fd * sfp, int size, int * retSzp, return resp; } -static inline int sg_alloc_kiovec(int nr, struct kiobuf **bufp, int *szp) -{ -#if SG_NEW_KIOVEC - return alloc_kiovec_sz(nr, bufp, szp); -#else - return alloc_kiovec(nr, bufp); -#endif -} - static void sg_low_free(char * buff, int size, int mem_src) { if (! buff) return; @@ -2573,7 +2393,7 @@ static void sg_low_free(char * buff, int size, int mem_src) case SG_USER_MEM: break; /* nothing to do */ default: - printk(KERN_ERR "sg_low_free: bad mem_src=%d, buff=0x%p, rqSz=%d\n", + printk("sg_low_free: bad mem_src=%d, buff=0x%p, rqSz=%d\n", mem_src, buff, size); break; } @@ -2589,13 +2409,14 @@ static void sg_free(char * buff, int size, int mem_src) sg_low_free(buff, size, mem_src); } -static inline void sg_free_kiovec(int nr, struct kiobuf **bufp, int *szp) +static void sg_clr_srpnt(Scsi_Request * SRpnt) { -#if SG_NEW_KIOVEC - free_kiovec_sz(nr, bufp, szp); -#else - free_kiovec(nr, bufp); -#endif + SRpnt->sr_use_sg = 0; + SRpnt->sr_sglist_len = 0; + SRpnt->sr_bufflen = 0; + SRpnt->sr_buffer = NULL; + SRpnt->sr_underflow = 0; + SRpnt->sr_request.rq_dev = mk_kdev(0, 0); /* "sg" _disowns_ command blk */ } static int sg_ms_to_jif(unsigned int msecs) @@ -2607,7 +2428,7 @@ static int sg_ms_to_jif(unsigned int msecs) : (((int)msecs / 1000) * HZ); } -static inline unsigned sg_jif_to_ms(int jifs) +static unsigned sg_jif_to_ms(int jifs) { if (jifs <= 0) return 0U; @@ -2657,8 +2478,8 @@ static Sg_device * sg_get_dev(int dev) if (sg_dev_arr && (dev >= 0)) { read_lock_irqsave(&sg_dev_arr_lock, iflags); - if (dev < sg_template.dev_max) - sdp = sg_dev_arr[dev]; + if (dev < sg_template.dev_max) + sdp = sg_dev_arr[dev]; read_unlock_irqrestore(&sg_dev_arr_lock, iflags); } return sdp; @@ -2851,7 +2672,7 @@ static int sg_proc_debug_info(char * buffer, int * len, off_t * begin, { Sg_device * sdp; const sg_io_hdr_t * hp; - int j, max_dev, new_interface; + int j, max_dev; if (NULL == sg_dev_arr) { PRINT_PROC("sg_dev_arr NULL, driver not initialized\n"); @@ -2897,10 +2718,8 @@ static int sg_proc_debug_info(char * buffer, int * len, off_t * begin, (int)fp->keep_orphan, (int)fp->closed); for (m = 0; (srp = sg_get_nth_request(fp, m)); ++m) { hp = &srp->header; - new_interface = (hp->interface_id == '\0') ? 0 : 1; /* stop indenting so far ... */ - PRINT_PROC(srp->res_used ? ((new_interface && - (SG_FLAG_MMAP_IO & hp->flags)) ? " mmap>> " : " rb>> ") : + PRINT_PROC(srp->res_used ? " rb>> " : ((SG_INFO_DIRECT_IO_MASK & hp->info) ? " dio>> " : " ")); blen = srp->my_cmdp ? srp->my_cmdp->sr_bufflen : srp->data.bufflen; usg = srp->my_cmdp ? srp->my_cmdp->sr_use_sg : srp->data.k_use_sg; @@ -2910,8 +2729,8 @@ static int sg_proc_debug_info(char * buffer, int * len, off_t * begin, if (srp->done) PRINT_PROC(" dur=%d", hp->duration); else - PRINT_PROC(" t_o/elap=%d/%d", new_interface ? hp->timeout : - sg_jif_to_ms(fp->timeout), + PRINT_PROC(" t_o/elap=%d/%d", ((hp->interface_id == '\0') ? + sg_jif_to_ms(fp->timeout) : hp->timeout), sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0)); PRINT_PROC("ms sgat=%d op=0x%02x\n", usg, (int)srp->data.cmd_opcode); /* reset indenting */ diff --git a/include/scsi/sg.h b/include/scsi/sg.h index 863b89120..26ee7fea2 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h @@ -11,20 +11,9 @@ Original driver (sg.h): Version 2 and 3 extensions to driver: * Copyright (C) 1998 - 2001 Douglas Gilbert - Version: 3.1.22 (20011128) + Version: 3.1.20 (20010814) This version is for 2.4 series kernels. - Changes since 3.1.21 (20011029) - - add support for SG_FLAG_MMAP_IO [permit mmap() on sg devices] - - update documentation pointers in this header - - put KERNEL_VERSION macros around code that breaks early 2.4 series - - switch back to alloc_kiovec() - Changes since 3.1.20 (20010814) - - use alloc_kiovec_sz() to speed dio [set num_buffer_heads==0] - - changes to cope with larger scatter gather element sizes - - clean up some printk()s - - add MODULE_LICENSE("GPL") [in a 3.1.20 subversion] - - fix race around generic_unplug_device() [in a 3.1.20 subversion] Changes since 3.1.19 (20010623) - add SG_GET_ACCESS_COUNT ioctl - make open() increment and close() decrement access_count @@ -44,57 +33,56 @@ Version 2 and 3 extensions to driver: Map of SG verions to the Linux kernels in which they appear: ---------- ---------------------------------- original all kernels < 2.2.6 - 2.1.40 2.2.20 + 2.1.38 2.2.16 + 2.1.39 2.2.17 - 2.2.19 3.0.x optional version 3 sg driver for 2.2 series - 3.1.17++ 2.4.0++ + 3.1.17 2.4.0 ++ Major new features in SG 3.x driver (cf SG 2.x drivers) - SG_IO ioctl() combines function if write() and read() - new interface (sg_io_hdr_t) but still supports old interface - - scatter/gather in user space, direct IO, and mmap supported - - The normal action of this driver is to use the adapter (HBA) driver to DMA - data into kernel buffers and then use the CPU to copy the data into the - user space (vice versa for writes). That is called "indirect" IO due to - the double handling of data. There are two methods offered to remove the - redundant copy: 1) direct IO which uses the kernel kiobuf mechanism and - 2) using the mmap() system call to map the reserve buffer (this driver has - one reserve buffer per fd) into the user space. Both have their advantages. - In terms of absolute speed mmap() is faster. If speed is not a concern, - indirect IO should be fine. Read the documentation for more information. + - scatter/gather in user space and direct IO supported + + The term "indirect IO" refers a method by which data is DMAed into kernel + buffers from the hardware and afterwards is transferred into the user + space (or vice versa if you are writing). Transfer speeds of up to 20 to + 30MBytes/sec have been measured using indirect IO. For faster throughputs + "direct IO" which cuts out the double handling of data is required. + Direct IO is supported by the SG 3.x drivers on 2.4 series Linux kernels + and requires the use of the new interface. + + Requests for direct IO with the new interface will automatically fall back + to indirect IO mode if they cannot be fulfilled. An example of such a case + is an ISA SCSI adapter which is only capable of DMAing to the lower 16MB of + memory due to the architecture of ISA. The 'info' field in the new + interface indicates whether a direct or indirect data transfer took place. + + Obtaining memory for the kernel buffers used in indirect IO is done by + first checking if the "reserved buffer" for the current file descriptor + is available and large enough. If these conditions are _not_ met then + kernel memory is obtained on a per SCSI command basis. This corresponds + to a write(), read() sequence or a SG_IO ioctl() call. Further, the + kernel memory that is suitable for DMA may be constrained by the + architecture of the SCSI adapter (e.g. ISA adapters). ** N.B. To use direct IO 'echo 1 > /proc/scsi/sg/allow_dio' may be needed. That pseudo file's content is defaulted to 0. ** - - Historical note: this SCSI pass-through driver has been known as "sg" for - a decade. In broader kernel discussions "sg" is used to refer to scatter - gather techniques. The context should clarify which "sg" is referred to. Documentation ============= - A web site for the SG device driver can be found at: + A web site for SG device drivers can be found at: http://www.torque.net/sg [alternatively check the MAINTAINERS file] - The documentation for the sg version 3 driver can be found at: - http://www.torque.net/sg/p/sg_v3_ho.html - This is a rendering from DocBook source [change the extension to "sgml" - or "xml"]. There are renderings in "ps", "pdf", "rtf" and "txt" (soon). - - The older, version 2 documents discuss the original sg interface in detail: + The main documents are still based on 2.x versions: http://www.torque.net/sg/p/scsi-generic.txt http://www.torque.net/sg/p/scsi-generic_long.txt + Documentation on the changes and additions in 3.x version of the sg driver + can be found at: http://www.torque.net/sg/p/scsi-generic_v3.txt A version of this document (potentially out of date) may also be found in the kernel source tree, probably at: /usr/src/linux/Documentation/scsi-generic.txt . - - Utility and test programs are available at the sg web site. They are - bundled as sg_utils (for the lk 2.2 series) and sg3_utils (for the - lk 2.4 series). - - There is a HOWTO on the Linux SCSI subsystem in the lk 2.4 series at: - http://www.linuxdoc.org/HOWTO/SCSI-2.4-HOWTO + Utility and test programs are available at the sg web site. */ - /* New interface introduced in the 3.x SG drivers follows */ typedef struct sg_iovec /* same structure as used by readv() Linux system */ @@ -132,20 +120,19 @@ typedef struct sg_io_hdr } sg_io_hdr_t; /* 64 bytes long (on i386) */ /* Use negative values to flag difference from original sg_header structure */ -#define SG_DXFER_NONE (-1) /* e.g. a SCSI Test Unit Ready command */ -#define SG_DXFER_TO_DEV (-2) /* e.g. a SCSI WRITE command */ -#define SG_DXFER_FROM_DEV (-3) /* e.g. a SCSI READ command */ -#define SG_DXFER_TO_FROM_DEV (-4) /* treated like SG_DXFER_FROM_DEV with the +#define SG_DXFER_NONE -1 /* e.g. a SCSI Test Unit Ready command */ +#define SG_DXFER_TO_DEV -2 /* e.g. a SCSI WRITE command */ +#define SG_DXFER_FROM_DEV -3 /* e.g. a SCSI READ command */ +#define SG_DXFER_TO_FROM_DEV -4 /* treated like SG_DXFER_FROM_DEV with the additional property than during indirect IO the user buffer is copied into the kernel buffers before the transfer */ -#define SG_DXFER_UNKNOWN (-5) /* Unknown data direction */ +#define SG_DXFER_UNKNOWN -5 /* Unknown data direction */ /* following flag values can be "or"-ed together */ #define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */ -#define SG_FLAG_LUN_INHIBIT 2 /* default is overwrite lun in SCSI */ - /* command block (when <= SCSI_2) */ -#define SG_FLAG_MMAP_IO 4 /* request memory mapped IO */ +#define SG_FLAG_LUN_INHIBIT 2 /* default is to put device's lun into */ + /* the 2nd byte of SCSI command */ #define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */ /* user space (debug indirect IO) */ |