1 /* $NetBSD: si.c,v 1.24 2008/06/17 17:31:51 tsutsui Exp $ */
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Adam Glass, David Jones, Gordon W. Ross, and Jens A. Nilsson.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * This file contains the machine-dependent parts of the Sony CXD1180
34 * controller. The machine-independent parts are in ncr5380sbc.c.
35 * Written by Izumi Tsutsui.
37 * This code is based on arch/vax/vsa/ncr.c and sun3/dev/si.c
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: si.c,v 1.24 2008/06/17 17:31:51 tsutsui Exp $");
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
48 #include <machine/cpu.h>
49 #include <m68k/cacheops.h>
51 #include <dev/scsipi/scsipi_all.h>
52 #include <dev/scsipi/scsiconf.h>
54 #include <dev/ic/ncr5380reg.h>
55 #include <dev/ic/ncr5380var.h>
57 #include <news68k/dev/hbvar.h>
58 #include <news68k/dev/dmac_0266.h>
62 #define MIN_DMA_LEN 128
63 #define DMAC_BASE 0xe0e80000 /* XXX */
67 struct ncr5380_softc ncr_sc
;
69 struct dma_regs
*sc_regs
;
73 static int si_match(device_t
, cfdata_t
, void *);
74 static void si_attach(device_t
, device_t
, void *);
77 static void si_dma_alloc(struct ncr5380_softc
*);
78 static void si_dma_free(struct ncr5380_softc
*);
79 static void si_dma_start(struct ncr5380_softc
*);
80 static void si_dma_poll(struct ncr5380_softc
*);
81 static void si_dma_eop(struct ncr5380_softc
*);
82 static void si_dma_stop(struct ncr5380_softc
*);
84 CFATTACH_DECL_NEW(si
, sizeof(struct si_softc
),
85 si_match
, si_attach
, NULL
, NULL
);
88 * Options for disconnect/reselect, DMA, and interrupts.
89 * By default, allow disconnect/reselect on targets 4-6.
90 * Those are normally tapes that really need it enabled.
91 * The options are taken from the config file.
93 #define SI_NO_DISCONNECT 0x000ff
94 #define SI_NO_PARITY_CHK 0x0ff00
95 #define SI_FORCE_POLLING 0x10000
96 #define SI_DISABLE_DMA 0x20000
98 int si_options
= 0x00;
102 si_match(device_t parent
, cfdata_t cf
, void *aux
)
104 struct hb_attach_args
*ha
= aux
;
107 if (strcmp(ha
->ha_name
, "si"))
110 addr
= IIOV(ha
->ha_address
);
112 if (badaddr((void *)addr
, 1))
115 ha
->ha_size
= SI_REGSIZE
;
121 * Card attach function
125 si_attach(device_t parent
, device_t self
, void *aux
)
127 struct si_softc
*sc
= device_private(self
);
128 struct ncr5380_softc
*ncr_sc
= &sc
->ncr_sc
;
129 struct cfdata
*cf
= device_cfdata(self
);
130 struct hb_attach_args
*ha
= aux
;
132 ncr_sc
->sc_dev
= self
;
133 ncr_sc
->sc_regt
= ha
->ha_bust
;
134 if (bus_space_map(ncr_sc
->sc_regt
, (bus_addr_t
)ha
->ha_address
,
135 ha
->ha_size
, 0, &ncr_sc
->sc_regh
) != 0) {
136 aprint_error(": can't map device space\n");
140 /* Get options from config flags if specified. */
142 sc
->sc_options
= cf
->cf_flags
;
144 sc
->sc_options
= si_options
;
146 if (sc
->sc_options
!= 0)
147 aprint_normal(": options=0x%x", sc
->sc_options
);
150 ncr_sc
->sc_no_disconnect
= (sc
->sc_options
& SI_NO_DISCONNECT
);
151 ncr_sc
->sc_parity_disable
= (sc
->sc_options
& SI_NO_PARITY_CHK
) >> 8;
152 if (sc
->sc_options
& SI_FORCE_POLLING
)
153 ncr_sc
->sc_flags
|= NCR5380_FORCE_POLLING
;
155 ncr_sc
->sc_min_dma_len
= MIN_DMA_LEN
;
156 ncr_sc
->sc_dma_alloc
= si_dma_alloc
;
157 ncr_sc
->sc_dma_free
= si_dma_free
;
158 ncr_sc
->sc_dma_poll
= si_dma_poll
;
159 ncr_sc
->sc_dma_start
= si_dma_start
;
160 ncr_sc
->sc_dma_eop
= si_dma_eop
;
161 ncr_sc
->sc_dma_stop
= si_dma_stop
;
163 if (sc
->sc_options
& SI_DISABLE_DMA
)
164 /* Override this function pointer. */
165 ncr_sc
->sc_dma_alloc
= NULL
;
176 ncr_sc
->sc_rev
= NCR_VARIANT_CXD1180
;
178 ncr_sc
->sc_pio_in
= ncr5380_pio_in
;
179 ncr_sc
->sc_pio_out
= ncr5380_pio_out
;
181 ncr_sc
->sc_adapter
.adapt_minphys
= minphys
;
182 ncr_sc
->sc_channel
.chan_id
= 7;
184 /* soft reset DMAC */
185 sc
->sc_regs
= (void *)IIOV(DMAC_BASE
);
186 sc
->sc_regs
->ctl
= DC_CTL_RST
;
188 ncr5380_attach(ncr_sc
);
196 if (unit
>= si_cd
.cd_ndevs
)
199 sc
= device_lookup_private(&si_cd
, unit
); /* XXX */
200 (void)ncr5380_intr(&sc
->ncr_sc
);
206 * DMA routines for news1700 machines
209 si_dma_alloc(struct ncr5380_softc
*ncr_sc
)
211 struct sci_req
*sr
= ncr_sc
->sc_current
;
214 if (sr
->sr_dma_hand
!= NULL
)
215 panic("%s: DMA already in use", __func__
);
219 * On news68k, SCSI has its own DMAC so no need allocate it.
220 * Just mark that DMA is available.
222 sr
->sr_dma_hand
= (void *)-1;
226 si_dma_free(struct ncr5380_softc
*ncr_sc
)
228 struct sci_req
*sr
= ncr_sc
->sc_current
;
231 if (sr
->sr_dma_hand
== NULL
)
232 panic("%s: DMA not in use", __func__
);
235 sr
->sr_dma_hand
= NULL
;
240 si_dma_start(struct ncr5380_softc
*ncr_sc
)
242 struct si_softc
*sc
= (struct si_softc
*)ncr_sc
;
243 struct dma_regs
*dmac
= sc
->sc_regs
;
244 struct sci_req
*sr
= ncr_sc
->sc_current
;
245 u_int addr
, offset
, rest
;
250 dmac
->ctl
= DC_CTL_RST
;
253 addr
= (u_int
)ncr_sc
->sc_dataptr
;
254 offset
= addr
& DMAC_SEG_OFFSET
;
255 len
= sc
->sc_xlen
= ncr_sc
->sc_datalen
;
257 /* set DMA transfer length */
258 dmac
->tcnt
= (uint32_t)len
;
260 /* set offset of first segment */
261 dmac
->offset
= offset
;
263 /* set first DMA segment address */
265 dmac
->mapent
= kvtop((void *)addr
) >> DMAC_SEG_SHIFT
;
266 rest
= DMAC_SEG_SIZE
- offset
;
270 /* set all the rest segments */
271 for (i
= 1; len
> 0; i
++) {
273 dmac
->mapent
= kvtop((void *)addr
) >> DMAC_SEG_SHIFT
;
274 len
-= DMAC_SEG_SIZE
;
275 addr
+= DMAC_SEG_SIZE
;
280 if (sr
->sr_xs
->xs_control
& XS_CTL_DATA_OUT
) {
281 NCR5380_WRITE(ncr_sc
, sci_tcmd
, PHASE_DATA_OUT
);
282 NCR5380_WRITE(ncr_sc
, sci_icmd
, SCI_ICMD_DATA
);
283 NCR5380_WRITE(ncr_sc
, sci_mode
, NCR5380_READ(ncr_sc
, sci_mode
)
284 | SCI_MODE_DMA
| SCI_MODE_DMA_IE
);
290 NCR5380_WRITE(ncr_sc
, sci_dma_send
, 0);
291 dmac
->ctl
= DC_CTL_ENB
;
293 NCR5380_WRITE(ncr_sc
, sci_tcmd
, PHASE_DATA_IN
);
294 NCR5380_WRITE(ncr_sc
, sci_icmd
, 0);
295 NCR5380_WRITE(ncr_sc
, sci_mode
, NCR5380_READ(ncr_sc
, sci_mode
)
296 | SCI_MODE_DMA
| SCI_MODE_DMA_IE
);
299 dmac
->ctl
= DC_CTL_MOD
;
302 NCR5380_WRITE(ncr_sc
, sci_irecv
, 0);
303 dmac
->ctl
= DC_CTL_MOD
| DC_CTL_ENB
;
305 ncr_sc
->sc_state
|= NCR_DOINGDMA
;
312 si_dma_poll(struct ncr5380_softc
*ncr_sc
)
314 struct si_softc
*sc
= (struct si_softc
*)ncr_sc
;
315 struct dma_regs
*dmac
= sc
->sc_regs
;
318 #define POLL_TIMEOUT 100000
320 /* check DMAC interrupt status */
321 for (i
= 0; i
< POLL_TIMEOUT
; i
++) {
322 if ((dmac
->stat
& DC_ST_INT
) != 0)
327 if (i
== POLL_TIMEOUT
)
328 printf("%s: DMA polling timeout\n",
329 device_xname(ncr_sc
->sc_dev
));
333 * news68k (probably) does not use the EOP signal.
336 si_dma_eop(struct ncr5380_softc
*ncr_sc
)
339 printf("si_dma_eop\n");
343 si_dma_stop(struct ncr5380_softc
*ncr_sc
)
345 struct si_softc
*sc
= (struct si_softc
*)ncr_sc
;
346 struct dma_regs
*dmac
= sc
->sc_regs
;
347 struct sci_req
*sr
= ncr_sc
->sc_current
;
350 /* check DMAC interrupt status */
351 if ((dmac
->stat
& DC_ST_INT
) == 0) {
353 printf("%s: no DMA interrupt\n", __func__
);
358 if ((ncr_sc
->sc_state
& NCR_DOINGDMA
) == 0) {
360 printf("%s: dma not running\n", __func__
);
364 ncr_sc
->sc_state
&= ~NCR_DOINGDMA
;
368 dmac
->ctl
&= ~DC_CTL_ENB
;
370 /* OK, have either phase mis-match or end of DMA. */
371 /* Set an impossible phase to prevent data movement? */
372 NCR5380_WRITE(ncr_sc
, sci_tcmd
, PHASE_INVALID
);
374 /* Note that timeout may have set the error flag. */
375 if (ncr_sc
->sc_state
& NCR_ABORTING
)
380 printf("%s: datalen = 0x%x, resid = 0x%x\n",
381 __func__
, sc
->sc_xlen
, resid
);
384 ntrans
= sc
->sc_xlen
- resid
;
386 ncr_sc
->sc_dataptr
+= ntrans
;
387 ncr_sc
->sc_datalen
-= ntrans
;
389 if (sr
->sr_xs
->xs_control
& XS_CTL_DATA_IN
) {
390 /* flush data cache */
396 dmac
->ctl
= DC_CTL_RST
;
399 NCR5380_WRITE(ncr_sc
, sci_mode
, NCR5380_READ(ncr_sc
, sci_mode
) &
400 ~(SCI_MODE_DMA
| SCI_MODE_DMA_IE
));
401 NCR5380_WRITE(ncr_sc
, sci_icmd
, 0);