1 /* $NetBSD: spc.c,v 1.6 2008/03/31 15:20:47 tsutsui Exp $ */
4 * Copyright (c) 2003 Izumi Tsutsui. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
31 __KERNEL_RCSID(0, "$NetBSD: spc.c,v 1.6 2008/03/31 15:20:47 tsutsui Exp $");
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/device.h>
37 #include <machine/autoconf.h>
38 #include <machine/bus.h>
39 #include <machine/cpu.h>
40 #include <machine/intr.h>
42 #include <hp300/dev/dioreg.h>
43 #include <hp300/dev/diovar.h>
44 #include <hp300/dev/diodevs.h>
46 #include <dev/scsipi/scsi_all.h>
47 #include <dev/scsipi/scsipi_all.h>
48 #include <dev/scsipi/scsi_message.h>
49 #include <dev/scsipi/scsiconf.h>
51 #include <dev/ic/mb89352reg.h>
52 #include <dev/ic/mb89352var.h>
54 #include <hp300/dev/hp98265reg.h>
55 #include <hp300/dev/dmareg.h>
56 #include <hp300/dev/dmavar.h>
58 static int spc_dio_match(device_t
, cfdata_t
, void *);
59 static void spc_dio_attach(device_t
, device_t
, void *);
60 static void spc_dio_dmastart(struct spc_softc
*, void *, size_t, int);
61 static void spc_dio_dmadone(struct spc_softc
*);
62 static void spc_dio_dmago(void *);
63 static void spc_dio_dmastop(void *);
65 struct spc_dio_softc
{
66 struct spc_softc sc_spc
; /* MI spc softc */
68 /* DIO specific goo. */
69 struct bus_space_tag sc_tag
; /* bus space tag with oddbyte func */
70 bus_space_handle_t sc_iohsc
; /* bus space handle for HPSCSI */
71 struct dmaqueue sc_dq
; /* DMA job queue */
72 u_int sc_dflags
; /* DMA flags */
73 #define SCSI_DMA32 0x01 /* 32-bit DMA should be used */
74 #define SCSI_HAVEDMA 0x02 /* controller has DMA channel */
75 #define SCSI_DATAIN 0x04 /* DMA direction */
78 CFATTACH_DECL_NEW(spc
, sizeof(struct spc_dio_softc
),
79 spc_dio_match
, spc_dio_attach
, NULL
, NULL
);
82 spc_dio_match(device_t parent
, cfdata_t cf
, void *aux
)
84 struct dio_attach_args
*da
= aux
;
87 case DIO_DEVICE_ID_SCSI0
:
88 case DIO_DEVICE_ID_SCSI1
:
89 case DIO_DEVICE_ID_SCSI2
:
90 case DIO_DEVICE_ID_SCSI3
:
98 spc_dio_attach(device_t parent
, device_t self
, void *aux
)
100 struct spc_dio_softc
*dsc
= device_private(self
);
101 struct spc_softc
*sc
= &dsc
->sc_spc
;
102 struct dio_attach_args
*da
= aux
;
103 bus_space_tag_t iot
= &dsc
->sc_tag
;
104 bus_space_handle_t iohsc
, iohspc
;
108 memcpy(iot
, da
->da_bst
, sizeof(struct bus_space_tag
));
109 dio_set_bus_space_oddbyte(iot
);
111 if (bus_space_map(iot
, da
->da_addr
, da
->da_size
, 0, &iohsc
)) {
112 aprint_error(": can't map SCSI registers\n");
116 if (bus_space_subregion(iot
, iohsc
, SPC_OFFSET
, SPC_SIZE
, &iohspc
)) {
117 aprint_error(": can't map SPC registers\n");
121 aprint_normal(": 98265A SCSI");
123 bus_space_write_1(iot
, iohsc
, HPSCSI_ID
, 0xff);
125 id
= bus_space_read_1(iot
, iohsc
, HPSCSI_ID
);
126 if ((id
& ID_WORD_DMA
) == 0) {
127 aprint_normal(", 32-bit DMA");
128 dsc
->sc_dflags
|= SCSI_DMA32
;
131 aprint_normal(", SCSI ID %d\n", id
);
135 sc
->sc_initiator
= id
;
137 sc
->sc_dma_start
= spc_dio_dmastart
;
138 sc
->sc_dma_done
= spc_dio_dmadone
;
140 dsc
->sc_iohsc
= iohsc
;
141 dsc
->sc_dq
.dq_softc
= dsc
;
142 dsc
->sc_dq
.dq_start
= spc_dio_dmago
;
143 dsc
->sc_dq
.dq_done
= spc_dio_dmastop
;
145 bus_space_write_1(iot
, iohsc
, HPSCSI_CSR
, 0x00);
146 bus_space_write_1(iot
, iohsc
, HPSCSI_HCONF
, 0x00);
148 dio_intr_establish(spc_intr
, (void *)sc
, da
->da_ipl
, IPL_BIO
);
152 /* Enable SPC interrupts. */
153 bus_space_write_1(iot
, iohsc
, HPSCSI_CSR
, CSR_IE
);
157 spc_dio_dmastart(struct spc_softc
*sc
, void *addr
, size_t size
, int datain
)
159 struct spc_dio_softc
*dsc
= (struct spc_dio_softc
*)sc
;
161 dsc
->sc_dq
.dq_chan
= DMA0
| DMA1
;
162 dsc
->sc_dflags
|= SCSI_HAVEDMA
;
164 dsc
->sc_dflags
|= SCSI_DATAIN
;
166 dsc
->sc_dflags
&= ~SCSI_DATAIN
;
168 if (dmareq(&dsc
->sc_dq
) != 0)
169 /* DMA channel is available, so start DMA immediately */
171 /* else dma start function will be called later from dmafree(). */
175 spc_dio_dmago(void *arg
)
177 struct spc_dio_softc
*dsc
= arg
;
178 struct spc_softc
*sc
= &dsc
->sc_spc
;
180 bus_space_handle_t iohsc
, iohspc
;
187 iohsc
= dsc
->sc_iohsc
;
189 bus_space_write_1(iot
, iohsc
, HPSCSI_HCONF
, 0);
192 dmaflags
= DMAGO_NOINT
;
193 chan
= dsc
->sc_dq
.dq_chan
;
194 if ((dsc
->sc_dflags
& SCSI_DATAIN
) != 0) {
196 dmaflags
|= DMAGO_READ
;
198 if ((dsc
->sc_dflags
& SCSI_DMA32
) != 0 &&
199 ((u_int
)sc
->sc_dp
& 3) == 0 &&
200 (sc
->sc_dleft
& 3) == 0) {
202 dmaflags
|= DMAGO_LWORD
;
204 dmaflags
|= DMAGO_WORD
;
206 dmago(chan
, sc
->sc_dp
, sc
->sc_dleft
, dmaflags
);
208 bus_space_write_1(iot
, iohsc
, HPSCSI_CSR
, cmd
);
209 cmd
|= (chan
== 0) ? CSR_DE0
: CSR_DE1
;
210 bus_space_write_1(iot
, iohsc
, HPSCSI_CSR
, cmd
);
215 if ((len
& (DEV_BSIZE
- 1)) != 0) /* XXX ??? */ {
218 if ((dsc
->sc_dflags
& SCSI_DATAIN
) != 0)
219 len
+= 2; /* XXX ??? */
223 bus_space_write_1(iot
, iohspc
, TCH
, len
>> 16);
224 bus_space_write_1(iot
, iohspc
, TCM
, len
>> 8);
225 bus_space_write_1(iot
, iohspc
, TCL
, len
);
226 bus_space_write_1(iot
, iohspc
, PCTL
, sc
->sc_phase
| PCTL_BFINT_ENAB
);
227 bus_space_write_1(iot
, iohspc
, SCMD
, cmd
);
229 sc
->sc_flags
|= SPC_DOINGDMA
;
233 spc_dio_dmadone(struct spc_softc
*sc
)
235 struct spc_dio_softc
*dsc
= (struct spc_dio_softc
*)sc
;
237 bus_space_handle_t ioh
, iohsc
;
243 iohsc
= dsc
->sc_iohsc
;
245 /* wait DMA complete */
246 if ((bus_space_read_1(iot
, ioh
, SSTS
) & SSTS_BUSY
) != 0) {
247 int timeout
= 1000; /* XXX how long? */
248 while ((bus_space_read_1(iot
, ioh
, SSTS
) & SSTS_BUSY
) != 0) {
250 printf("%s: DMA complete timeout\n",
251 device_xname(sc
->sc_dev
));
256 if ((dsc
->sc_dflags
& SCSI_HAVEDMA
) != 0) {
257 dmafree(&dsc
->sc_dq
);
258 dsc
->sc_dflags
&= ~SCSI_HAVEDMA
;
261 cmd
= bus_space_read_1(iot
, iohsc
, HPSCSI_CSR
);
262 cmd
&= ~(CSR_DE1
|CSR_DE0
);
263 bus_space_write_1(iot
, iohsc
, HPSCSI_CSR
, cmd
);
265 resid
= bus_space_read_1(iot
, ioh
, TCH
) << 16 |
266 bus_space_read_1(iot
, ioh
, TCM
) << 8 |
267 bus_space_read_1(iot
, ioh
, TCL
);
268 trans
= sc
->sc_dleft
- resid
;
270 sc
->sc_dleft
-= trans
;
272 sc
->sc_flags
&= ~SPC_DOINGDMA
;
276 spc_dio_dmastop(void *arg
)
278 struct spc_dio_softc
*dsc
= arg
;
279 struct spc_softc
*sc
= &dsc
->sc_spc
;
282 /* XXX When is this function called? */
283 cmd
= bus_space_read_1(sc
->sc_iot
, dsc
->sc_iohsc
, HPSCSI_CSR
);
284 cmd
&= ~(CSR_DE1
|CSR_DE0
);
285 bus_space_write_1(sc
->sc_iot
, dsc
->sc_iohsc
, HPSCSI_CSR
, cmd
);
287 dsc
->sc_dflags
&= ~SCSI_HAVEDMA
;
288 sc
->sc_flags
&= ~SPC_DOINGDMA
;