|
|
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() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.