File:  [NeXTSTEP 3.3 examples] / Examples / UNIX / SCSI / sg_example.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:48:25 2018 UTC (8 years, 1 month ago) by root
Branches: NeXT, MAIN
CVS tags: NeXTSTEP33, HEAD
Sample Programs from NeXSTEP 3.3

/*
 * Generic SCSI driver example.
 *
 * History
 * -------
 * 02-Feb-93	Erik Kay at NeXT
 *	i386 support
 * 10-Apr-89	Doug Mitchell
 *	Write after read to avoid trashing system disk.
 * 20-Mar-89	Doug Mitchell at NeXT
 *	Created.
 *
 *	Procedure:
 *		open sg0;
 *		set (target,lun) to (1,0);
 *		execute Request Sense command;
 *		Read 4 blocks;
 *		Write 4 blocks;
 *
 *	You may freely copy, distribute and reuse the code in this example.
 *	NeXT disclaims any warranty of any kind, expressed or implied, as to
 *	its fitness for any particular use.
 */
 
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <bsd/dev/scsireg.h>


#define IO_SIZE		4			/* in blocks */
#define BLOCK_SIZE	0x400			/* in bytes */
#define BUF_SIZE	(IO_SIZE*BLOCK_SIZE)
#define SENSE_SIZE	0x40			/* sense buffer size */

char rwbuf[BUF_SIZE];				/* read/write buffer */
char sbuf[SENSE_SIZE]; 				/* sense buffer */

int fd;						/* file descriptor */
int target=1;
int lun=0;
int lba=0;					/* start block for rd/wr */
char *dev_name="/dev/sg0";

main() {

	struct scsi_adr sa;
	int rtn;
	int i;
	
	/* open /dev/sg0 */
	
	if ((fd = open (dev_name, O_RDWR)) < 0) {
		printf("\nCould not open %s - fd = %XH\n",dev_name,fd);
		printf("errno = %d\n",errno);
		perror("open");
		exit(1);
	}
	
	/* set (target,lun) */
	
	sa.sa_target = target;
	sa.sa_lun = lun;
	if (ioctl(fd,SGIOCSTL,&sa) < 0) {
		printf("Error setting target %d lun %d\n",target,lun);
		printf("errno = %d\n",errno);
		perror("ioctl(SGIOCSTL)");
		exit(1);
	}

	if(gs_request_sense())			/* clear unit attention */
		exit(1);
	for(i=0; i<BUF_SIZE; i++)		/* init buffer */
		rwbuf[i] = 0;
	if(gs_read(lba,IO_SIZE,rwbuf))		/* read data */
		exit(1);
	if(gs_write(lba,IO_SIZE,rwbuf))		/* write the same data */
		exit(1);
	
	/* close /dev/sg0 */
	
	if ((rtn = close(fd)) < 0) {
		printf("\nCould not close %s - fd = %XH\n",dev_name,fd);
		printf("\nerrno = %d\n",errno);
		perror("close");
		exit(1);
	}
	else
		exit(0);

} /* main() */


/*	
 *	standard I/O routines
 */
 
gs_request_sense() {

	struct scsi_req sr;	
	struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
	
	cdb_clr(cdbp);
	cdbp->c6_opcode = C6OP_REQSENSE;
	cdbp->c6_lun    = lun;
	cdbp->c6_len	= SENSE_SIZE;
	sr.sr_dma_dir	= SR_DMA_RD;
	sr.sr_addr	= sbuf;
	sr.sr_dma_max	= SENSE_SIZE;
	sr.sr_ioto	= 10;
	return(do_ioc(&sr));


} /* gs_request_seense() */

gs_read(int lba, int block_count, u_char *bp) {

	/* read block_count blocks starting at lba. Data goes to *bp. */
	
	struct scsi_req sr;	
	struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
	
	cdb_clr(cdbp);
	cdbp->c6_opcode = C6OP_READ;
	cdbp->c6_lun    = 0;
#ifdef i386
	if (lba > 0) {
	    cdbp->c6_lba0 = lba & 0xFF;
	    cdbp->c6_lba1 = (lba >> 8) & 0xFF;
	    cdbp->c6_lba2 = (lba >> 16) & 0xFF;
	} else
	    cdbp->c6_lba0 = cdbp->c6_lba1 = cdbp->c6_lba2 = 0;
#else
	cdbp->c6_lba	= lba;
#endif
	cdbp->c6_len	= block_count;
	sr.sr_dma_dir	= SR_DMA_RD;
	sr.sr_addr	= (char *)bp;
	sr.sr_dma_max	= block_count * BLOCK_SIZE;
	sr.sr_ioto	= 10;
	return(do_ioc(&sr));

} /* gs_read() */

gs_write(int lba, int block_count, u_char *bp) {

	/* write block_count blocks starting at lba. Data comes from *bp. */

	struct scsi_req sr;	
	struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
	
	cdb_clr(cdbp);
	cdbp->c6_opcode = C6OP_WRITE;
	cdbp->c6_lun    = 0;
#ifdef i386
	if (lba > 0) {
	    cdbp->c6_lba0 = lba & 0xFF;
	    cdbp->c6_lba1 = (lba >> 8) & 0xFF;
	    cdbp->c6_lba2 = (lba >> 16) & 0xFF;
	} else
	    cdbp->c6_lba0 = cdbp->c6_lba1 = cdbp->c6_lba2 = 0;
#else
	cdbp->c6_lba	= lba;
#endif
	cdbp->c6_len	= block_count;
	sr.sr_dma_dir	= SR_DMA_WR;
	sr.sr_addr	= (char *)bp;
	sr.sr_dma_max	= block_count * BLOCK_SIZE;
	sr.sr_ioto	= 10;
	return(do_ioc(&sr));

} /* gs_write() */

cdb_clr(cdbp)
union cdb *cdbp;
{
	int i;
	char *p;
	
	p = (char *)cdbp;
	for(i=0; i<sizeof(union cdb); i++)
		*p++ = 0;
}

do_ioc(sr)
struct scsi_req *sr;
{
	
	if (ioctl(fd,SGIOCREQ,sr) < 0) {
		printf("..Error executing ioctl\n");
		printf("errno = %d\n",errno);
		perror("ioctl(SGIOCREQ)");
		return(1);
	}
	if(sr->sr_io_status) {
		printf("sr_io_status = 0x%X\n",sr->sr_io_status);
		if(sr->sr_io_status == SR_IOST_CHKSV) {
			printf("   sense key = %02XH   sense code = %02XH\n",
				sr->sr_esense.er_sensekey,
				sr->sr_esense.er_addsensecode);
		}
		printf("SCSI status = %02XH\n",sr->sr_scsi_status);
		return(1);
	}
	return(0);
} /* do_ioc() */
	

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.