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