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