1 /* $NetBSD: tcds.c,v 1.24 2009/03/18 16:00:20 cegger Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * 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 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
35 * All rights reserved.
37 * Author: Keith Bostic, Chris G. Demetriou
39 * Permission to use, copy, modify and distribute this software and
40 * its documentation is hereby granted, provided that both the copyright
41 * notice and this permission notice appear in all copies of the
42 * software, derivative works or modified versions, and any portions
43 * thereof, and that both notices appear in supporting documentation.
45 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
46 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
47 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
49 * Carnegie Mellon requests users of this software to return to
51 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
52 * School of Computer Science
53 * Carnegie Mellon University
54 * Pittsburgh PA 15213-3890
56 * any improvements or extensions that they make and grant Carnegie the
57 * rights to redistribute these changes.
60 #include <sys/cdefs.h>
61 __KERNEL_RCSID(0, "$NetBSD: tcds.c,v 1.24 2009/03/18 16:00:20 cegger Exp $");
63 #include <sys/param.h>
64 #include <sys/kernel.h>
65 #include <sys/systm.h>
66 #include <sys/device.h>
67 #include <sys/malloc.h>
70 #include <machine/rpb.h>
71 #endif /* __alpha__ */
73 #include <dev/scsipi/scsi_all.h>
74 #include <dev/scsipi/scsipi_all.h>
75 #include <dev/scsipi/scsiconf.h>
77 #include <dev/ic/ncr53c9xvar.h>
81 #include <dev/tc/tcvar.h>
82 #include <dev/tc/tcdsreg.h>
83 #include <dev/tc/tcdsvar.h>
89 bus_space_tag_t sc_bst
;
90 bus_space_handle_t sc_bsh
;
91 bus_dma_tag_t sc_dmat
;
94 struct tcds_slotconfig sc_slots
[2];
98 #define TCDSF_BASEBOARD 0x01 /* baseboard on DEC 3000 */
99 #define TCDSF_FASTSCSI 0x02 /* supports Fast SCSI */
101 /* Definition of the driver for autoconfig. */
102 static int tcdsmatch(device_t
, cfdata_t
, void *);
103 static void tcdsattach(device_t
, device_t
, void *);
104 static int tcdsprint(void *, const char *);
106 CFATTACH_DECL_NEW(tcds
, sizeof(struct tcds_softc
),
107 tcdsmatch
, tcdsattach
, NULL
, NULL
);
109 /*static*/ int tcds_intr(void *);
110 /*static*/ int tcds_intrnull(void *);
112 static const struct tcds_device
{
117 { "PMAZ-DS ", TCDSF_BASEBOARD
},
118 { "PMAZ-FS ", TCDSF_BASEBOARD
|TCDSF_FASTSCSI
},
119 #endif /* __alpha__ */
121 { "PMAZC-AA", TCDSF_FASTSCSI
},
125 static void tcds_params(struct tcds_softc
*, int, int *, int *);
127 static const struct tcds_device
*
128 tcds_lookup(const char *modname
)
130 const struct tcds_device
*td
;
132 for (td
= tcds_devices
; td
->td_name
!= NULL
; td
++)
133 if (strncmp(td
->td_name
, modname
, TC_ROM_LLEN
) == 0)
140 tcdsmatch(device_t parent
, cfdata_t cfdata
, void *aux
)
142 struct tc_attach_args
*ta
= aux
;
144 return (tcds_lookup(ta
->ta_modname
) != NULL
);
148 tcdsattach(device_t parent
, device_t self
, void *aux
)
150 struct tcds_softc
*sc
= device_private(self
);
151 struct tc_attach_args
*ta
= aux
;
152 struct tcdsdev_attach_args tcdsdev
;
153 struct tcds_slotconfig
*slotc
;
154 const struct tcds_device
*td
;
155 bus_space_handle_t sbsh
[2];
157 const struct evcnt
*pevcnt
;
158 int locs
[TCDSCF_NLOCS
];
162 td
= tcds_lookup(ta
->ta_modname
);
164 panic("\ntcdsattach: impossible");
166 printf(": TurboChannel Dual SCSI");
167 if (td
->td_flags
& TCDSF_BASEBOARD
)
168 printf(" (baseboard)");
171 sc
->sc_flags
= td
->td_flags
;
173 sc
->sc_bst
= ta
->ta_memt
;
174 sc
->sc_dmat
= ta
->ta_dmat
;
179 if (bus_space_map(sc
->sc_bst
, ta
->ta_addr
,
180 (TCDS_SCSI1_OFFSET
+ 0x100), 0, &sc
->sc_bsh
)) {
181 aprint_error_dev(self
, "unable to map device\n");
186 * Now, slice off two subregions for the individual NCR SCSI chips.
188 if (bus_space_subregion(sc
->sc_bst
, sc
->sc_bsh
, TCDS_SCSI0_OFFSET
,
190 bus_space_subregion(sc
->sc_bst
, sc
->sc_bsh
, TCDS_SCSI1_OFFSET
,
192 aprint_error_dev(self
, "unable to subregion SCSI chip space\n");
196 sc
->sc_cookie
= ta
->ta_cookie
;
198 pevcnt
= tc_intr_evcnt(parent
, sc
->sc_cookie
);
199 tc_intr_establish(parent
, sc
->sc_cookie
, TC_IPL_BIO
, tcds_intr
, sc
);
203 * IMER apparently has some random (or, not so random, but still
204 * not useful) bits set in it when the system boots. Clear it.
206 bus_space_write_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_IMER
, 0);
208 /* XXX Initial contents of CIR? */
211 * Remember if GPI2 is set in the CIR; we'll need it later.
213 gpi2
= (bus_space_read_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
) &
214 TCDS_CIR_GPI_2
) != 0;
217 * Set up the per-slot definitions for later use.
220 /* fill in common information first */
221 for (i
= 0; i
< 2; i
++) {
224 slotc
= &sc
->sc_slots
[i
];
225 memset(slotc
, 0, sizeof *slotc
); /* clear everything */
228 snprintf(cp
, sizeof(slotc
->sc_name
), "chip %d", i
);
229 evcnt_attach_dynamic(&slotc
->sc_evcnt
, EVCNT_TYPE_INTR
,
230 pevcnt
, device_xname(self
), cp
);
233 slotc
->sc_bst
= sc
->sc_bst
;
234 slotc
->sc_bsh
= sc
->sc_bsh
;
235 slotc
->sc_intrhand
= tcds_intrnull
;
236 slotc
->sc_intrarg
= (void *)(long)i
;
239 /* information for slot 0 */
240 slotc
= &sc
->sc_slots
[0];
241 slotc
->sc_resetbits
= TCDS_CIR_SCSI0_RESET
;
242 slotc
->sc_intrmaskbits
=
243 TCDS_IMER_SCSI0_MASK
| TCDS_IMER_SCSI0_ENB
;
244 slotc
->sc_intrbits
= TCDS_CIR_SCSI0_INT
;
245 slotc
->sc_dmabits
= TCDS_CIR_SCSI0_DMAENA
;
246 slotc
->sc_errorbits
= 0; /* XXX */
247 slotc
->sc_sda
= TCDS_SCSI0_DMA_ADDR
;
248 slotc
->sc_dic
= TCDS_SCSI0_DMA_INTR
;
249 slotc
->sc_dud0
= TCDS_SCSI0_DMA_DUD0
;
250 slotc
->sc_dud1
= TCDS_SCSI0_DMA_DUD1
;
252 /* information for slot 1 */
253 slotc
= &sc
->sc_slots
[1];
254 slotc
->sc_resetbits
= TCDS_CIR_SCSI1_RESET
;
255 slotc
->sc_intrmaskbits
=
256 TCDS_IMER_SCSI1_MASK
| TCDS_IMER_SCSI1_ENB
;
257 slotc
->sc_intrbits
= TCDS_CIR_SCSI1_INT
;
258 slotc
->sc_dmabits
= TCDS_CIR_SCSI1_DMAENA
;
259 slotc
->sc_errorbits
= 0; /* XXX */
260 slotc
->sc_sda
= TCDS_SCSI1_DMA_ADDR
;
261 slotc
->sc_dic
= TCDS_SCSI1_DMA_INTR
;
262 slotc
->sc_dud0
= TCDS_SCSI1_DMA_DUD0
;
263 slotc
->sc_dud1
= TCDS_SCSI1_DMA_DUD1
;
265 /* find the hardware attached to the TCDS ASIC */
266 for (i
= 0; i
< 2; i
++) {
267 tcds_params(sc
, i
, &tcdsdev
.tcdsda_id
,
268 &tcdsdev
.tcdsda_fast
);
270 tcdsdev
.tcdsda_bst
= sc
->sc_bst
;
271 tcdsdev
.tcdsda_bsh
= sbsh
[i
];
272 tcdsdev
.tcdsda_dmat
= sc
->sc_dmat
;
273 tcdsdev
.tcdsda_chip
= i
;
274 tcdsdev
.tcdsda_sc
= &sc
->sc_slots
[i
];
276 * Determine the chip frequency. TCDSF_FASTSCSI will be set
277 * for TC option cards. For baseboard chips, GPI2 is set, for a
278 * 25MHz clock, else a 40MHz clock.
280 if ((sc
->sc_flags
& TCDSF_BASEBOARD
&& gpi2
== 0) ||
281 sc
->sc_flags
& TCDSF_FASTSCSI
) {
282 tcdsdev
.tcdsda_freq
= 40000000;
283 tcdsdev
.tcdsda_period
= tcdsdev
.tcdsda_fast
? 4 : 8;
285 tcdsdev
.tcdsda_freq
= 25000000;
286 tcdsdev
.tcdsda_period
= 5;
288 if (sc
->sc_flags
& TCDSF_BASEBOARD
)
289 tcdsdev
.tcdsda_variant
= NCR_VARIANT_NCR53C94
;
291 tcdsdev
.tcdsda_variant
= NCR_VARIANT_NCR53C96
;
293 tcds_scsi_reset(tcdsdev
.tcdsda_sc
);
295 locs
[TCDSCF_CHIP
] = i
;
297 config_found_sm_loc(self
, "tcds", locs
, &tcdsdev
,
298 tcdsprint
, config_stdsubmatch
);
301 * The second SCSI chip isn't present on the baseboard TCDS
302 * on the DEC Alpha 3000/300 series.
304 if (sc
->sc_flags
& TCDSF_BASEBOARD
&&
305 cputype
== ST_DEC_3000_300
)
307 #endif /* __alpha__ */
312 tcdsprint(void *aux
, const char *pnp
)
314 struct tcdsdev_attach_args
*tcdsdev
= aux
;
316 /* Only ASCs can attach to TCDSs; easy. */
318 aprint_normal("asc at %s", pnp
);
320 aprint_normal(" chip %d", tcdsdev
->tcdsda_chip
);
326 tcds_intr_establish(device_t tcds
, int slot
, int (*func
)(void *),
329 struct tcds_softc
*sc
= device_private(tcds
);
331 if (sc
->sc_slots
[slot
].sc_intrhand
!= tcds_intrnull
)
332 panic("tcds_intr_establish: chip %d twice", slot
);
334 sc
->sc_slots
[slot
].sc_intrhand
= func
;
335 sc
->sc_slots
[slot
].sc_intrarg
= arg
;
336 tcds_scsi_reset(&sc
->sc_slots
[slot
]);
340 tcds_intr_disestablish(device_t tcds
, int slot
)
342 struct tcds_softc
*sc
= device_private(tcds
);
344 if (sc
->sc_slots
[slot
].sc_intrhand
== tcds_intrnull
)
345 panic("tcds_intr_disestablish: chip %d missing intr",
348 sc
->sc_slots
[slot
].sc_intrhand
= tcds_intrnull
;
349 sc
->sc_slots
[slot
].sc_intrarg
= (void *)(u_long
)slot
;
351 tcds_dma_enable(&sc
->sc_slots
[slot
], 0);
352 tcds_scsi_enable(&sc
->sc_slots
[slot
], 0);
356 tcds_intrnull(void *val
)
359 panic("tcds_intrnull: uncaught TCDS intr for chip %lu",
364 tcds_scsi_reset(struct tcds_slotconfig
*sc
)
368 tcds_dma_enable(sc
, 0);
369 tcds_scsi_enable(sc
, 0);
371 cir
= bus_space_read_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
);
372 TCDS_CIR_CLR(cir
, sc
->sc_resetbits
);
373 bus_space_write_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
, cir
);
377 cir
= bus_space_read_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
);
378 TCDS_CIR_SET(cir
, sc
->sc_resetbits
);
379 bus_space_write_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
, cir
);
381 tcds_scsi_enable(sc
, 1);
382 tcds_dma_enable(sc
, 1);
386 tcds_scsi_enable(struct tcds_slotconfig
*sc
, int on
)
390 imer
= bus_space_read_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_IMER
);
393 imer
|= sc
->sc_intrmaskbits
;
395 imer
&= ~sc
->sc_intrmaskbits
;
397 bus_space_write_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_IMER
, imer
);
401 tcds_dma_enable(struct tcds_slotconfig
*sc
, int on
)
405 cir
= bus_space_read_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
);
407 /* XXX Clear/set IOSLOT/PBS bits. */
409 TCDS_CIR_SET(cir
, sc
->sc_dmabits
);
411 TCDS_CIR_CLR(cir
, sc
->sc_dmabits
);
413 bus_space_write_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
, cir
);
417 tcds_scsi_isintr(struct tcds_slotconfig
*sc
, int clear
)
421 cir
= bus_space_read_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
);
423 if ((cir
& sc
->sc_intrbits
) != 0) {
425 TCDS_CIR_CLR(cir
, sc
->sc_intrbits
);
426 bus_space_write_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
,
435 tcds_scsi_iserr(struct tcds_slotconfig
*sc
)
439 cir
= bus_space_read_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
);
440 return ((cir
& sc
->sc_errorbits
) != 0);
446 struct tcds_softc
*sc
= arg
;
451 * Copy and clear (gag!) the interrupts.
453 ir
= ir0
= bus_space_read_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
);
454 TCDS_CIR_CLR(ir0
, TCDS_CIR_ALLINTR
);
455 bus_space_write_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_CIR
, ir0
);
458 #define INCRINTRCNT(slot) sc->sc_slots[slot].sc_evcnt.ev_count++
460 #define CHECKINTR(slot) \
461 if (ir & sc->sc_slots[slot].sc_intrbits) { \
463 (void)(*sc->sc_slots[slot].sc_intrhand) \
464 (sc->sc_slots[slot].sc_intrarg); \
472 * Interrupts not currently handled, but would like to know if they
476 * Don't know if we have to set the interrupt mask and enable bits
477 * in the IMER to allow some of them to happen?
479 #define PRINTINTR(msg, bits) \
481 printf("%s: %s", device_xname(sc->sc_dev), msg);
482 PRINTINTR("SCSI0 DREQ interrupt.\n", TCDS_CIR_SCSI0_DREQ
);
483 PRINTINTR("SCSI1 DREQ interrupt.\n", TCDS_CIR_SCSI1_DREQ
);
484 PRINTINTR("SCSI0 prefetch interrupt.\n", TCDS_CIR_SCSI0_PREFETCH
);
485 PRINTINTR("SCSI1 prefetch interrupt.\n", TCDS_CIR_SCSI1_PREFETCH
);
486 PRINTINTR("SCSI0 DMA error.\n", TCDS_CIR_SCSI0_DMA
);
487 PRINTINTR("SCSI1 DMA error.\n", TCDS_CIR_SCSI1_DMA
);
488 PRINTINTR("SCSI0 DB parity error.\n", TCDS_CIR_SCSI0_DB
);
489 PRINTINTR("SCSI1 DB parity error.\n", TCDS_CIR_SCSI1_DB
);
490 PRINTINTR("SCSI0 DMA buffer parity error.\n", TCDS_CIR_SCSI0_DMAB_PAR
);
491 PRINTINTR("SCSI1 DMA buffer parity error.\n", TCDS_CIR_SCSI1_DMAB_PAR
);
492 PRINTINTR("SCSI0 DMA read parity error.\n", TCDS_CIR_SCSI0_DMAR_PAR
);
493 PRINTINTR("SCSI1 DMA read parity error.\n", TCDS_CIR_SCSI1_DMAR_PAR
);
494 PRINTINTR("TC write parity error.\n", TCDS_CIR_TCIOW_PAR
);
495 PRINTINTR("TC I/O address parity error.\n", TCDS_CIR_TCIOA_PAR
);
501 * The MACH source had this, with the comment:
502 * This is wrong, but machine keeps dying.
510 tcds_params(struct tcds_softc
*sc
, int chip
, int *idp
, int *fastp
)
516 if (sc
->sc_flags
& TCDSF_BASEBOARD
) {
517 extern uint8_t dec_3000_scsiid
[], dec_3000_scsifast
[];
519 id
= dec_3000_scsiid
[chip
];
520 fast
= dec_3000_scsifast
[chip
];
522 #endif /* __alpha__ */
525 * SCSI IDs are stored in the EEPROM, along with whether or
526 * not the device is "fast". Chip 0 is the high nibble,
527 * chip 1 the low nibble.
529 ids
= bus_space_read_4(sc
->sc_bst
, sc
->sc_bsh
, TCDS_EEPROM_IDS
);
537 if (id
< 0 || id
> 7) {
538 printf("%s: WARNING: bad SCSI ID %d for chip %d, using 7\n",
539 device_xname(sc
->sc_dev
), id
, chip
);
544 printf("%s: fast mode set for chip %d\n",
545 device_xname(sc
->sc_dev
), chip
);