1 /* $NetBSD: aha.c,v 1.59 2009/09/21 08:12:47 tsutsui Exp $ */
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Originally written by Julian Elischer (julian@tfs.com)
35 * for TRW Financial Systems for use under the MACH(2.5) operating system.
37 * TRW Financial Systems, in accordance with their agreement with Carnegie
38 * Mellon University, makes this software available to CMU to distribute
39 * or use in any manner that they see fit as long as this message is kept with
40 * the software. For this reason TFS also grants any other persons or
41 * organisations permission to use or modify this software.
43 * TFS supplies this software to be publicly redistributed
44 * on the understanding that TFS is not responsible for the correct
45 * functioning of this software in any circumstances.
48 #include <sys/cdefs.h>
49 __KERNEL_RCSID(0, "$NetBSD: aha.c,v 1.59 2009/09/21 08:12:47 tsutsui Exp $");
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/callout.h>
58 #include <sys/kernel.h>
59 #include <sys/errno.h>
60 #include <sys/ioctl.h>
61 #include <sys/device.h>
62 #include <sys/malloc.h>
66 #include <uvm/uvm_extern.h>
71 #include <dev/scsipi/scsi_all.h>
72 #include <dev/scsipi/scsipi_all.h>
73 #include <dev/scsipi/scsiconf.h>
75 #include <dev/ic/ahareg.h>
76 #include <dev/ic/ahavar.h>
79 #define Debugger() panic("should call debugger here (aha1542.c)")
82 #define AHA_MAXXFER ((AHA_NSEG - 1) << PGSHIFT)
88 static int aha_cmd(bus_space_tag_t
, bus_space_handle_t
,
89 struct aha_softc
*, int, u_char
*, int, u_char
*);
90 static void aha_finish_ccbs(struct aha_softc
*);
91 static void aha_free_ccb(struct aha_softc
*, struct aha_ccb
*);
92 static int aha_init_ccb(struct aha_softc
*, struct aha_ccb
*);
93 static struct aha_ccb
*aha_get_ccb(struct aha_softc
*);
94 static struct aha_ccb
*aha_ccb_phys_kv(struct aha_softc
*, u_long
);
95 static void aha_queue_ccb(struct aha_softc
*, struct aha_ccb
*);
96 static void aha_collect_mbo(struct aha_softc
*);
97 static void aha_start_ccbs(struct aha_softc
*);
98 static void aha_done(struct aha_softc
*, struct aha_ccb
*);
99 static int aha_init(struct aha_softc
*);
100 static void aha_inquire_setup_information(struct aha_softc
*);
101 static void ahaminphys(struct buf
*);
102 static void aha_scsipi_request(struct scsipi_channel
*,
103 scsipi_adapter_req_t
, void *);
104 static int aha_poll(struct aha_softc
*, struct scsipi_xfer
*, int);
105 static void aha_timeout(void *arg
);
106 static int aha_create_ccbs(struct aha_softc
*, struct aha_ccb
*, int);
108 #define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
109 #define AHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */
112 * aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
114 * Activate Adapter command
115 * icnt: number of args (outbound bytes including opcode)
116 * ibuf: argument buffer
117 * ocnt: number of expected returned bytes
118 * obuf: result buffer
119 * wait: number of seconds to wait for response
121 * Performs an adapter command through the ports. Not to be confused with a
122 * scsi command, which is read in via the DMA; one of the adapter commands
123 * tells it to read in a scsi command.
126 aha_cmd(bus_space_tag_t iot
, bus_space_handle_t ioh
, struct aha_softc
*sc
,
127 int icnt
, u_char
*ibuf
, int ocnt
, u_char
*obuf
)
133 u_char opcode
= ibuf
[0];
136 name
= device_xname(sc
->sc_dev
);
138 name
= "(aha probe)";
141 * Calculate a reasonable timeout for the command.
144 case AHA_INQUIRE_DEVICES
:
153 * Wait for the adapter to go idle, unless it's one of
154 * the commands which don't need this
156 if (opcode
!= AHA_MBO_INTR_EN
) {
157 for (i
= 20000; i
; i
--) { /* 1 sec? */
158 sts
= bus_space_read_1(iot
, ioh
, AHA_STAT_PORT
);
159 if (sts
& AHA_STAT_IDLE
)
164 printf("%s: aha_cmd, host not idle(0x%x)\n",
170 * Now that it is idle, if we expect output, preflush the
171 * queue feeding to us.
174 while ((bus_space_read_1(iot
, ioh
, AHA_STAT_PORT
)) & AHA_STAT_DF
)
175 bus_space_read_1(iot
, ioh
, AHA_DATA_PORT
);
178 * Output the command and the number of arguments given
179 * for each byte, first check the port is empty.
182 for (i
= wait
; i
; i
--) {
183 sts
= bus_space_read_1(iot
, ioh
, AHA_STAT_PORT
);
184 if (!(sts
& AHA_STAT_CDF
))
189 if (opcode
!= AHA_INQUIRE_REVISION
)
190 printf("%s: aha_cmd, cmd/data port full\n", name
);
191 bus_space_write_1(iot
, ioh
, AHA_CTRL_PORT
, AHA_CTRL_SRST
);
194 bus_space_write_1(iot
, ioh
, AHA_CMD_PORT
, *ibuf
++);
197 * If we expect input, loop that many times, each time,
198 * looking for the data register to have valid data
201 for (i
= wait
; i
; i
--) {
202 sts
= bus_space_read_1(iot
, ioh
, AHA_STAT_PORT
);
203 if (sts
& AHA_STAT_DF
)
208 if (opcode
!= AHA_INQUIRE_REVISION
)
209 printf("%s: aha_cmd, cmd/data port empty %d\n",
211 bus_space_write_1(iot
, ioh
, AHA_CTRL_PORT
, AHA_CTRL_SRST
);
214 *obuf
++ = bus_space_read_1(iot
, ioh
, AHA_DATA_PORT
);
217 * Wait for the board to report a finished instruction.
218 * We may get an extra interrupt for the HACC signal, but this is
221 if (opcode
!= AHA_MBO_INTR_EN
) {
222 for (i
= 20000; i
; i
--) { /* 1 sec? */
223 sts
= bus_space_read_1(iot
, ioh
, AHA_INTR_PORT
);
224 /* XXX Need to save this in the interrupt handler? */
225 if (sts
& AHA_INTR_HACC
)
230 printf("%s: aha_cmd, host not finished(0x%x)\n",
235 bus_space_write_1(iot
, ioh
, AHA_CTRL_PORT
, AHA_CTRL_IRST
);
240 aha_attach(struct aha_softc
*sc
, struct aha_probe_data
*apd
)
242 struct scsipi_adapter
*adapt
= &sc
->sc_adapter
;
243 struct scsipi_channel
*chan
= &sc
->sc_channel
;
245 TAILQ_INIT(&sc
->sc_free_ccb
);
246 TAILQ_INIT(&sc
->sc_waiting_ccb
);
249 * Fill in the scsipi_adapter.
251 memset(adapt
, 0, sizeof(*adapt
));
252 adapt
->adapt_dev
= sc
->sc_dev
;
253 adapt
->adapt_nchannels
= 1;
254 /* adapt_openings initialized below */
255 /* adapt_max_periph initialized below */
256 adapt
->adapt_request
= aha_scsipi_request
;
257 adapt
->adapt_minphys
= ahaminphys
;
260 * Fill in the scsipi_channel.
262 memset(chan
, 0, sizeof(*chan
));
263 chan
->chan_adapter
= adapt
;
264 chan
->chan_bustype
= &scsi_bustype
;
265 chan
->chan_channel
= 0;
266 chan
->chan_ntargets
= 8;
267 chan
->chan_nluns
= 8;
268 chan
->chan_id
= apd
->sc_scsi_dev
;
270 aha_inquire_setup_information(sc
);
271 if (aha_init(sc
) != 0) {
272 /* Error during initialization! */
277 * ask the adapter what subunits are present
279 config_found(sc
->sc_dev
, &sc
->sc_channel
, scsiprint
);
283 aha_finish_ccbs(struct aha_softc
*sc
)
285 struct aha_mbx_in
*wmbi
;
291 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
292 AHA_MBI_OFF(wmbi
), sizeof(struct aha_mbx_in
),
293 BUS_DMASYNC_POSTREAD
|BUS_DMASYNC_POSTWRITE
);
295 if (wmbi
->stat
== AHA_MBI_FREE
) {
296 for (i
= 0; i
< AHA_MBX_SIZE
; i
++) {
297 if (wmbi
->stat
!= AHA_MBI_FREE
) {
298 printf("%s: mbi not in round-robin order\n",
299 device_xname(sc
->sc_dev
));
302 aha_nextmbx(wmbi
, wmbx
, mbi
);
303 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
304 AHA_MBI_OFF(wmbi
), sizeof(struct aha_mbx_in
),
305 BUS_DMASYNC_POSTREAD
|BUS_DMASYNC_POSTWRITE
);
308 printf("%s: mbi interrupt with no full mailboxes\n",
309 device_xname(sc
->sc_dev
));
316 ccb
= aha_ccb_phys_kv(sc
, phystol(wmbi
->ccb_addr
));
318 printf("%s: bad mbi ccb pointer; skipping\n",
319 device_xname(sc
->sc_dev
));
323 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
324 AHA_CCB_OFF(ccb
), sizeof(struct aha_ccb
),
325 BUS_DMASYNC_POSTREAD
|BUS_DMASYNC_POSTWRITE
);
329 u_char
*cp
= ccb
->scsi_cmd
;
330 printf("op=%x %x %x %x %x %x\n",
331 cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5]);
332 printf("stat %x for mbi addr = %p, ",
334 printf("ccb addr = %p\n", ccb
);
336 #endif /* AHADEBUG */
338 switch (wmbi
->stat
) {
341 if ((ccb
->flags
& CCB_ABORT
) != 0) {
343 * If we already started an abort, wait for it
344 * to complete before clearing the CCB. We
345 * could instead just clear CCB_SENDING, but
346 * what if the mailbox was already received?
347 * The worst that happens here is that we clear
348 * the CCB a bit later than we need to. BFD.
355 case AHA_MBI_UNKNOWN
:
357 * Even if the CCB wasn't found, we clear it anyway.
358 * See preceding comment.
363 printf("%s: bad mbi status %02x; skipping\n",
364 device_xname(sc
->sc_dev
), wmbi
->stat
);
368 callout_stop(&ccb
->xs
->xs_callout
);
372 wmbi
->stat
= AHA_MBI_FREE
;
373 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
374 AHA_MBI_OFF(wmbi
), sizeof(struct aha_mbx_in
),
375 BUS_DMASYNC_PREREAD
|BUS_DMASYNC_PREWRITE
);
376 aha_nextmbx(wmbi
, wmbx
, mbi
);
377 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
378 AHA_MBI_OFF(wmbi
), sizeof(struct aha_mbx_in
),
379 BUS_DMASYNC_POSTREAD
|BUS_DMASYNC_POSTWRITE
);
380 } while (wmbi
->stat
!= AHA_MBI_FREE
);
386 * Catch an interrupt from the adaptor
391 struct aha_softc
*sc
= arg
;
392 bus_space_tag_t iot
= sc
->sc_iot
;
393 bus_space_handle_t ioh
= sc
->sc_ioh
;
397 printf("%s: aha_intr ", device_xname(sc
->sc_dev
));
401 * First acknowledge the interrupt, Then if it's not telling about
402 * a completed operation just return.
404 sts
= bus_space_read_1(iot
, ioh
, AHA_INTR_PORT
);
405 if ((sts
& AHA_INTR_ANYINTR
) == 0)
407 bus_space_write_1(iot
, ioh
, AHA_CTRL_PORT
, AHA_CTRL_IRST
);
410 /* Make sure we clear CCB_SENDING before finishing a CCB. */
414 /* Mail box out empty? */
415 if (sts
& AHA_INTR_MBOA
) {
416 struct aha_toggle toggle
;
418 toggle
.cmd
.opcode
= AHA_MBO_INTR_EN
;
419 toggle
.cmd
.enable
= 0;
420 aha_cmd(iot
, ioh
, sc
,
421 sizeof(toggle
.cmd
), (u_char
*)&toggle
.cmd
,
426 /* Mail box in full? */
427 if (sts
& AHA_INTR_MBIF
)
434 aha_reset_ccb(struct aha_softc
*sc
, struct aha_ccb
*ccb
)
441 * A ccb is put onto the free list.
444 aha_free_ccb(struct aha_softc
*sc
, struct aha_ccb
*ccb
)
449 aha_reset_ccb(sc
, ccb
);
450 TAILQ_INSERT_HEAD(&sc
->sc_free_ccb
, ccb
, chain
);
455 aha_init_ccb(struct aha_softc
*sc
, struct aha_ccb
*ccb
)
457 bus_dma_tag_t dmat
= sc
->sc_dmat
;
461 * Create the DMA map for this CCB.
463 error
= bus_dmamap_create(dmat
, AHA_MAXXFER
, AHA_NSEG
, AHA_MAXXFER
,
464 0, BUS_DMA_NOWAIT
|BUS_DMA_ALLOCNOW
, &ccb
->dmamap_xfer
);
466 aprint_error_dev(sc
->sc_dev
,
467 "unable to create ccb DMA map, error = %d\n",
473 * put in the phystokv hash table
474 * Never gets taken out.
476 ccb
->hashkey
= sc
->sc_dmamap_control
->dm_segs
[0].ds_addr
+
478 hashnum
= CCB_HASH(ccb
->hashkey
);
479 ccb
->nexthash
= sc
->sc_ccbhash
[hashnum
];
480 sc
->sc_ccbhash
[hashnum
] = ccb
;
481 aha_reset_ccb(sc
, ccb
);
486 * Create a set of ccbs and add them to the free list. Called once
487 * by aha_init(). We return the number of CCBs successfully created.
490 aha_create_ccbs(struct aha_softc
*sc
, struct aha_ccb
*ccbstore
, int count
)
495 memset(ccbstore
, 0, sizeof(struct aha_ccb
) * count
);
496 for (i
= 0; i
< count
; i
++) {
498 if ((error
= aha_init_ccb(sc
, ccb
)) != 0) {
499 aprint_error_dev(sc
->sc_dev
,
500 "unable to initialize ccb, error = %d\n",
504 TAILQ_INSERT_TAIL(&sc
->sc_free_ccb
, ccb
, chain
);
513 * If there are none, see if we can allocate a new one. If so, put it in
514 * the hash table too otherwise either return an error or sleep.
517 aha_get_ccb(struct aha_softc
*sc
)
523 ccb
= TAILQ_FIRST(&sc
->sc_free_ccb
);
525 TAILQ_REMOVE(&sc
->sc_free_ccb
, ccb
, chain
);
526 ccb
->flags
|= CCB_ALLOC
;
533 * Given a physical address, find the ccb that it corresponds to.
535 static struct aha_ccb
*
536 aha_ccb_phys_kv(struct aha_softc
*sc
, u_long ccb_phys
)
538 int hashnum
= CCB_HASH(ccb_phys
);
539 struct aha_ccb
*ccb
= sc
->sc_ccbhash
[hashnum
];
542 if (ccb
->hashkey
== ccb_phys
)
550 * Queue a CCB to be sent to the controller, and send it if possible.
553 aha_queue_ccb(struct aha_softc
*sc
, struct aha_ccb
*ccb
)
556 TAILQ_INSERT_TAIL(&sc
->sc_waiting_ccb
, ccb
, chain
);
561 * Garbage collect mailboxes that are no longer in use.
564 aha_collect_mbo(struct aha_softc
*sc
)
566 struct aha_mbx_out
*wmbo
; /* Mail Box Out pointer */
573 while (sc
->sc_mbofull
> 0) {
574 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
575 AHA_MBO_OFF(wmbo
), sizeof(struct aha_mbx_out
),
576 BUS_DMASYNC_POSTREAD
|BUS_DMASYNC_POSTWRITE
);
577 if (wmbo
->cmd
!= AHA_MBO_FREE
)
581 ccb
= aha_ccb_phys_kv(sc
, phystol(wmbo
->ccb_addr
));
582 ccb
->flags
&= ~CCB_SENDING
;
586 aha_nextmbx(wmbo
, wmbx
, mbo
);
593 * Send as many CCBs as we have empty mailboxes for.
596 aha_start_ccbs(struct aha_softc
*sc
)
598 bus_space_tag_t iot
= sc
->sc_iot
;
599 bus_space_handle_t ioh
= sc
->sc_ioh
;
600 struct aha_mbx_out
*wmbo
; /* Mail Box Out pointer */
605 while ((ccb
= sc
->sc_waiting_ccb
.tqh_first
) != NULL
) {
606 if (sc
->sc_mbofull
>= AHA_MBX_SIZE
) {
608 if (sc
->sc_mbofull
>= AHA_MBX_SIZE
) {
609 struct aha_toggle toggle
;
611 toggle
.cmd
.opcode
= AHA_MBO_INTR_EN
;
612 toggle
.cmd
.enable
= 1;
613 aha_cmd(iot
, ioh
, sc
,
614 sizeof(toggle
.cmd
), (u_char
*)&toggle
.cmd
,
620 TAILQ_REMOVE(&sc
->sc_waiting_ccb
, ccb
, chain
);
622 ccb
->flags
|= CCB_SENDING
;
625 /* Link ccb to mbo. */
626 ltophys(sc
->sc_dmamap_control
->dm_segs
[0].ds_addr
+
627 AHA_CCB_OFF(ccb
), wmbo
->ccb_addr
);
628 if (ccb
->flags
& CCB_ABORT
)
629 wmbo
->cmd
= AHA_MBO_ABORT
;
631 wmbo
->cmd
= AHA_MBO_START
;
633 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
634 AHA_MBO_OFF(wmbo
), sizeof(struct aha_mbx_out
),
635 BUS_DMASYNC_PREREAD
|BUS_DMASYNC_PREWRITE
);
637 /* Tell the card to poll immediately. */
638 bus_space_write_1(iot
, ioh
, AHA_CMD_PORT
, AHA_START_SCSI
);
640 if ((ccb
->xs
->xs_control
& XS_CTL_POLL
) == 0)
641 callout_reset(&ccb
->xs
->xs_callout
,
642 mstohz(ccb
->timeout
), aha_timeout
, ccb
);
645 aha_nextmbx(wmbo
, wmbx
, mbo
);
652 * We have a ccb which has been processed by the
653 * adaptor, now we look to see how the operation
654 * went. Wake up the owner if waiting
657 aha_done(struct aha_softc
*sc
, struct aha_ccb
*ccb
)
659 bus_dma_tag_t dmat
= sc
->sc_dmat
;
660 struct scsi_sense_data
*s1
, *s2
;
661 struct scsipi_xfer
*xs
= ccb
->xs
;
663 SC_DEBUG(xs
->xs_periph
, SCSIPI_DB2
, ("aha_done\n"));
666 * If we were a data transfer, unload the map that described
670 bus_dmamap_sync(dmat
, ccb
->dmamap_xfer
, 0,
671 ccb
->dmamap_xfer
->dm_mapsize
,
672 (xs
->xs_control
& XS_CTL_DATA_IN
) ? BUS_DMASYNC_POSTREAD
:
673 BUS_DMASYNC_POSTWRITE
);
674 bus_dmamap_unload(dmat
, ccb
->dmamap_xfer
);
678 * Otherwise, put the results of the operation
679 * into the xfer and call whoever started it
682 if (ccb
->flags
& CCB_SENDING
) {
683 printf("%s: exiting ccb still in transit!\n",
684 device_xname(sc
->sc_dev
));
689 if ((ccb
->flags
& CCB_ALLOC
) == 0) {
690 printf("%s: exiting ccb not allocated!\n",
691 device_xname(sc
->sc_dev
));
695 if (xs
->error
== XS_NOERROR
) {
696 if (ccb
->host_stat
!= AHA_OK
) {
697 switch (ccb
->host_stat
) {
698 case AHA_SEL_TIMEOUT
: /* No response */
699 xs
->error
= XS_SELTIMEOUT
;
701 default: /* Other scsi protocol messes */
702 printf("%s: host_stat %x\n",
703 device_xname(sc
->sc_dev
), ccb
->host_stat
);
704 xs
->error
= XS_DRIVER_STUFFUP
;
707 } else if (ccb
->target_stat
!= SCSI_OK
) {
708 switch (ccb
->target_stat
) {
710 s1
= (struct scsi_sense_data
*) (((char *) (&ccb
->scsi_cmd
)) +
711 ccb
->scsi_cmd_length
);
712 s2
= &xs
->sense
.scsi_sense
;
714 xs
->error
= XS_SENSE
;
720 printf("%s: target_stat %x\n",
721 device_xname(sc
->sc_dev
), ccb
->target_stat
);
722 xs
->error
= XS_DRIVER_STUFFUP
;
728 aha_free_ccb(sc
, ccb
);
733 * Find the board and find its irq/drq
736 aha_find(bus_space_tag_t iot
, bus_space_handle_t ioh
, struct aha_probe_data
*sc
)
740 struct aha_config config
;
744 * assume invalid status means the board is not present.
747 sts
= bus_space_read_1(iot
, ioh
, AHA_STAT_PORT
);
750 if ((sts
& (AHA_STAT_STST
|AHA_STAT_RSVD
|AHA_STAT_CDF
)) != 0)
752 sts
= bus_space_read_1(iot
, ioh
, AHA_INTR_PORT
);
753 if ((sts
& AHA_INTR_RSVD
) != 0)
757 * reset board, If it doesn't respond, assume
758 * that it's not there.. good for the probe
761 bus_space_write_1(iot
, ioh
, AHA_CTRL_PORT
, AHA_CTRL_HRST
| AHA_CTRL_SRST
);
764 for (i
= AHA_RESET_TIMEOUT
; i
; i
--) {
765 sts
= bus_space_read_1(iot
, ioh
, AHA_STAT_PORT
);
766 if (sts
== (AHA_STAT_IDLE
| AHA_STAT_INIT
))
768 delay(1000); /* calibrated in msec */
773 printf("aha_find: No answer from adaptec board\n");
774 #endif /* AHADEBUG */
779 * setup DMA channel from jumpers and save int
782 delay(1000); /* for Bustek 545 */
783 config
.cmd
.opcode
= AHA_INQUIRE_CONFIG
;
784 aha_cmd(iot
, ioh
, (struct aha_softc
*)0,
785 sizeof(config
.cmd
), (u_char
*)&config
.cmd
,
786 sizeof(config
.reply
), (u_char
*)&config
.reply
);
787 switch (config
.reply
.chan
) {
804 printf("aha_find: illegal drq setting %x\n", config
.reply
.chan
);
808 switch (config
.reply
.intr
) {
828 printf("aha_find: illegal irq setting %x\n", config
.reply
.intr
);
835 sc
->sc_scsi_dev
= config
.reply
.scsi_dev
;
842 * Start the board, ready for normal operation
845 aha_init(struct aha_softc
*sc
)
847 bus_space_tag_t iot
= sc
->sc_iot
;
848 bus_space_handle_t ioh
= sc
->sc_ioh
;
849 bus_dma_segment_t seg
;
850 struct aha_devices devices
;
851 struct aha_setup setup
;
852 struct aha_mailbox mailbox
;
853 int error
, i
, j
, initial_ccbs
, rseg
;
857 * If we are a 1542C or later, disable the extended BIOS so that the
858 * mailbox interface is unlocked.
859 * No need to check the extended BIOS flags as some of the
860 * extensions that cause us problems are not flagged in that byte.
862 if (!strncmp(sc
->sc_model
, "1542C", 5)) {
863 struct aha_extbios extbios
;
864 struct aha_unlock unlock
;
866 printf("%s: unlocking mailbox interface\n",
867 device_xname(sc
->sc_dev
));
868 extbios
.cmd
.opcode
= AHA_EXT_BIOS
;
869 aha_cmd(iot
, ioh
, sc
,
870 sizeof(extbios
.cmd
), (u_char
*)&extbios
.cmd
,
871 sizeof(extbios
.reply
), (u_char
*)&extbios
.reply
);
874 printf("%s: flags=%02x, mailboxlock=%02x\n",
875 device_xname(sc
->sc_dev
),
876 extbios
.reply
.flags
, extbios
.reply
.mailboxlock
);
877 #endif /* AHADEBUG */
879 unlock
.cmd
.opcode
= AHA_MBX_ENABLE
;
881 unlock
.cmd
.magic
= extbios
.reply
.mailboxlock
;
882 aha_cmd(iot
, ioh
, sc
,
883 sizeof(unlock
.cmd
), (u_char
*)&unlock
.cmd
,
889 * Change the bus on/off times to not clash with other DMA users.
891 aha_cmd(iot
, ioh
, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET
, 7);
892 aha_cmd(iot
, ioh
, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET
, 4);
895 /* Inquire Installed Devices (to force synchronous negotiation). */
896 devices
.cmd
.opcode
= AHA_INQUIRE_DEVICES
;
897 aha_cmd(iot
, ioh
, sc
,
898 sizeof(devices
.cmd
), (u_char
*)&devices
.cmd
,
899 sizeof(devices
.reply
), (u_char
*)&devices
.reply
);
901 /* Count installed units */
903 for (i
= 0; i
< 8; i
++) {
904 for (j
= 0; j
< 8; j
++) {
905 if (((devices
.reply
.lun_map
[i
] >> j
) & 1) == 1)
910 if (initial_ccbs
> AHA_CCB_MAX
)
911 initial_ccbs
= AHA_CCB_MAX
;
912 if (initial_ccbs
== 0) /* yes, this can happen */
915 /* Obtain setup information from. */
916 setup
.cmd
.opcode
= AHA_INQUIRE_SETUP
;
917 setup
.cmd
.len
= sizeof(setup
.reply
);
918 aha_cmd(iot
, ioh
, sc
,
919 sizeof(setup
.cmd
), (u_char
*)&setup
.cmd
,
920 sizeof(setup
.reply
), (u_char
*)&setup
.reply
);
922 printf("%s: %s, %s\n",
923 device_xname(sc
->sc_dev
),
924 setup
.reply
.sync_neg
? "sync" : "async",
925 setup
.reply
.parity
? "parity" : "no parity");
927 for (i
= 0; i
< 8; i
++) {
928 if (!setup
.reply
.sync
[i
].valid
||
929 (!setup
.reply
.sync
[i
].offset
&& !setup
.reply
.sync
[i
].period
))
931 printf("%s targ %d: sync, offset %d, period %dnsec\n",
932 device_xname(sc
->sc_dev
), i
,
933 setup
.reply
.sync
[i
].offset
, setup
.reply
.sync
[i
].period
* 50 + 200);
937 * Allocate the mailbox and control blocks.
939 if ((error
= bus_dmamem_alloc(sc
->sc_dmat
, sizeof(struct aha_control
),
940 PAGE_SIZE
, 0, &seg
, 1, &rseg
, BUS_DMA_NOWAIT
)) != 0) {
941 aprint_error_dev(sc
->sc_dev
,
942 "unable to allocate control structures, "
943 "error = %d\n", error
);
946 if ((error
= bus_dmamem_map(sc
->sc_dmat
, &seg
, rseg
,
947 sizeof(struct aha_control
), (void **)&sc
->sc_control
,
948 BUS_DMA_NOWAIT
|BUS_DMA_COHERENT
)) != 0) {
949 aprint_error_dev(sc
->sc_dev
,
950 "unable to map control structures, error = %d\n", error
);
955 * Create and load the DMA map used for the mailbox and
958 if ((error
= bus_dmamap_create(sc
->sc_dmat
, sizeof(struct aha_control
),
959 1, sizeof(struct aha_control
), 0, BUS_DMA_NOWAIT
,
960 &sc
->sc_dmamap_control
)) != 0) {
961 aprint_error_dev(sc
->sc_dev
,
962 "unable to create control DMA map, error = %d\n",
966 if ((error
= bus_dmamap_load(sc
->sc_dmat
, sc
->sc_dmamap_control
,
967 sc
->sc_control
, sizeof(struct aha_control
), NULL
,
968 BUS_DMA_NOWAIT
)) != 0) {
969 aprint_error_dev(sc
->sc_dev
,
970 "unable to load control DMA map, error = %d\n",
976 * Initialize the control blocks.
978 i
= aha_create_ccbs(sc
, sc
->sc_control
->ac_ccbs
, initial_ccbs
);
980 aprint_error_dev(sc
->sc_dev
,
981 "unable to create control blocks\n");
983 } else if (i
!= initial_ccbs
) {
984 printf("%s: WARNING: only %d of %d control blocks created\n",
985 device_xname(sc
->sc_dev
), i
, initial_ccbs
);
988 sc
->sc_adapter
.adapt_openings
= i
;
989 sc
->sc_adapter
.adapt_max_periph
= sc
->sc_adapter
.adapt_openings
;
992 * Set up initial mail box for round-robin operation.
994 for (i
= 0; i
< AHA_MBX_SIZE
; i
++) {
995 wmbx
->mbo
[i
].cmd
= AHA_MBO_FREE
;
996 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
997 AHA_MBO_OFF(&wmbx
->mbo
[i
]), sizeof(struct aha_mbx_out
),
998 BUS_DMASYNC_PREREAD
|BUS_DMASYNC_PREWRITE
);
999 wmbx
->mbi
[i
].stat
= AHA_MBI_FREE
;
1000 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
1001 AHA_MBI_OFF(&wmbx
->mbi
[i
]), sizeof(struct aha_mbx_in
),
1002 BUS_DMASYNC_PREREAD
|BUS_DMASYNC_PREWRITE
);
1004 wmbx
->cmbo
= wmbx
->tmbo
= &wmbx
->mbo
[0];
1005 wmbx
->tmbi
= &wmbx
->mbi
[0];
1008 /* Initialize mail box. */
1009 mailbox
.cmd
.opcode
= AHA_MBX_INIT
;
1010 mailbox
.cmd
.nmbx
= AHA_MBX_SIZE
;
1011 ltophys(sc
->sc_dmamap_control
->dm_segs
[0].ds_addr
+
1012 offsetof(struct aha_control
, ac_mbx
), mailbox
.cmd
.addr
);
1013 aha_cmd(iot
, ioh
, sc
,
1014 sizeof(mailbox
.cmd
), (u_char
*)&mailbox
.cmd
,
1020 aha_inquire_setup_information(struct aha_softc
*sc
)
1022 bus_space_tag_t iot
= sc
->sc_iot
;
1023 bus_space_handle_t ioh
= sc
->sc_ioh
;
1024 struct aha_revision revision
;
1029 strcpy(sc
->sc_model
, "unknown");
1032 * Assume we have a board at this stage, do an adapter inquire
1033 * to find out what type of controller it is. If the command
1034 * fails, we assume it's either a crusty board or an old 1542
1035 * clone, and skip the board-specific stuff.
1037 revision
.cmd
.opcode
= AHA_INQUIRE_REVISION
;
1038 if (aha_cmd(iot
, ioh
, sc
,
1039 sizeof(revision
.cmd
), (u_char
*)&revision
.cmd
,
1040 sizeof(revision
.reply
), (u_char
*)&revision
.reply
)) {
1042 * aha_cmd() already started the reset. It's not clear we
1043 * even need to bother here.
1045 for (i
= AHA_RESET_TIMEOUT
; i
; i
--) {
1046 sts
= bus_space_read_1(iot
, ioh
, AHA_STAT_PORT
);
1047 if (sts
== (AHA_STAT_IDLE
| AHA_STAT_INIT
))
1053 printf("aha_init: soft reset failed\n");
1054 #endif /* AHADEBUG */
1058 printf("aha_init: inquire command failed\n");
1059 #endif /* AHADEBUG */
1064 printf("%s: inquire %x, %x, %x, %x\n",
1065 device_xname(sc
->sc_dev
),
1066 revision
.reply
.boardid
, revision
.reply
.spec_opts
,
1067 revision
.reply
.revision_1
, revision
.reply
.revision_2
);
1068 #endif /* AHADEBUG */
1070 switch (revision
.reply
.boardid
) {
1071 case BOARD_1540_16HEAD_BIOS
:
1072 case BOARD_1540_64HEAD_BIOS
:
1074 strcpy(sc
->sc_model
, "1540");
1077 strcpy(sc
->sc_model
, "1540A/1542A/1542B");
1080 strcpy(sc
->sc_model
, "1640");
1083 strcpy(sc
->sc_model
, "1740");
1086 strcpy(sc
->sc_model
, "1542C");
1089 strcpy(sc
->sc_model
, "1542CF");
1092 strcpy(sc
->sc_model
, "1542CP");
1096 p
= sc
->sc_firmware
;
1097 *p
++ = revision
.reply
.revision_1
;
1099 *p
++ = revision
.reply
.revision_2
;
1103 printf("%s: model AHA-%s, firmware %s\n",
1104 device_xname(sc
->sc_dev
),
1105 sc
->sc_model
, sc
->sc_firmware
);
1109 ahaminphys(struct buf
*bp
)
1112 if (bp
->b_bcount
> AHA_MAXXFER
)
1113 bp
->b_bcount
= AHA_MAXXFER
;
1118 * start a scsi operation given the command and the data address. Also needs
1119 * the unit, target and lu.
1123 aha_scsipi_request(struct scsipi_channel
*chan
, scsipi_adapter_req_t req
,
1126 struct scsipi_xfer
*xs
;
1127 struct scsipi_periph
*periph
;
1128 struct aha_softc
*sc
= device_private(chan
->chan_adapter
->adapt_dev
);
1129 bus_dma_tag_t dmat
= sc
->sc_dmat
;
1130 struct aha_ccb
*ccb
;
1131 int error
, seg
, flags
, s
;
1135 case ADAPTER_REQ_RUN_XFER
:
1137 periph
= xs
->xs_periph
;
1138 flags
= xs
->xs_control
;
1140 SC_DEBUG(periph
, SCSIPI_DB2
, ("aha_scsipi_request\n"));
1142 /* Get a CCB to use. */
1143 ccb
= aha_get_ccb(sc
);
1146 * This should never happen as we track the resources
1150 scsipi_printaddr(periph
);
1151 printf("unable to allocate ccb\n");
1152 panic("aha_scsipi_request");
1157 ccb
->timeout
= xs
->timeout
;
1160 * Put all the arguments for the xfer in the ccb
1162 if (flags
& XS_CTL_RESET
) {
1163 ccb
->opcode
= AHA_RESET_CCB
;
1164 ccb
->scsi_cmd_length
= 0;
1166 /* can't use S/G if zero length */
1167 if (xs
->cmdlen
> sizeof(ccb
->scsi_cmd
)) {
1168 printf("%s: cmdlen %d too large for CCB\n",
1169 device_xname(sc
->sc_dev
), xs
->cmdlen
);
1170 xs
->error
= XS_DRIVER_STUFFUP
;
1173 ccb
->opcode
= (xs
->datalen
? AHA_INIT_SCAT_GATH_CCB
1174 : AHA_INITIATOR_CCB
);
1175 memcpy(&ccb
->scsi_cmd
, xs
->cmd
,
1176 ccb
->scsi_cmd_length
= xs
->cmdlen
);
1181 * Map the DMA transfer.
1184 if (flags
& XS_CTL_DATA_UIO
) {
1185 error
= bus_dmamap_load_uio(dmat
,
1186 ccb
->dmamap_xfer
, (struct uio
*)xs
->data
,
1187 ((flags
& XS_CTL_NOSLEEP
) ? BUS_DMA_NOWAIT
:
1188 BUS_DMA_WAITOK
) | BUS_DMA_STREAMING
|
1189 ((flags
& XS_CTL_DATA_IN
) ? BUS_DMA_READ
:
1194 error
= bus_dmamap_load(dmat
,
1195 ccb
->dmamap_xfer
, xs
->data
, xs
->datalen
,
1197 ((flags
& XS_CTL_NOSLEEP
) ? BUS_DMA_NOWAIT
:
1198 BUS_DMA_WAITOK
) | BUS_DMA_STREAMING
|
1199 ((flags
& XS_CTL_DATA_IN
) ? BUS_DMA_READ
:
1209 xs
->error
= XS_RESOURCE_SHORTAGE
;
1213 xs
->error
= XS_DRIVER_STUFFUP
;
1214 if (error
== EFBIG
) {
1215 printf("%s: aha_scsi_cmd, more than %d"
1217 device_xname(sc
->sc_dev
), AHA_NSEG
);
1219 aprint_error_dev(sc
->sc_dev
,
1220 "error %d loading DMA map\n",
1224 aha_free_ccb(sc
, ccb
);
1229 bus_dmamap_sync(dmat
, ccb
->dmamap_xfer
, 0,
1230 ccb
->dmamap_xfer
->dm_mapsize
,
1231 (flags
& XS_CTL_DATA_IN
) ? BUS_DMASYNC_PREREAD
:
1232 BUS_DMASYNC_PREWRITE
);
1235 * Load the hardware scatter/gather map with the
1236 * contents of the DMA map.
1238 for (seg
= 0; seg
< ccb
->dmamap_xfer
->dm_nsegs
; seg
++) {
1239 ltophys(ccb
->dmamap_xfer
->dm_segs
[seg
].ds_addr
,
1240 ccb
->scat_gath
[seg
].seg_addr
);
1241 ltophys(ccb
->dmamap_xfer
->dm_segs
[seg
].ds_len
,
1242 ccb
->scat_gath
[seg
].seg_len
);
1245 ltophys(sc
->sc_dmamap_control
->dm_segs
[0].ds_addr
+
1247 offsetof(struct aha_ccb
, scat_gath
),
1249 ltophys(ccb
->dmamap_xfer
->dm_nsegs
*
1250 sizeof(struct aha_scat_gath
), ccb
->data_length
);
1253 * No data xfer, use non S/G values.
1255 ltophys(0, ccb
->data_addr
);
1256 ltophys(0, ccb
->data_length
);
1261 ccb
->target
= periph
->periph_target
;
1262 ccb
->lun
= periph
->periph_lun
;
1263 ccb
->req_sense_length
= sizeof(ccb
->scsi_sense
);
1264 ccb
->host_stat
= 0x00;
1265 ccb
->target_stat
= 0x00;
1267 ltophys(0, ccb
->link_addr
);
1269 bus_dmamap_sync(sc
->sc_dmat
, sc
->sc_dmamap_control
,
1270 AHA_CCB_OFF(ccb
), sizeof(struct aha_ccb
),
1271 BUS_DMASYNC_PREREAD
|BUS_DMASYNC_PREWRITE
);
1274 aha_queue_ccb(sc
, ccb
);
1277 SC_DEBUG(periph
, SCSIPI_DB3
, ("cmd_sent\n"));
1278 if ((flags
& XS_CTL_POLL
) == 0)
1281 /* Not allowed to use interrupts, poll for completion. */
1282 if (aha_poll(sc
, xs
, ccb
->timeout
)) {
1284 if (aha_poll(sc
, xs
, ccb
->timeout
))
1289 case ADAPTER_REQ_GROW_RESOURCES
:
1290 /* XXX Not supported. */
1293 case ADAPTER_REQ_SET_XFER_MODE
:
1295 * Can't really do this on the Adaptec; it has
1296 * its own config mechanism, but we do know how
1297 * to query what the firmware negotiated.
1305 * Poll a particular unit, looking for a particular xs
1308 aha_poll(struct aha_softc
*sc
, struct scsipi_xfer
*xs
, int count
)
1310 bus_space_tag_t iot
= sc
->sc_iot
;
1311 bus_space_handle_t ioh
= sc
->sc_ioh
;
1313 /* timeouts are in msec, so we loop in 1000 usec cycles */
1316 * If we had interrupts enabled, would we
1317 * have got an interrupt?
1319 if (bus_space_read_1(iot
, ioh
, AHA_INTR_PORT
) & AHA_INTR_ANYINTR
)
1321 if (xs
->xs_status
& XS_STS_DONE
)
1323 delay(1000); /* only happens in boot so ok */
1330 aha_timeout(void *arg
)
1332 struct aha_ccb
*ccb
= arg
;
1333 struct scsipi_xfer
*xs
= ccb
->xs
;
1334 struct scsipi_periph
*periph
= xs
->xs_periph
;
1335 struct aha_softc
*sc
=
1336 device_private(periph
->periph_channel
->chan_adapter
->adapt_dev
);
1339 scsipi_printaddr(periph
);
1340 printf("timed out");
1346 * If The ccb's mbx is not free, then the board has gone south?
1348 aha_collect_mbo(sc
);
1349 if (ccb
->flags
& CCB_SENDING
) {
1350 aprint_error_dev(sc
->sc_dev
, "not taking commands!\n");
1356 * If it has been through before, then
1357 * a previous abort has failed, don't
1360 if (ccb
->flags
& CCB_ABORT
) {
1361 /* abort timed out */
1363 /* XXX Must reset! */
1365 /* abort the operation that has timed out */
1367 ccb
->xs
->error
= XS_TIMEOUT
;
1368 ccb
->timeout
= AHA_ABORT_TIMEOUT
;
1369 ccb
->flags
|= CCB_ABORT
;
1370 aha_queue_ccb(sc
, ccb
);