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.