1 /*
2 * Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu)
3 * Slight fixes to timeouts to run with the 34F
4 * Thanks to Julian Elischer for advice and help with this port.
5 *
6 * Written by Julian Elischer (julian@tfs.com)
7 * for TRW Financial Systems for use under the MACH(2.5) operating system.
8 *
9 * TRW Financial Systems, in accordance with their agreement with Carnegie
10 * Mellon University, makes this software available to CMU to distribute
11 * or use in any manner that they see fit as long as this message is kept with
12 * the software. For this reason TFS also grants any other persons or
13 * organisations permission to use or modify this software.
14 *
15 * TFS supplies this software to be publicly redistributed
16 * on the understanding that TFS is not responsible for the correct
17 * functioning of this software in any circumstances.
18 *
19 * commenced: Sun Sep 27 18:14:01 PDT 1992
20 * slight mod to make work with 34F as well: Wed Jun 2 18:05:48 WST 1993
21 *
22 * today: Fri Jun 2 17:21:03 EST 1994
23 * added 24F support ++sg
24 *
25 * $FreeBSD: src/sys/i386/isa/ultra14f.c,v 1.49.2.1 1999/09/05 08:13:39 peter Exp $
26 */
27
28 #include <sys/types.h>
29
30 #ifdef KERNEL /* don't laugh.. this compiles to a program too.. look */
31 #include "uha.h"
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/errno.h>
36 #include <sys/ioctl.h>
37 #include <sys/malloc.h>
38 #include <sys/buf.h>
39 #include <sys/proc.h>
40
41 #include <machine/clock.h>
42
43 #include <vm/vm.h>
44 #include <vm/vm_param.h>
45 #include <vm/pmap.h>
46
47 #include <i386/isa/isa_device.h>
48 #endif /*KERNEL */
49 #include <scsi/scsi_all.h>
50 #include <scsi/scsiconf.h>
51
52 /* */
53
54 #ifndef KERNEL
55 #define NUHA 1
56 #endif /*KERNEL */
57
58 typedef struct {
59 unsigned char addr[4];
60 } physaddr;
61 typedef struct {
62 unsigned char len[4];
63 } physlen;
64
65 #define KVTOPHYS(x) vtophys(x)
66
67 #define UHA_MSCP_MAX 32 /* store up to 32MSCPs at any one time
68 * MAX = ?
69 */
70 #define MSCP_HASH_SIZE 32 /* when we have a physical addr. for
71 * a mscp and need to find the mscp in
72 * space, look it up in the hash table
73 */
74 #define MSCP_HASH_SHIFT 9 /* only hash on multiples of 512 */
75 #define MSCP_HASH(x) ((((long int)(x))>>MSCP_HASH_SHIFT) % MSCP_HASH_SIZE)
76
77 extern int hz;
78 #define UHA_NSEG 33 /* number of dma segments supported */
79
80 /************************** board definitions *******************************/
81 struct uha_reg
82 {
83 int id; /* product id reg */
84 int type; /* product type reg */
85 int ectl; /* EISA expansion control bits */
86 int config; /* configuration bits */
87 int lmask; /* local doorbell mask reg */
88 int lint; /* local doorbell int/stat reg */
89 int smask; /* system doorbell mask reg */
90 int sint; /* system doorbell int/stat reg */
91 int ogmcmd; /* outgoing mail command */
92 int ogmptr; /* outgoing mail ptr */
93 int icmcmd; /* incoming mail command */
94 int icmptr; /* incoming mail ptr */
95 };
96
97 struct uha_bits
98 {
99 /* uha_lint (read) */
100 unsigned char ldip;
101
102 /* uha_lint (write) */
103 unsigned char adrst;
104 unsigned char sbrst;
105 unsigned char asrst;
106 unsigned char abort;
107 unsigned char ogmint;
108
109 /* uha_sint (read) */
110 unsigned char sintp;
111 unsigned char abort_succ;
112 unsigned char abort_fail;
113
114 /* uha_sint (write) */
115 unsigned char abort_ack;
116 unsigned char icm_ack;
117 };
118
119
120 /*
121 * UHA_LINT bits (read)
122 */
123
124 #define UHA_LDIP 0x80 /* local doorbell int pending */
125 #define U24_LDIP 0x02
126
127 /*
128 * UHA_LINT bits (write)
129 */
130
131 #define UHA_ADRST 0x40 /* adapter soft reset */
132 #define UHA_SBRST 0x20 /* scsi bus reset */
133 #define UHA_ASRST 0x60 /* adapter and scsi reset */
134 #define UHA_ABORT 0x10 /* abort MSCP */
135 #define UHA_OGMINT 0x01 /* tell adapter to get mail */
136 #define U24_SBRST 0x40 /* scsi bus reset */
137 #define U24_ADRST 0x80 /* adapter soft reset */
138 #define U24_ASRST 0xc0 /* adapter and scsi reset */
139 #define U24_ABORT 0x10 /* same? */
140 #define U24_OGMINT 0x02 /* enable OGM interrupt */
141
142 /*
143 * UHA_SMASK bits (read)
144 */
145
146 #define UHA_SINTEN 0x80 /* system doorbell interupt Enabled */
147 #define UHA_ABORT_COMPLETE_EN 0x10 /* abort MSCP command complete int Enabled */
148 #define UHA_ICM_ENABLED 0x01 /* ICM interrupt enabled */
149
150 /*
151 * UHA_SMASK bits (write)
152 */
153
154 #define UHA_ENSINT 0x80 /* enable system doorbell interrupt */
155 #define UHA_EN_ABORT_COMPLETE 0x10 /* enable abort MSCP complete int */
156 #define UHA_ENICM 0x01 /* enable ICM interrupt */
157
158 /*
159 * UHA_SINT bits (read)
160 */
161
162 #define UHA_SINTP 0x80 /* system doorbell int pending */
163 #define UHA_ABORT_SUCC 0x10 /* abort MSCP successful */
164 #define UHA_ABORT_FAIL 0x18 /* abort MSCP failed */
165 #define U24_SINTP 0x02 /* system doorbell int pending */
166 #define U24_ABORT_SUCC 0x10 /* same? */
167 #define U24_ABORT_FAIL 0x18 /* same? */
168
169 /*
170 * UHA_SINT bits (write)
171 */
172
173 #define UHA_ABORT_ACK 0x18 /* acknowledge status and clear */
174 #define UHA_ICM_ACK 0x01 /* acknowledge ICM and clear */
175 #define U24_ABORT_ACK 0x18 /* same */
176 #define U24_ICM_ACK 0x02 /* 24F acknowledge ICM and clear */
177
178 /*
179 * UHA_CONF1 bits (read only)
180 */
181
182 #define UHA_DMA_CH5 0x00 /* DMA channel 5 */
183 #define UHA_DMA_CH6 0x40 /* 6 */
184 #define UHA_DMA_CH7 0x80 /* 7 */
185 #define UHA_IRQ15 0x00 /* IRQ 15 */
186 #define UHA_IRQ14 0x10 /* 14 */
187 #define UHA_IRQ11 0x20 /* 11 */
188 #define UHA_IRQ10 0x30 /* 10 */
189
190 #define EISA_CONFIG 0x0c80 /* Configuration base port */
191 #define EISA_DISABLE 0x01 /* EISA disable bit */
192
193 /*
194 * ha_status error codes
195 */
196
197 #define UHA_NO_ERR 0x00 /* No error supposedly */
198 #define UHA_SBUS_ABORT_ERR 0x84 /* scsi bus abort error */
199 #define UHA_SBUS_TIMEOUT 0x91 /* scsi bus selection timeout */
200 #define UHA_SBUS_OVER_UNDER 0x92 /* scsi bus over/underrun */
201 #define UHA_BAD_SCSI_CMD 0x96 /* illegal scsi command */
202 #define UHA_AUTO_SENSE_ERR 0x9b /* auto request sense err */
203 #define UHA_SBUS_RES_ERR 0xa3 /* scsi bus reset error */
204 #define UHA_BAD_SG_LIST 0xff /* invalid scatter gath list */
205
206 struct uha_dma_seg {
207 physaddr addr;
208 physlen len;
209 };
210
211 struct mscp {
212 unsigned char opcode:3;
213 #define U14_HAC 0x01 /* host adapter command */
214 #define U14_TSP 0x02 /* target scsi pass through command */
215 #define U14_SDR 0x04 /* scsi device reset */
216 unsigned char xdir:2; /* xfer direction */
217 #define U14_SDET 0x00 /* determined by scsi command */
218 #define U14_SDIN 0x01 /* scsi data in */
219 #define U14_SDOUT 0x02 /* scsi data out */
220 #define U14_NODATA 0x03 /* no data xfer */
221 unsigned char dcn:1; /* disable disconnect for this command */
222 unsigned char ca:1; /* cache control */
223 unsigned char sgth:1; /* scatter gather flag */
224 unsigned char target:3;
225 unsigned char chan:2; /* scsi channel (always 0 for 14f) */
226 unsigned char lun:3;
227 physaddr data;
228 physlen datalen;
229 physaddr link;
230 unsigned char link_id;
231 unsigned char sg_num; /*number of scat gath segs */
232 /*in s-g list if sg flag is */
233 /*set. starts at 1, 8bytes per */
234 unsigned char senselen;
235 unsigned char cdblen;
236 unsigned char cdb[12];
237 unsigned char ha_status;
238 unsigned char targ_status;
239 physaddr sense; /* if 0 no auto sense */
240 /*-----------------end of hardware supported fields----------------*/
241 struct mscp *next; /* in free list */
242 struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
243 int flags;
244 #define MSCP_FREE 0
245 #define MSCP_ACTIVE 1
246 #define MSCP_ABORTED 2
247 struct uha_dma_seg uha_dma[UHA_NSEG];
248 struct scsi_sense_data mscp_sense;
249 struct mscp *nexthash;
250 long int hashkey;
251 };
252
253 static struct uha_data {
254 int flags;
255 #define UHA_INIT 0x01
256 #define UHA_24F 0x02
257 int baseport;
258 struct mscp *mscphash[MSCP_HASH_SIZE];
259 struct mscp *free_mscp;
260 int unit;
261 int our_id; /* our scsi id */
262 int vect;
263 int dma;
264 int nummscps;
265 struct scsi_link sc_link;
266 struct uha_reg *ur;
267 struct uha_bits *ub;
268 } *uhadata[NUHA];
269
270 static int uha_abort __P((struct uha_data *uha, struct mscp *mscp));
271 static u_int32_t uha_adapter_info __P((int unit));
272 static int uha_attach __P((struct isa_device *dev));
273 static void uha_done __P((struct uha_data *uha, struct mscp *mscp));
274 static void uha_free_mscp __P((struct uha_data *uha, struct mscp *mscp,
275 int flags));
276 static struct mscp *
277 uha_get_mscp __P((struct uha_data *uha, int flags));
278 static int uha_init __P((struct uha_data *uha));
279 static int uha24_init __P((struct uha_data *uha));
280 static void uhaminphys __P((struct buf *bp));
281 static struct mscp *
282 uha_mscp_phys_kv __P((struct uha_data *uha, long mscp_phys));
283 static int uha_poll __P((struct uha_data *uha, int wait));
284 #ifdef UHADEBUG
285 static void uha_print_active_mscp __P((struct uha_data *uha));
286 static void uha_print_mscp __P((struct mscp *mscp));
287 #endif
288 static int uhaprobe __P((struct isa_device *dev));
289 static int32_t uha_scsi_cmd __P((struct scsi_xfer *xs));
290 static void uha_send_mbox __P((struct uha_data *uha, struct mscp *mscp));
291 static timeout_t
292 uha_timeout;
293
294 static struct mscp *cheat;
295 static unsigned long int scratch;
296 #define EISA_MAX_SLOTS 16 /* XXX This should go into a comon header */
297 static uha_slot = 0; /* slot last board was found in */
298 static uha_unit = 0;
299 #define UHA_SHOWMSCPS 0x01
300 #define UHA_SHOWINTS 0x02
301 #define UHA_SHOWCMDS 0x04
302 #define UHA_SHOWMISC 0x08
303 #define FAIL 1
304 #define SUCCESS 0
305 #define PAGESIZ 4096
306
307 #ifdef KERNEL
308 struct isa_driver uhadriver =
309 {
310 uhaprobe,
311 uha_attach,
312 "uha"
313 };
314
315 static struct scsi_adapter uha_switch =
316 {
317 uha_scsi_cmd,
318 uhaminphys,
319 0,
320 0,
321 uha_adapter_info,
322 "uha",
323 { 0, 0 }
324 };
325
326 /* the below structure is so we have a default dev struct for out link struct */
327 static struct scsi_device uha_dev =
328 {
329 NULL, /* Use default error handler */
330 NULL, /* have a queue, served by this */
331 NULL, /* have no async handler */
332 NULL, /* Use default 'done' routine */
333 "uha",
334 0,
335 { 0, 0 }
336 };
337
338 #endif /*KERNEL */
339
340 #ifndef KERNEL
341 main()
342 {
343 printf("uha_data is %d bytes\n", sizeof(struct uha_data));
344 printf("mscp is %d bytes\n", sizeof(struct mscp));
345 }
346
347 #else /*KERNEL*/
348 /*
349 * Function to send a command out through a mailbox
350 */
351 static void
352 uha_send_mbox(struct uha_data *uha, struct mscp *mscp)
353 {
354 int spincount = 100000; /* 1s should be enough */
355 struct uha_reg *ur = uha->ur;
356 struct uha_bits *ub = uha->ub;
357 int s = splbio();
358
359 while (--spincount) {
360 if ((inb(ur->lint) & ub->ldip) == 0)
361 break;
362 DELAY(100);
363 }
364 if (spincount == 0) {
365 printf("uha%d: uha_send_mbox, board is not responding\n",
366 uha->unit);
367 Debugger("ultra14f");
368 }
369 outl(ur->ogmptr, KVTOPHYS(mscp));
370 if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1);
371 outb(ur->lint, ub->ogmint);
372 splx(s);
373 }
374
375 /*
376 * Function to send abort to 14f
377 */
378 int
379 uha_abort(struct uha_data *uha, struct mscp *mscp)
380 {
381 int spincount = 100; /* 1 mSec */
382 int abortcount = 200000; /*2 secs */
383 struct uha_reg *ur = uha->ur;
384 struct uha_bits *ub = uha->ub;
385 int s = splbio();
386
387 while (--spincount) {
388 if ((inb(ur->lint) & ub->ldip) == 0)
389 break;
390 DELAY(10);
391 }
392 if (spincount == 0) {
393 printf("uha%d: uha_abort, board is not responding\n", uha->unit);
394 Debugger("ultra14f");
395 }
396 outl(ur->ogmptr,KVTOPHYS(mscp));
397 if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1);
398 outb(ur->lint, ub->abort);
399
400 while (--abortcount) {
401 if (inb(ur->sint) & ub->abort_fail)
402 break;
403 DELAY(10);
404 }
405 if (abortcount == 0) {
406 printf("uha%d: uha_abort, board is not responding\n", uha->unit);
407 Debugger("ultra14f");
408 }
409 if ((inb(ur->sint) & 0x10) != 0) {
410 outb(ur->sint, ub->abort_ack);
411 splx(s);
412 return (1);
413 } else {
414 outb(ur->sint, ub->abort_ack);
415 splx(s);
416 return (0);
417 }
418 }
419
420 /*
421 * Function to poll for command completion when in poll mode.
422 *
423 * wait = timeout in msec
424 */
425 static int
426 uha_poll(struct uha_data *uha, int wait)
427 {
428 struct uha_reg *ur = uha->ur;
429 struct uha_bits *ub = uha->ub;
430 int stport = ur->sint;
431
432 while (--wait) {
433 if (inb(stport) & ub->sintp)
434 break;
435 DELAY(1000); /* 1 mSec per loop */
436 }
437 if (wait == 0) {
438 printf("uha%d: uha_poll, board is not responding\n", uha->unit);
439 return (EIO);
440 }
441 uhaintr(uha->unit);
442 return (0);
443 }
444
445 /*
446 * Check if the device can be found at the port given and if so, set it up
447 * ready for further work as an argument, takes the isa_device structure
448 * from autoconf.c
449 */
450 int
451 uhaprobe(dev)
452 struct isa_device *dev;
453 {
454 int unit = uha_unit;
455 struct uha_data *uha;
456
457 dev->id_unit = unit; /* XXX */
458
459 /*
460 * find unit and check we have that many defined
461 */
462 if (unit >= NUHA) {
463 printf("uha: unit number (%d) too high\n", unit);
464 return (0);
465 }
466 dev->id_unit = unit;
467
468 /*
469 * Allocate a storage area for us
470 */
471 if (uhadata[unit]) {
472 printf("uha%d: memory already allocated\n", unit);
473 return 0;
474 }
475 uha = malloc(sizeof(struct uha_data), M_TEMP, M_NOWAIT);
476 if (!uha) {
477 printf("uha%d: cannot malloc!\n", unit);
478 return 0;
479 }
480 bzero(uha, sizeof(struct uha_data));
481
482 uha->ur = malloc(sizeof(struct uha_reg), M_TEMP, M_NOWAIT);
483 if (!uha->ur) {
484 printf("uha%d: cannot malloc!\n", unit);
485 return 0;
486 }
487 bzero(uha->ur, sizeof(struct uha_reg));
488
489 uha->ub = malloc(sizeof(struct uha_bits), M_TEMP, M_NOWAIT);
490 if (!uha->ub) {
491 printf("uha%d: cannot malloc!\n", unit);
492 return 0;
493 }
494 bzero(uha->ub, sizeof(struct uha_bits));
495
496 uhadata[unit] = uha;
497 uha->unit = unit;
498 uha->baseport = dev->id_iobase;
499 /*
500 * Try initialise a unit at this location
501 * sets up dma and bus speed, loads uha->vect
502 */
503 if (uha_init(uha) != 0 && uha24_init(uha) != 0) {
504 uhadata[unit] = NULL;
505 free(uha->ur, M_TEMP);
506 free(uha->ub, M_TEMP);
507 free(uha, M_TEMP);
508 return (0);
509 }
510 /* if it's there put in its interrupt and DRQ vectors */
511 dev->id_irq = (1 << uha->vect);
512 dev->id_drq = uha->dma;
513 dev->id_iobase = uha->baseport;
514
515 uha_unit++;
516 return (16);
517 }
518
519 /*
520 * Attach all the sub-devices we can find
521 */
522 int
523 uha_attach(dev)
524 struct isa_device *dev;
525 {
526 int unit = dev->id_unit;
527 struct uha_data *uha = uhadata[unit];
528 struct scsibus_data *scbus;
529
530 /*
531 * fill in the prototype scsi_link.
532 */
533 uha->sc_link.adapter_unit = unit;
534 uha->sc_link.adapter_targ = uha->our_id;
535 uha->sc_link.adapter_softc = uha;
536 uha->sc_link.adapter = &uha_switch;
537 uha->sc_link.device = &uha_dev;
538 uha->sc_link.flags = SDEV_BOUNCE;
539
540 /*
541 * Prepare the scsibus_data area for the upperlevel
542 * scsi code.
543 */
544 scbus = scsi_alloc_bus();
545 if(!scbus)
546 return 0;
547 scbus->adapter_link = &uha->sc_link;
548
549 /*
550 * ask the adapter what subunits are present
551 */
552 scsi_attachdevs(scbus);
553
554 return 1;
555 }
556
557 /*
558 * Return some information to the caller about
559 * the adapter and it's capabilities
560 */
561 u_int32_t
562 uha_adapter_info(unit)
563 int unit;
564 {
565 return (2); /* 2 outstanding requests at a time per device */
566 }
567
568 /*
569 * Catch an interrupt from the adaptor
570 */
571 void
572 uhaintr(unit)
573 int unit;
574 {
575 struct uha_data *uha = uhadata[unit];
576 struct mscp *mscp;
577 u_char uhastat;
578 unsigned long int mboxval;
579 struct uha_reg *ur;
580 struct uha_bits *ub;
581 int port;
582
583 ur = uha->ur;
584 ub = uha->ub;
585 port = uha->baseport;
586
587 #ifdef UHADEBUG
588 printf("uhaintr ");
589 #endif /*UHADEBUG */
590
591 while ((uhastat = inb(ur->sint)) & ub->sintp) {
592 /*
593 * First get all the information and then
594 * acknowledge the interrupt
595 */
596 mboxval = inl(ur->icmptr);
597 outb(ur->sint, ub->icm_ack);
598 if (uha->flags & UHA_24F) outb(ur->icmcmd, 0);
599
600 #ifdef UHADEBUG
601 printf("status = 0x%x ", uhastat);
602 #endif /*UHADEBUG*/
603 /*
604 * Process the completed operation
605 */
606
607 mscp = uha_mscp_phys_kv(uha, mboxval);
608 if (!mscp) {
609 printf("uha: BAD MSCP RETURNED\n");
610 return; /* whatever it was, it'll timeout */
611 }
612 untimeout(uha_timeout, (caddr_t)mscp);
613
614 uha_done(uha, mscp);
615 }
616 }
617
618 /*
619 * We have a mscp which has been processed by the adaptor, now we look to see
620 * how the operation went.
621 */
622 void
623 uha_done(uha, mscp)
624 struct uha_data *uha;
625 struct mscp *mscp;
626 {
627 struct scsi_sense_data *s1, *s2;
628 struct scsi_xfer *xs = mscp->xs;
629
630 SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_done\n"));
631 /*
632 * Otherwise, put the results of the operation
633 * into the xfer and call whoever started it
634 */
635 if (((mscp->ha_status != UHA_NO_ERR) || (mscp->targ_status != SCSI_OK))
636 && ((xs->flags & SCSI_ERR_OK) == 0)) {
637
638 s1 = &(mscp->mscp_sense);
639 s2 = &(xs->sense);
640
641 if (mscp->ha_status != UHA_NO_ERR) {
642 switch (mscp->ha_status) {
643 case UHA_SBUS_ABORT_ERR:
644 case UHA_SBUS_TIMEOUT: /* No sel response */
645 SC_DEBUG(xs->sc_link, SDEV_DB3,
646 ("abort or timeout; ha_status 0x%x\n",
647 mscp->ha_status));
648 xs->error = XS_TIMEOUT;
649 break;
650 case UHA_SBUS_OVER_UNDER:
651 SC_DEBUG(xs->sc_link, SDEV_DB3,
652 ("scsi bus xfer over/underrun\n"));
653 xs->error = XS_DRIVER_STUFFUP;
654 break;
655 default: /* Other scsi protocol messes */
656 xs->error = XS_DRIVER_STUFFUP;
657 printf("uha%d: unexpected ha_status 0x%x (target status 0x%x)\n",
658 uha->unit, mscp->ha_status,
659 mscp->targ_status);
660 break;
661 }
662 } else {
663 /* Target status problem */
664 SC_DEBUG(xs->sc_link, SDEV_DB3, ("target err 0x%x\n",
665 mscp->targ_status));
666 switch (mscp->targ_status) {
667 case 0x02:
668 *s2 = *s1;
669 xs->error = XS_SENSE;
670 break;
671 case 0x08:
672 xs->error = XS_BUSY;
673 break;
674 default:
675 printf("uha%d: unexpected targ_status 0x%x\n",
676 uha->unit, mscp->targ_status);
677 xs->error = XS_DRIVER_STUFFUP;
678 break;
679 }
680 }
681 }
682 else {
683 /* All went correctly OR errors expected */
684 xs->resid = 0;
685 xs->error = 0;
686 }
687 xs->flags |= ITSDONE;
688 uha_free_mscp(uha, mscp, xs->flags);
689 scsi_done(xs);
690 }
691
692 /*
693 * A mscp (and hence a mbx-out) is put onto the free list.
694 */
695 void
696 uha_free_mscp(uha, mscp, flags)
697 struct uha_data *uha;
698 struct mscp *mscp;
699 int flags;
700 {
701 unsigned int opri = 0;
702
703 if (!(flags & SCSI_NOMASK))
704 opri = splbio();
705
706 mscp->next = uha->free_mscp;
707 uha->free_mscp = mscp;
708 mscp->flags = MSCP_FREE;
709 /*
710 * If there were none, wake abybody waiting for
711 * one to come free, starting with queued entries
712 */
713 if (!mscp->next) {
714 wakeup((caddr_t)&uha->free_mscp);
715 }
716 if (!(flags & SCSI_NOMASK))
717 splx(opri);
718 }
719
720 /*
721 * Get a free mscp
722 *
723 * If there are none, see if we can allocate a new one. If so, put it in the
724 * hash table too otherwise either return an error or sleep.
725 */
726 static struct mscp *
727 uha_get_mscp(uha, flags)
728 struct uha_data *uha;
729 int flags;
730 {
731 unsigned opri = 0;
732 struct mscp *mscpp;
733 int hashnum;
734
735 if (!(flags & SCSI_NOMASK))
736 opri = splbio();
737 /*
738 * If we can and have to, sleep waiting for one to come free
739 * but only if we can't allocate a new one
740 */
741 while (!(mscpp = uha->free_mscp)) {
742 if (uha->nummscps < UHA_MSCP_MAX) {
743 if (mscpp = (struct mscp *)malloc(sizeof(struct mscp),
744 M_TEMP,
745 M_NOWAIT)) {
746 bzero(mscpp, sizeof(struct mscp));
747 uha->nummscps++;
748 mscpp->flags = MSCP_ACTIVE;
749 /*
750 * put in the phystokv hash table
751 * Never gets taken out.
752 */
753 mscpp->hashkey = KVTOPHYS(mscpp);
754 hashnum = MSCP_HASH(mscpp->hashkey);
755 mscpp->nexthash = uha->mscphash[hashnum];
756 uha->mscphash[hashnum] = mscpp;
757 } else {
758 printf("uha%d: Can't malloc MSCP\n", uha->unit);
759 }
760 goto gottit;
761 } else {
762 if (!(flags & SCSI_NOSLEEP)) {
763 tsleep((caddr_t)&uha->free_mscp, PRIBIO,
764 "uhamscp", 0);
765 }
766 }
767 }
768 if (mscpp) {
769 /* Get MSCP from from free list */
770 uha->free_mscp = mscpp->next;
771 mscpp->flags = MSCP_ACTIVE;
772 }
773 gottit:
774 if (!(flags & SCSI_NOMASK))
775 splx(opri);
776
777 return (mscpp);
778 }
779
780 /*
781 * given a physical address, find the mscp that it corresponds to.
782 */
783 static struct mscp *
784 uha_mscp_phys_kv(uha, mscp_phys)
785 struct uha_data *uha;
786 long int mscp_phys;
787 {
788 int hashnum = MSCP_HASH(mscp_phys);
789 struct mscp *mscpp = uha->mscphash[hashnum];
790
791 while (mscpp) {
792 if (mscpp->hashkey == mscp_phys)
793 break;
794 mscpp = mscpp->nexthash;
795 }
796 return mscpp;
797 }
798
799 /*
800 * Start the board, ready for normal operation
801 */
802 int
803 uha_init(uha)
804 struct uha_data *uha;
805 {
806 volatile unsigned char model;
807 volatile unsigned char submodel;
808 unsigned char config_reg1;
809 unsigned char config_reg2;
810 unsigned char dma_ch;
811 unsigned char irq_ch;
812 unsigned char uha_id;
813 int port = uha->baseport;
814 int resetcount = 4000; /* 4 secs? */
815 struct uha_reg *ur = uha->ur;
816 struct uha_bits *ub = uha->ub;
817
818 /*
819 * Prepare to use a 14/34F.
820 */
821 ur->id = port + 0x04;
822 ur->type = port + 0x00; /* 24F only */
823 ur->ectl = port + 0x00; /* 24F only */
824 ur->config = port + 0x06; /* 0-1 for 14F */
825 ur->lmask = port + 0x00;
826 ur->lint = port + 0x01;
827 ur->smask = port + 0x02;
828 ur->sint = port + 0x03;
829 ur->ogmcmd = port + 0x00; /* 24F only */
830 ur->ogmptr = port + 0x08;
831 ur->icmcmd = port + 0x00; /* 24F only */
832 ur->icmptr = port + 0x0c;
833
834 ub->ldip = UHA_LDIP;
835 ub->adrst = UHA_ADRST;
836 ub->sbrst = UHA_SBRST;
837 ub->asrst = UHA_ASRST;
838 ub->abort = UHA_ABORT;
839 ub->ogmint = UHA_OGMINT;
840 ub->sintp = UHA_SINTP;
841 ub->abort_succ = UHA_ABORT_SUCC;
842 ub->abort_fail = UHA_ABORT_FAIL;
843 ub->abort_ack = UHA_ABORT_ACK;
844 ub->icm_ack = UHA_ICM_ACK;
845
846 model = inb(ur->id);
847 submodel = inb(ur->id + 1);
848 if ((model != 0x56) & (submodel != 0x40)) return(ENXIO);
849 printf("uha%d: reading board settings, ", uha->unit);
850
851 config_reg1 = inb(ur->config);
852 config_reg2 = inb(ur->config + 1);
853 dma_ch = (config_reg1 & 0xc0);
854 irq_ch = (config_reg1 & 0x30);
855 uha_id = (config_reg2 & 0x07);
856
857 switch (dma_ch) {
858 case UHA_DMA_CH5:
859 uha->dma = 5;
860 printf("dma=5 ");
861 break;
862 case UHA_DMA_CH6:
863 uha->dma = 6;
864 printf("dma=6 ");
865 break;
866 case UHA_DMA_CH7:
867 uha->dma = 7;
868 printf("dma=7 ");
869 break;
870 default:
871 printf("illegal dma jumper setting\n");
872 return (EIO);
873 }
874 switch (irq_ch) {
875 case UHA_IRQ10:
876 uha->vect = 10;
877 printf("int=10 ");
878 break;
879 case UHA_IRQ11:
880 uha->vect = 11;
881 printf("int=11 ");
882 break;
883 case UHA_IRQ14:
884 uha->vect = 14;
885 printf("int=14 ");
886 break;
887 case UHA_IRQ15:
888 uha->vect = 15;
889 printf("int=15 ");
890 break;
891 default:
892 printf("illegal int jumper setting\n");
893 return (EIO);
894 }
895
896 /* who are we on the scsi bus */
897 printf("id=%x\n", uha_id);
898 uha->our_id = uha_id;
899
900 /*
901 * Note that we are going and return (to probe)
902 */
903 outb(ur->lint, ub->asrst);
904 while (--resetcount) {
905 if (inb(ur->lint))
906 break;
907 DELAY(1000); /* 1 mSec per loop */
908 }
909 if (resetcount == 0) {
910 printf("uha%d: board timed out during reset\n", uha->unit);
911 return (ENXIO);
912 }
913 outb(ur->smask, 0x81); /* make sure interrupts are enabled */
914 uha->flags |= UHA_INIT;
915 return (0);
916 }
917
918
919 /*
920 * Initialize an Ultrastor 24F
921 */
922 int
923 uha24_init(uha)
924 struct uha_data *uha;
925 {
926 unsigned char p0, p1, p2, p3, p5, p7;
927 unsigned char id[7], rev, haid;
928 int port = 0, irq;
929 int resetcount = 4000;
930 struct uha_reg *ur = uha->ur;
931 struct uha_bits *ub = uha->ub;
932
933 /* Search for the 24F's product ID */
934 uha_slot++;
935 while (uha_slot < EISA_MAX_SLOTS) {
936 /*
937 * Prepare to use a 24F.
938 */
939 port = EISA_CONFIG | (uha_slot << 12);
940 ur->id = port + 0x00;
941 ur->type = port + 0x02;
942 ur->ectl = port + 0x04;
943 ur->config = port + 0x05; /* 0-2 for 24F */
944 ur->lmask = port + 0x0c;
945 ur->lint = port + 0x0d;
946 ur->smask = port + 0x0e;
947 ur->sint = port + 0x0f;
948 ur->ogmcmd = port + 0x16;
949 ur->ogmptr = port + 0x17;
950 ur->icmcmd = port + 0x1b;
951 ur->icmptr = port + 0x1c;
952
953 ub->ldip = U24_LDIP;
954 ub->adrst = U24_ADRST;
955 ub->sbrst = U24_SBRST;
956 ub->asrst = U24_ASRST;
957 ub->abort = U24_ABORT;
958 ub->ogmint = U24_OGMINT;
959 ub->sintp = U24_SINTP;
960 ub->abort_succ = U24_ABORT_SUCC;
961 ub->abort_fail = U24_ABORT_FAIL;
962 ub->abort_ack = U24_ABORT_ACK;
963 ub->icm_ack = U24_ICM_ACK;
964
965 /*
966 * Make sure an EISA card is installed in this slot,
967 * and if it is make sure that the card is enabled.
968 */
969 outb(ur->id, 0xff);
970 p0 = inb(ur->id);
971 if ((p0 == 0xff) ||
972 ((p0 & 0x80) != 0) ||
973 ((inb(ur->ectl) & EISA_DISABLE) == 0)) {
974 uha_slot++;
975 continue;
976 }
977
978 /* Found an enabled card. Grab the product ID. */
979 p1 = inb(ur->id+1);
980 p2 = inb(ur->type);
981 p3 = inb(ur->type+1);
982 id[0] = 0x40 + ((p0 >> 2) & 0x1f);
983 id[1] = 0x40 + (((p0 & 0x03) << 3) | ((p1 >> 5) & 0x07));
984 id[2] = 0x40 + (p1 & 0x1f);
985 id[3] = hex2ascii((p2 >> 4) & 0x0f);
986 id[4] = hex2ascii(p2 & 0x0f);
987 id[5] = hex2ascii((p3 >> 4) & 0x0f);
988 id[6] = '\0';
989 rev = p3 & 0xf;
990
991 /* We only want the 24F product ID. */
992 if (!strcmp(id, "USC024")) break;
993 uha_slot++;
994 }
995 if (uha_slot == EISA_MAX_SLOTS) return(ENODEV);
996
997 /* We have the card! Grab remaining config. */
998 p5 = inb(ur->config);
999 p7 = inb(ur->config+2);
1000
1001 switch (p5 & 0xf0) {
1002 case 0x10: irq = 15; break;
1003 case 0x20: irq = 14; break;
1004 case 0x40: irq = 11; break;
1005 case 0x80: irq = 10; break;
1006 default:
1007 printf("uha%d: bad 24F irq\n", uha->unit);
1008 return(ENXIO);
1009 }
1010
1011 haid = (p7 & 0x07);
1012 printf("uha%d: UltraStor 24F int=%d id=%d\n", uha->unit, irq, haid);
1013
1014 /* Issue SCSI and adapter reset */
1015 outb(ur->lint, ub->asrst);
1016 while (--resetcount) {
1017 if (inb(ur->lint))
1018 break;
1019 DELAY(1000); /* 1 mSec per loop */
1020 }
1021 if (resetcount == 0) {
1022 printf("uha%d: board timed out during reset\n", uha->unit);
1023 return (ENXIO);
1024 }
1025 outb(ur->smask, 0xc2); /* make sure interrupts are enabled */
1026 uha->flags |= (UHA_INIT | UHA_24F);
1027 uha->baseport = port;
1028 uha->our_id = haid;
1029 uha->vect = irq;
1030 uha->dma = -1;
1031 return(0);
1032 }
1033
1034 #ifndef min
1035 #define min(x,y) (x < y ? x : y)
1036 #endif /* min */
1037
1038 void
1039 uhaminphys(bp)
1040 struct buf *bp;
1041 {
1042 if (bp->b_bcount > ((UHA_NSEG - 1) * PAGESIZ)) {
1043 bp->b_bcount = ((UHA_NSEG - 1) * PAGESIZ);
1044 }
1045 }
1046
1047 /*
1048 * start a scsi operation given the command and the data address. Also
1049 * needs the unit, target and lu.
1050 */
1051 static int32_t
1052 uha_scsi_cmd(xs)
1053 struct scsi_xfer *xs;
1054 {
1055 struct mscp *mscp;
1056 struct uha_dma_seg *sg;
1057 int seg; /* scatter gather seg being worked on */
1058 int thiskv;
1059 unsigned long int thisphys, nextphys;
1060 int bytes_this_seg, bytes_this_page, datalen, flags;
1061 struct uha_data *uha;
1062 int s;
1063 unsigned long int templen;
1064
1065 uha = (struct uha_data *)xs->sc_link->adapter_softc;
1066 SC_DEBUG(xs->sc_link, SDEV_DB2, ("uha_scsi_cmd\n"));
1067 /*
1068 * get a mscp (mbox-out) to use. If the transfer
1069 * is from a buf (possibly from interrupt time)
1070 * then we can't allow it to sleep
1071 */
1072 flags = xs->flags;
1073 if (xs->bp)
1074 flags |= (SCSI_NOSLEEP); /* just to be sure */
1075 if (flags & ITSDONE) {
1076 printf("uha%d: Already done?", uha->unit);
1077 xs->flags &= ~ITSDONE;
1078 }
1079 if (!(flags & INUSE)) {
1080 printf("uha%d: Not in use?", uha->unit);
1081 xs->flags |= INUSE;
1082 }
1083 if (!(mscp = uha_get_mscp(uha, flags))) {
1084 xs->error = XS_DRIVER_STUFFUP;
1085 return (TRY_AGAIN_LATER);
1086 }
1087 cheat = mscp;
1088 SC_DEBUG(xs->sc_link, SDEV_DB3, ("start mscp(%p)\n", mscp));
1089 mscp->xs = xs;
1090
1091 /*
1092 * Put all the arguments for the xfer in the mscp
1093 */
1094 if (flags & SCSI_RESET) {
1095 mscp->opcode = 0x04;
1096 mscp->ca = 0x01;
1097 } else {
1098 mscp->opcode = 0x02;
1099 mscp->ca = 0x01;
1100 }
1101 if (flags & SCSI_DATA_IN) {
1102 mscp->xdir = 0x01;
1103 }
1104 if (flags & SCSI_DATA_OUT) {
1105 mscp->xdir = 0x02;
1106 }
1107 #ifdef GOTTABEJOKING
1108 if (xs->sc_link->lun != 0) {
1109 xs->error = XS_DRIVER_STUFFUP;
1110 uha_free_mscp(uha, mscp, flags);
1111 return (HAD_ERROR);
1112 }
1113 #endif
1114 mscp->dcn = 0x00;
1115 mscp->chan = 0x00;
1116 mscp->target = xs->sc_link->target;
1117 mscp->lun = xs->sc_link->lun;
1118 mscp->link.addr[0] = 0x00;
1119 mscp->link.addr[1] = 0x00;
1120 mscp->link.addr[2] = 0x00;
1121 mscp->link.addr[3] = 0x00;
1122 mscp->link_id = 0x00;
1123 mscp->cdblen = xs->cmdlen;
1124 scratch = KVTOPHYS(&(mscp->mscp_sense));
1125 mscp->sense.addr[0] = (scratch & 0xff);
1126 mscp->sense.addr[1] = ((scratch >> 8) & 0xff);
1127 mscp->sense.addr[2] = ((scratch >> 16) & 0xff);
1128 mscp->sense.addr[3] = ((scratch >> 24) & 0xff);
1129 mscp->senselen = sizeof(mscp->mscp_sense);
1130 mscp->ha_status = 0x00;
1131 mscp->targ_status = 0x00;
1132
1133 if (xs->datalen) { /* should use S/G only if not zero length */
1134 scratch = KVTOPHYS(mscp->uha_dma);
1135 mscp->data.addr[0] = (scratch & 0xff);
1136 mscp->data.addr[1] = ((scratch >> 8) & 0xff);
1137 mscp->data.addr[2] = ((scratch >> 16) & 0xff);
1138 mscp->data.addr[3] = ((scratch >> 24) & 0xff);
1139 sg = mscp->uha_dma;
1140 seg = 0;
1141 mscp->sgth = 0x01;
1142
1143 #ifdef TFS
1144 if (flags & SCSI_DATA_UIO) {
1145 iovp = ((struct uio *) xs->data)->uio_iov;
1146 datalen = ((struct uio *) xs->data)->uio_iovcnt;
1147 xs->datalen = 0;
1148 while ((datalen) && (seg < UHA_NSEG)) {
1149 scratch = (unsigned long) iovp->iov_base;
1150 sg->addr.addr[0] = (scratch & 0xff);
1151 sg->addr.addr[1] = ((scratch >> 8) & 0xff);
1152 sg->addr.addr[2] = ((scratch >> 16) & 0xff);
1153 sg->addr.addr[3] = ((scratch >> 24) & 0xff);
1154 xs->datalen += *(unsigned long *) sg->len.len = iovp->iov_len;
1155 SC_DEBUGN(xs->sc_link, SDEV_DB4, ("(0x%x@0x%x)",
1156 iovp->iov_len,
1157 iovp->iov_base));
1158 sg++;
1159 iovp++;
1160 seg++;
1161 datalen--;
1162 }
1163 } else
1164 #endif /*TFS */
1165 {
1166 /*
1167 * Set up the scatter gather block
1168 */
1169
1170 SC_DEBUG(xs->sc_link, SDEV_DB4,
1171 ("%ld @%p:- ", xs->datalen, xs->data));
1172 datalen = xs->datalen;
1173 thiskv = (int) xs->data;
1174 thisphys = KVTOPHYS(thiskv);
1175 templen = 0;
1176
1177 while ((datalen) && (seg < UHA_NSEG)) {
1178 bytes_this_seg = 0;
1179
1180 /* put in the base address */
1181 sg->addr.addr[0] = (thisphys & 0xff);
1182 sg->addr.addr[1] = ((thisphys >> 8) & 0xff);
1183 sg->addr.addr[2] = ((thisphys >> 16) & 0xff);
1184 sg->addr.addr[3] = ((thisphys >> 24) & 0xff);
1185
1186 SC_DEBUGN(xs->sc_link, SDEV_DB4, ("0x%lx",
1187 thisphys));
1188
1189 /* do it at least once */
1190 nextphys = thisphys;
1191 while ((datalen) && (thisphys == nextphys))
1192 /*
1193 * This page is contiguous (physically) with
1194 * the the last, just extend the length
1195 */
1196 {
1197 /* how far to the end of the page */
1198 nextphys = (thisphys & (~(PAGESIZ - 1)))
1199 + PAGESIZ;
1200 bytes_this_page = nextphys - thisphys;
1201 /**** or the data ****/
1202 bytes_this_page = min(bytes_this_page
1203 ,datalen);
1204 bytes_this_seg += bytes_this_page;
1205 datalen -= bytes_this_page;
1206
1207 /* get more ready for the next page */
1208 thiskv = (thiskv & (~(PAGESIZ - 1)))
1209 + PAGESIZ;
1210 if (datalen)
1211 thisphys = KVTOPHYS(thiskv);
1212 }
1213 /*
1214 * next page isn't contiguous, finish the seg
1215 */
1216 SC_DEBUGN(xs->sc_link, SDEV_DB4,
1217 ("(0x%x)", bytes_this_seg));
1218 sg->len.len[0] = (bytes_this_seg & 0xff);
1219 sg->len.len[1] = ((bytes_this_seg >> 8) & 0xff);
1220 sg->len.len[2] = ((bytes_this_seg >> 16) & 0xff);
1221 sg->len.len[3] = ((bytes_this_seg >> 24) & 0xff);
1222 templen += bytes_this_seg;
1223 sg++;
1224 seg++;
1225 }
1226 }
1227
1228 /* end of iov/kv decision */
1229 mscp->datalen.len[0] = (templen & 0xff);
1230 mscp->datalen.len[1] = ((templen >> 8) & 0xff);
1231 mscp->datalen.len[2] = ((templen >> 16) & 0xff);
1232 mscp->datalen.len[3] = ((templen >> 24) & 0xff);
1233 mscp->sg_num = seg;
1234
1235 SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
1236 if (datalen) { /* there's still data, must have run out of segs! */
1237 printf("uha%d: uha_scsi_cmd, more than %d DMA segs\n",
1238 uha->unit, UHA_NSEG);
1239 xs->error = XS_DRIVER_STUFFUP;
1240 uha_free_mscp(uha, mscp, flags);
1241 return (HAD_ERROR);
1242 }
1243 } else { /* No data xfer, use non S/G values */
1244 mscp->data.addr[0] = 0x00;
1245 mscp->data.addr[1] = 0x00;
1246 mscp->data.addr[2] = 0x00;
1247 mscp->data.addr[3] = 0x00;
1248 mscp->datalen.len[0] = 0x00;
1249 mscp->datalen.len[1] = 0x00;
1250 mscp->datalen.len[2] = 0x00;
1251 mscp->datalen.len[3] = 0x00;
1252 mscp->xdir = 0x03;
1253 mscp->sgth = 0x00;
1254 mscp->sg_num = 0x00;
1255 }
1256
1257 /*
1258 * Put the scsi command in the mscp and start it
1259 */
1260 bcopy(xs->cmd, mscp->cdb, xs->cmdlen);
1261
1262 /*
1263 * Usually return SUCCESSFULLY QUEUED
1264 */
1265 if (!(flags & SCSI_NOMASK)) {
1266 s = splbio();
1267 uha_send_mbox(uha, mscp);
1268 timeout(uha_timeout, (caddr_t)mscp, (xs->timeout * hz) / 1000);
1269 splx(s);
1270 SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
1271 return (SUCCESSFULLY_QUEUED);
1272 }
1273
1274 /*
1275 * If we can't use interrupts, poll on completion
1276 */
1277 uha_send_mbox(uha, mscp);
1278 SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_wait\n"));
1279 do {
1280 if (uha_poll(uha, xs->timeout)) {
1281 if (!(xs->flags & SCSI_SILENT))
1282 printf("uha%d: cmd fail\n", uha->unit);
1283 if (!(uha_abort(uha, mscp))) {
1284 printf("uha%d: abort failed in wait\n",
1285 uha->unit);
1286 uha_free_mscp(uha, mscp, flags);
1287 }
1288 xs->error = XS_DRIVER_STUFFUP;
1289 return (HAD_ERROR);
1290 }
1291 }
1292 while (!(xs->flags & ITSDONE)); /* something (?) else finished */
1293 if (xs->error) {
1294 return (HAD_ERROR);
1295 }
1296 return (COMPLETE);
1297 }
1298
1299 static void
1300 uha_timeout(arg1)
1301 void *arg1;
1302 {
1303 struct mscp *mscp = (struct mscp *)arg1;
1304 struct uha_data *uha;
1305 int s = splbio();
1306
1307 uha = (struct uha_data *)mscp->xs->sc_link->adapter_softc;
1308 printf("uha%d:%d:%d (%s%d) timed out ", uha->unit
1309 ,mscp->xs->sc_link->target
1310 ,mscp->xs->sc_link->lun
1311 ,mscp->xs->sc_link->device->name
1312 ,mscp->xs->sc_link->dev_unit);
1313
1314 #ifdef UHADEBUG
1315 uha_print_active_mscp(uha);
1316 #endif /*UHADEBUG */
1317
1318 if ((uha_abort(uha, mscp) != 1) || (mscp->flags = MSCP_ABORTED)) {
1319 printf("AGAIN");
1320 mscp->xs->retries = 0; /* I MEAN IT ! */
1321 uha_done(uha, mscp);
1322 } else { /* abort the operation that has timed out */
1323 printf("\n");
1324 timeout(uha_timeout, (caddr_t)mscp, 2 * hz);
1325 mscp->flags = MSCP_ABORTED;
1326 }
1327 splx(s);
1328 }
1329
1330 #ifdef UHADEBUG
1331 void
1332 uha_print_mscp(mscp)
1333 struct mscp *mscp;
1334 {
1335 printf("mscp:%x op:%x cmdlen:%d senlen:%d\n"
1336 ,mscp
1337 ,mscp->opcode
1338 ,mscp->cdblen
1339 ,mscp->senselen);
1340 printf(" sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x flags:%x\n"
1341 ,mscp->sgth
1342 ,mscp->sg_num
1343 ,mscp->datalen
1344 ,mscp->ha_status
1345 ,mscp->targ_status
1346 ,mscp->flags);
1347 show_scsi_cmd(mscp->xs);
1348 }
1349
1350 void
1351 uha_print_active_mscp(struct uha_data *uha)
1352 {
1353 struct mscp *mscp;
1354 int i = 0;
1355
1356 while (i < MSCP_HASH_SIZE) {
1357 mscp = uha->mscphash[i];
1358 while (mscp) {
1359 if (mscp->flags != MSCP_FREE) {
1360 uha_print_mscp(mscp);
1361 }
1362 mscp = mscp->nexthash;
1363 }
1364 i++;
1365 }
1366 }
1367 #endif /*UHADEBUG */
1368 #endif /*KERNEL */
Cache object: 0f78edf61b5563a737047c31a74df7d6
|