This is DriveSCSI.m in view mode; [Download] [Up]
//
// DriveSCSI_Class - subclass of SCSI2_Class for disk drive devices
//
// Copyright (C) 1994 by Christopher Wolf.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// Bug-reports, comments and questions should be directed to:
// Christopher Wolf <chris@alchemy.geo.cornell.edu>
//
// Portions of this code and documentation are derived from an
// earlier work (SCSI Inquirer) Copyright (C) 1990, 1991, 1992 by
// Jiro Nakamura and used with permission.
//
//
// For best results view this file with a tab size of 4 and
// a display width of 132 columns or wider.
//
// file version information
#define RCSDSM "$Id: DriveSCSI.m,v 0.55 94/12/06 03:57:22 chris Exp $"
// generic Unix headers
#import <stdio.h>
#import <libc.h>
// NeXTSTEP specific headers
#import <appkit/appkit.h>
// SCSI2 class specific headers
#import "DriveSCSI.h"
#import "errio.h"
// string constants
const char RCSdsm[] = RCSDSM;
const char RCSdsh[] = RCSDSH;
@implementation DriveSCSI
// ----------------------------------------------------------------------
//
// NAME
// isDevice
//
// RETURNS
// (BOOL) YES if sub-class can handle device, NO otherwise.
//
// EXPLANATION
// It is the sub-classes responsibility to implement this method.
// The method should return YES if the subclass of SCSI can handle
// the device at the current target, NO otherwise.
//
// SEE ALSO
// findDevice (SCSI), findDevice: (SCSI)
//
// ----------------------------------------------------------------------
- (BOOL) isDevice
{
struct inquiry_reply ibuffer;
BOOL result;
PrintFunction oldPf = dprintf;
dprintf = printfToNull;
result = ((![self inquiry: &ibuffer]) && (ibuffer.ir_devicetype == DEVTYPE_DISK));
dprintf = oldPf;
return result;
}
// ----------------------------------------------------------------------
//
// NAME
// seekExtended:
//
// RETURNS
// (int) 0 Seek succeeded
// (int) -1 Seek failed
//
// PARAMETERS
// (u_int) logicalBlockAddress logical block address to seek to
//
// EXPLANATION
// This implements the SCSI command ªSeek Extendedº. It must be
// passed a long integer logicalBlockAddress which to seek to.
// This method returns when the device has finished seeking.
// The method returns zero for success, non-zero otherwise.
//
// ----------------------------------------------------------------------
- (int) seekExtended: (u_int) logicalBlockAddress
{
struct cdb10 *cdbp = &sr.sr_cdb.cdb10;
BOOL wasOpen = isOpen;
int result = -1;
if (wasOpen || ![self openSCSI])
{
[SCSI clearCommandBlock: (cdb *) cdbp];
cdbp->c10_opcode = C10OP_SEEKEXTENDED;
cdbp->c10_lun = lun;
writeBigEndianLong(logicalBlockAddress, &cdbp->c10_lba_BE32);
sr.sr_dma_dir = SR_DMA_RD;
sr.sr_addr = NULL;
sr.sr_dma_max = 0;
sr.sr_ioto = timeout;
result = [self performRequest];
}
if (!wasOpen && [self closeSCSI])
{
result = -1;
}
return(result);
}
// ----------------------------------------------------------------------
//
// NAME
// readExtended: lba: numBytes: numBlocks:
//
// RETURNS
// (int) 0 read succeeded
// (int) -1 read failed
//
// PARAMETERS
// (u_int) lba logical block address to start read from
// (char *) destBuffer pointer to buffer to place data in
// (u_int) numBytes size of read in bytes
// (u_int) numBlock size of read in blocks
//
// EXPLANATION
// This implements the SCSI command ªRead Extendedº. It reads
// data starting from the specified logical block address into the
// specified buffer. The size of the read must be specified in
// BOTH number of bytes and number of blocks to be read. The
// method returns after the read has been completed. The method
// returns zero on success, non-zero otherwise.
//
// ----------------------------------------------------------------------
- (int) readExtended: (char *)destBuffer numBytes: (u_int)numBytes numBlocks: (u_int) numBlocks lba: (u_int)lba
{
struct cdb10 *cdbp = &sr.sr_cdb.cdb10;
BOOL wasOpen = isOpen;
int result = -1;
if (wasOpen || ![self openSCSI])
{
[SCSI clearCommandBlock: (cdb *) cdbp];
cdbp->c10_opcode = C10OP_READEXTENDED;
cdbp->c10_lun = lun;
writeBigEndianLong(lba, &cdbp->c10_lba_BE32);
writeBigEndianShort(numBlocks, &cdbp->c10_len_BE16);
sr.sr_dma_dir = SR_DMA_RD;
sr.sr_addr = destBuffer;
sr.sr_dma_max = numBytes;
sr.sr_ioto = timeout;
result = [self performRequest];
}
if (!wasOpen && [self closeSCSI])
{
result = -1;
}
return(result);
}
// ----------------------------------------------------------------------
//
// NAME
// read:numBytes:numBlocks:lba:
//
// RETURNS
// (int) 0 = success, -1 = failure
//
// PARAMETERS
// (u_int) lba logical block address to start read from
// (char *) destBuffer pointer to buffer to place data in
// (u_int) numBytes size of read in bytes
// (u_int) numBlock size of read in blocks
//
// EXPLANATION
// This implements the SCSI command ªRead (6)º. It reads
// data starting from the specified logical block address into the
// specified buffer. The size of the read must be specified in
// BOTH number of bytes and number of blocks to be read. The
// method returns after the read has been completed. The method
// returns zero on success, non-zero otherwise.
//
// ----------------------------------------------------------------------
- (int) read: (char *)destBuffer numBytes: (u_int)numBytes numBlocks: (u_int) numBlocks lba: (u_int)lba
{
struct cdb6 *cdbp = &sr.sr_cdb.cdb6;
BOOL wasOpen = isOpen;
int result = -1;
if (wasOpen || ![self openSCSI])
{
[SCSI clearCommandBlock: (cdb *) cdbp];
cdbp->c6_opcode = C6OP_READ;
writeBigEndianValue((lun<<21) + (lba & 0x1FFFFF), &cdbp->c6_lunlba_BE24, 24);
cdbp->c6_len = numBlocks;
sr.sr_dma_dir = SR_DMA_RD;
sr.sr_addr = destBuffer;
sr.sr_dma_max = numBytes;
sr.sr_ioto = timeout;
result = [self performRequest];
}
if (!wasOpen && [self closeSCSI])
{
result = -1;
}
return(result);
}
// ----------------------------------------------------------------------
//
// NAME
// formatUnitInterleave clearGList: cert: immed:
//
// RETURNS
// (int) 0 format succeeded
// (int) -1 format failed
//
// EXPLANATION
// This implements the SCSI command ªFormat Unitº. It performs
// a low level format of the device. ALL DATA WILL BE ERASED!
// Use this command with caution. This command will operate in
// immediate mode and return as soon as the device accepts the
// format unit command unless setImmediate: FALSE (from SCSI.m)
// is used in which case the command will not return until
// the format is complete. Note that if you setImmediate: FALSE
// you will probably have to adjust the timeout delay using
// the setTimeout: method from SCSI.m since the default timeout
// is too short for non-immediate mode format operations.
//
// SEE ALSO
// setImmediate: (SCSI.m), setTimeout: (SCSI.m)
//
// ----------------------------------------------------------------------
- (int) formatUnitInterleave: (u_int)interleave clearGList: (BOOL)clearGList cert: (BOOL)mediaCert
{
struct cdb6_format_unit *cdbp = &sr.sr_cdb.cdb6_format_unit;
struct defect_list_header *dlh = malloc(sizeof (struct defect_list_header));
BOOL wasOpen = isOpen;
int result = -1;
if (wasOpen || ![self openSCSI])
{
[SCSI clearCommandBlock: (cdb *) cdbp];
bzero(dlh, sizeof(struct defect_list_header));
cdbp->fu_opcode = C6OP_FORMAT;
cdbp->fu_lun = lun;
cdbp->fu_fmtdata = 0;
cdbp->fu_cmplist = clearGList;
writeBigEndianShort(interleave,&cdbp->fu_interleave_BE16);
dlh->dlh_fov = 1;
dlh->dlh_dcrt = !mediaCert;
dlh->dlh_dsp = 1;
dlh->dlh_immed = immed;
sr.sr_dma_dir = SR_DMA_WR;
sr.sr_addr = (char *)dlh;
sr.sr_dma_max = sizeof(struct defect_list_header);
sr.sr_ioto = timeout;
result = [self performRequest];
}
if (!wasOpen && [self closeSCSI])
{
result = -1;
}
free(dlh);
return(result);
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.