|
|
1.1 root 1: /*
2: * sys/i386/stand/as.c
3: *
4: * Standalone driver for Adaptech 1542 SCSI
5: *
6: * Pace Willisson [email protected] April 8, 1992
7: */
8:
9: #include "param.h"
10: #include "disklabel.h"
11: #include "i386/isa/asreg.h"
12: #include "saio.h"
13:
14: #ifdef ASDEBUG
15: #define ASPRINT(x) { printf x; DELAY (10000); }
16: #else
17: #define ASPRINT(x)
18: #endif
19:
20: #define NRETRIES 3
21:
22: int as_port = 0x330;
23:
24: struct mailbox_entry mailbox[2];
25:
26: int
27: asopen(io)
28: struct iob *io;
29: {
30: struct disklabel *dd;
31: char cdb[6];
32: char data[12];
33: int val;
34: int oval;
35: int i;
36: struct iob aio;
37:
38: if (io->i_unit < 0 || io->i_unit > 8
39: || io->i_part < 0 || io->i_part > 8
40: || io->i_ctlr < 0 || io->i_ctlr > 0)
41: return (-1);
42:
43: /* dma setup: see page 5-31 in the Adaptech manual */
44: outb (0xd6, 0xc1);
45: outb (0xd4, 0x01);
46:
47: ASPRINT (("resetting adaptech card... "));
48:
49: outb (as_port + AS_CONTROL, AS_CONTROL_SRST);
50:
51: /* delay a little */
52: for (i = 0; i < 100; i++)
53: inb (0x84);
54:
55: while (inb (as_port + AS_STATUS) != (AS_STATUS_INIT | AS_STATUS_IDLE))
56: ;
57:
58: ASPRINT (("reset ok "));
59:
60: as_put_byte (AS_CMD_MAILBOX_INIT);
61: as_put_byte (1); /* one mailbox out, one in */
62: as_put_byte ((int)mailbox >> 16);
63: as_put_byte ((int)mailbox >> 8);
64: as_put_byte ((int)mailbox);
65:
66: while (inb (as_port + AS_STATUS) & AS_STATUS_INIT)
67: ;
68:
69: ASPRINT (("mailbox init ok "));
70:
71: /* do mode select to set the logical block size */
72: bzero (cdb, 6);
73: cdb[0] = 0x15; /* MODE SELECT */
74: cdb[4] = 12; /* parameter list length */
75:
76: bzero (data, 12);
77: data[3] = 8; /* block descriptor length */
78: data[9] = DEV_BSIZE >> 16;
79: data[10] = DEV_BSIZE >> 8;
80: data[11] = DEV_BSIZE;
81:
82: if (ascmd (io->i_unit, 0, cdb, 6, data, 12, 1) < 0) {
83: printf ("as%d: error setting logical block size\n",
84: io->i_unit);
85: return (-1);
86: }
87:
88: aio = *io;
89: aio.i_bn = LABELSECTOR;
90: aio.i_cc = DEV_BSIZE;
91: /*io->i_ma = buf;*/
92: aio.i_boff = 0;
93:
94: #ifdef was
95: if (asstrategy (&aio, F_READ) == DEV_BSIZE) {
96: dd = (struct disklabel *)aio.i_ma;
97: io->i_boff = dd->d_partitions[io->i_part].p_offset;
98: ASPRINT (("partition offset %d ", io->i_boff));
99: }
100: #else
101: {
102: extern struct disklabel disklabel;
103: io->i_boff = disklabel.d_partitions[io->i_part].p_offset;
104: ASPRINT (("partition offset %d ", io->i_boff));
105: }
106: #endif
107:
108: ASPRINT (("asopen ok "));
109: return(0);
110: }
111:
112: /* func is F_WRITE or F_READ
113: * io->i_unit, io->i_part, io->i_bn is starting block
114: * io->i_cc is byte count
115: * io->i_ma is memory address
116: * io->i_boff is block offset for this partition (set up in asopen)
117: */
118: int
119: asstrategy(io, func)
120: struct iob *io;
121: {
122: char cdb[6];
123: int blkno;
124: int retry;
125:
126: ASPRINT (("asstrategy(target=%d, block=%d+%d, count=%d) ",
127: io->i_unit, io->i_bn, io->i_boff, io->i_cc));
128:
129: if (func == F_WRITE) {
130: printf ("as%d: write not supported\n", io->i_unit);
131: return (0);
132: }
133:
134: if (io->i_cc == 0)
135: return (0);
136:
137: if (io->i_cc % DEV_BSIZE != 0) {
138: printf ("as%d: transfer size not multiple of %d\n",
139: io->i_unit, DEV_BSIZE);
140: return (0);
141: }
142:
143: /* retry in case we get a unit-attention error, which just
144: * means the drive has been reset since the last command
145: */
146: for (retry = 0; retry < NRETRIES; retry++) {
147: blkno = io->i_bn + io->i_boff;
148:
149: cdb[0] = 8; /* scsi read opcode */
150: cdb[1] = (blkno >> 16) & 0x1f;
151: cdb[2] = blkno >> 8;
152: cdb[3] = blkno;
153: cdb[4] = io->i_cc / DEV_BSIZE;
154: cdb[5] = 0; /* control byte (used in linking) */
155:
156: if (ascmd (io->i_unit, 1, cdb, 6, io->i_ma, io->i_cc,
157: retry == NRETRIES - 1) >= 0) {
158: ASPRINT (("asstrategy ok "));
159: return (io->i_cc);
160: }
161: }
162:
163: ASPRINT (("asstrategy failed "));
164: return (0);
165: }
166:
167: int
168: ascmd (target, readflag, cdb, cdblen, data, datalen, printerr)
169: int target;
170: int readflag;
171: char *cdb;
172: int cdblen;
173: char *data;
174: int datalen;
175: int printerr;
176: {
177: struct ccb ccb;
178: int physaddr;
179: unsigned char *sp;
180: int i;
181:
182: if (mailbox[0].cmd != 0)
183: /* this can't happen, unless the card flakes */
184: _stop ("asstart: mailbox not available\n");
185:
186: bzero (&ccb, sizeof ccb);
187:
188: ccb.ccb_opcode = 3;
189: ccb.ccb_addr_and_control = target << 5;
190: if (datalen != 0)
191: ccb.ccb_addr_and_control |= readflag ? 8 : 0x10;
192: else
193: ccb.ccb_addr_and_control |= 0x18;
194:
195: ccb.ccb_data_len_msb = datalen >> 16;
196: ccb.ccb_data_len_mid = datalen >> 8;
197: ccb.ccb_data_len_lsb = datalen;
198:
199: ccb.ccb_requst_sense_allocation_len = MAXSENSE;
200:
201: physaddr = (int)data;
202: ccb.ccb_data_ptr_msb = physaddr >> 16;
203: ccb.ccb_data_ptr_mid = physaddr >> 8;
204: ccb.ccb_data_ptr_lsb = physaddr;
205:
206: ccb.ccb_scsi_command_len = cdblen;
207: bcopy (cdb, ccb.ccb_cdb, cdblen);
208:
209: #ifdef ASDEBUG
210: printf ("ccb: ");
211: for (i = 0; i < 48; i++)
212: printf ("%x ", ((unsigned char *)&ccb)[i]);
213: printf ("\n");
214: /*getchar ();*/
215: #endif
216:
217: physaddr = (int)&ccb;
218: mailbox[0].msb = physaddr >> 16;
219: mailbox[0].mid = physaddr >> 8;
220: mailbox[0].lsb = physaddr;
221: mailbox[0].cmd = 1;
222:
223: /* tell controller to look in its mailbox */
224: outb (as_port + AS_CONTROL, AS_CONTROL_IRST);
225: as_put_byte (AS_CMD_START_SCSI_COMMAND);
226:
227: /* wait for status */
228: ASPRINT (("waiting for status..."));
229: while (mailbox[1].cmd == 0)
230: ;
231: mailbox[1].cmd = 0;
232:
233:
234: if (ccb.ccb_host_status != 0 || ccb.ccb_target_status != 0) {
235: #ifdef ASDEBUG
236: printerr = 1;
237: #endif
238: if (printerr) {
239: printf ("as%d error: hst=%x tst=%x sense=",
240: target,
241: ccb.ccb_host_status,
242: ccb.ccb_target_status);
243: sp = ccb_sense (&ccb);
244: for (i = 0; i < 8; i++)
245: printf ("%x ", sp[i]);
246: printf ("\n");
247: #ifdef ASDEBUG
248: /*getchar ();*/
249: #endif
250: }
251: return (-1);
252: }
253:
254: ASPRINT (("ascmd ok "));
255:
256: return (0);
257: }
258:
259: int
260: as_put_byte (val)
261: int val;
262: {
263: while (inb (as_port + AS_STATUS) & AS_STATUS_CDF)
264: ;
265: outb (as_port + AS_DATA_OUT, val);
266: }
267:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.