|
|
1.1 root 1: /*
2: * Generic SCSI driver example.
3: *
4: * History
5: * -------
6: * 02-Feb-93 Erik Kay at NeXT
7: * i386 support
8: * 10-Apr-89 Doug Mitchell
9: * Write after read to avoid trashing system disk.
10: * 20-Mar-89 Doug Mitchell at NeXT
11: * Created.
12: *
13: * Procedure:
14: * open sg0;
15: * set (target,lun) to (1,0);
16: * execute Request Sense command;
17: * Read 4 blocks;
18: * Write 4 blocks;
19: *
20: * You may freely copy, distribute and reuse the code in this example.
21: * NeXT disclaims any warranty of any kind, expressed or implied, as to
22: * its fitness for any particular use.
23: */
24:
25: #include <errno.h>
26: #include <fcntl.h>
27: #include <stdio.h>
28: #include <sys/types.h>
29: #include <bsd/dev/scsireg.h>
30:
31:
32: #define IO_SIZE 4 /* in blocks */
33: #define BLOCK_SIZE 0x400 /* in bytes */
34: #define BUF_SIZE (IO_SIZE*BLOCK_SIZE)
35: #define SENSE_SIZE 0x40 /* sense buffer size */
36:
37: char rwbuf[BUF_SIZE]; /* read/write buffer */
38: char sbuf[SENSE_SIZE]; /* sense buffer */
39:
40: int fd; /* file descriptor */
41: int target=1;
42: int lun=0;
43: int lba=0; /* start block for rd/wr */
44: char *dev_name="/dev/sg0";
45:
46: main() {
47:
48: struct scsi_adr sa;
49: int rtn;
50: int i;
51:
52: /* open /dev/sg0 */
53:
54: if ((fd = open (dev_name, O_RDWR)) < 0) {
55: printf("\nCould not open %s - fd = %XH\n",dev_name,fd);
56: printf("errno = %d\n",errno);
57: perror("open");
58: exit(1);
59: }
60:
61: /* set (target,lun) */
62:
63: sa.sa_target = target;
64: sa.sa_lun = lun;
65: if (ioctl(fd,SGIOCSTL,&sa) < 0) {
66: printf("Error setting target %d lun %d\n",target,lun);
67: printf("errno = %d\n",errno);
68: perror("ioctl(SGIOCSTL)");
69: exit(1);
70: }
71:
72: if(gs_request_sense()) /* clear unit attention */
73: exit(1);
74: for(i=0; i<BUF_SIZE; i++) /* init buffer */
75: rwbuf[i] = 0;
76: if(gs_read(lba,IO_SIZE,rwbuf)) /* read data */
77: exit(1);
78: if(gs_write(lba,IO_SIZE,rwbuf)) /* write the same data */
79: exit(1);
80:
81: /* close /dev/sg0 */
82:
83: if ((rtn = close(fd)) < 0) {
84: printf("\nCould not close %s - fd = %XH\n",dev_name,fd);
85: printf("\nerrno = %d\n",errno);
86: perror("close");
87: exit(1);
88: }
89: else
90: exit(0);
91:
92: } /* main() */
93:
94:
95: /*
96: * standard I/O routines
97: */
98:
99: gs_request_sense() {
100:
101: struct scsi_req sr;
102: struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
103:
104: cdb_clr(cdbp);
105: cdbp->c6_opcode = C6OP_REQSENSE;
106: cdbp->c6_lun = lun;
107: cdbp->c6_len = SENSE_SIZE;
108: sr.sr_dma_dir = SR_DMA_RD;
109: sr.sr_addr = sbuf;
110: sr.sr_dma_max = SENSE_SIZE;
111: sr.sr_ioto = 10;
112: return(do_ioc(&sr));
113:
114:
115: } /* gs_request_seense() */
116:
117: gs_read(int lba, int block_count, u_char *bp) {
118:
119: /* read block_count blocks starting at lba. Data goes to *bp. */
120:
121: struct scsi_req sr;
122: struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
123:
124: cdb_clr(cdbp);
125: cdbp->c6_opcode = C6OP_READ;
126: cdbp->c6_lun = 0;
127: #ifdef i386
128: if (lba > 0) {
129: cdbp->c6_lba0 = lba & 0xFF;
130: cdbp->c6_lba1 = (lba >> 8) & 0xFF;
131: cdbp->c6_lba2 = (lba >> 16) & 0xFF;
132: } else
133: cdbp->c6_lba0 = cdbp->c6_lba1 = cdbp->c6_lba2 = 0;
134: #else
135: cdbp->c6_lba = lba;
136: #endif
137: cdbp->c6_len = block_count;
138: sr.sr_dma_dir = SR_DMA_RD;
139: sr.sr_addr = (char *)bp;
140: sr.sr_dma_max = block_count * BLOCK_SIZE;
141: sr.sr_ioto = 10;
142: return(do_ioc(&sr));
143:
144: } /* gs_read() */
145:
146: gs_write(int lba, int block_count, u_char *bp) {
147:
148: /* write block_count blocks starting at lba. Data comes from *bp. */
149:
150: struct scsi_req sr;
151: struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
152:
153: cdb_clr(cdbp);
154: cdbp->c6_opcode = C6OP_WRITE;
155: cdbp->c6_lun = 0;
156: #ifdef i386
157: if (lba > 0) {
158: cdbp->c6_lba0 = lba & 0xFF;
159: cdbp->c6_lba1 = (lba >> 8) & 0xFF;
160: cdbp->c6_lba2 = (lba >> 16) & 0xFF;
161: } else
162: cdbp->c6_lba0 = cdbp->c6_lba1 = cdbp->c6_lba2 = 0;
163: #else
164: cdbp->c6_lba = lba;
165: #endif
166: cdbp->c6_len = block_count;
167: sr.sr_dma_dir = SR_DMA_WR;
168: sr.sr_addr = (char *)bp;
169: sr.sr_dma_max = block_count * BLOCK_SIZE;
170: sr.sr_ioto = 10;
171: return(do_ioc(&sr));
172:
173: } /* gs_write() */
174:
175: cdb_clr(cdbp)
176: union cdb *cdbp;
177: {
178: int i;
179: char *p;
180:
181: p = (char *)cdbp;
182: for(i=0; i<sizeof(union cdb); i++)
183: *p++ = 0;
184: }
185:
186: do_ioc(sr)
187: struct scsi_req *sr;
188: {
189:
190: if (ioctl(fd,SGIOCREQ,sr) < 0) {
191: printf("..Error executing ioctl\n");
192: printf("errno = %d\n",errno);
193: perror("ioctl(SGIOCREQ)");
194: return(1);
195: }
196: if(sr->sr_io_status) {
197: printf("sr_io_status = 0x%X\n",sr->sr_io_status);
198: if(sr->sr_io_status == SR_IOST_CHKSV) {
199: printf(" sense key = %02XH sense code = %02XH\n",
200: sr->sr_esense.er_sensekey,
201: sr->sr_esense.er_addsensecode);
202: }
203: printf("SCSI status = %02XH\n",sr->sr_scsi_status);
204: return(1);
205: }
206: return(0);
207: } /* do_ioc() */
208:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.