1 /* $NetBSD: cypide.c,v 1.21 2008/03/18 20:46:36 cube Exp $ */
4 * Copyright (c) 1999, 2000, 2001 Manuel Bouyer.
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.
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: cypide.c,v 1.21 2008/03/18 20:46:36 cube Exp $");
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/malloc.h>
35 #include <dev/pci/pcivar.h>
36 #include <dev/pci/pcidevs.h>
37 #include <dev/pci/pciidereg.h>
38 #include <dev/pci/pciidevar.h>
39 #include <dev/pci/pciide_cy693_reg.h>
40 #include <dev/pci/cy82c693var.h>
42 static void cy693_chip_map(struct pciide_softc
*, struct pci_attach_args
*);
43 static void cy693_setup_channel(struct ata_channel
*);
45 static int cypide_match(device_t
, cfdata_t
, void *);
46 static void cypide_attach(device_t
, device_t
, void *);
48 CFATTACH_DECL_NEW(cypide
, sizeof(struct pciide_softc
),
49 cypide_match
, cypide_attach
, NULL
, NULL
);
51 static const struct pciide_product_desc pciide_cypress_products
[] = {
52 { PCI_PRODUCT_CONTAQ_82C693
,
54 "Cypress 82C693 IDE Controller",
65 cypide_match(device_t parent
, cfdata_t match
, void *aux
)
67 struct pci_attach_args
*pa
= aux
;
69 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_CONTAQ
&&
70 PCI_CLASS(pa
->pa_class
) == PCI_CLASS_MASS_STORAGE
&&
71 PCI_SUBCLASS(pa
->pa_class
) == PCI_SUBCLASS_MASS_STORAGE_IDE
) {
72 if (pciide_lookup_product(pa
->pa_id
, pciide_cypress_products
))
79 cypide_attach(device_t parent
, device_t self
, void *aux
)
81 struct pci_attach_args
*pa
= aux
;
82 struct pciide_softc
*sc
= device_private(self
);
84 sc
->sc_wdcdev
.sc_atac
.atac_dev
= self
;
86 pciide_common_attach(sc
, pa
,
87 pciide_lookup_product(pa
->pa_id
, pciide_cypress_products
));
92 cy693_chip_map(struct pciide_softc
*sc
, struct pci_attach_args
*pa
)
94 struct pciide_channel
*cp
;
95 pcireg_t interface
= PCI_INTERFACE(pa
->pa_class
);
96 bus_size_t cmdsize
, ctlsize
;
98 if (pciide_chipen(sc
, pa
) == 0)
102 * this chip has 2 PCI IDE functions, one for primary and one for
103 * secondary. So we need to call pciide_mapregs_compat() with
106 if (pa
->pa_function
== 1) {
107 sc
->sc_cy_compatchan
= 0;
108 } else if (pa
->pa_function
== 2) {
109 sc
->sc_cy_compatchan
= 1;
111 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
112 "unexpected PCI function %d\n", pa
->pa_function
);
115 if (interface
& PCIIDE_INTERFACE_BUS_MASTER_DMA
) {
116 aprint_verbose_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
117 "bus-master DMA support present\n");
118 pciide_mapreg_dma(sc
, pa
);
120 aprint_normal_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
121 "hardware does not support DMA\n");
125 sc
->sc_cy_handle
= cy82c693_init(pa
->pa_iot
);
126 if (sc
->sc_cy_handle
== NULL
) {
127 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
128 "unable to map hyperCache control registers\n");
132 sc
->sc_wdcdev
.sc_atac
.atac_cap
= ATAC_CAP_DATA16
| ATAC_CAP_DATA32
;
134 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_DMA
;
135 sc
->sc_wdcdev
.irqack
= pciide_irqack
;
137 sc
->sc_wdcdev
.sc_atac
.atac_pio_cap
= 4;
138 sc
->sc_wdcdev
.sc_atac
.atac_dma_cap
= 2;
139 sc
->sc_wdcdev
.sc_atac
.atac_set_modes
= cy693_setup_channel
;
141 sc
->sc_wdcdev
.sc_atac
.atac_channels
= sc
->wdc_chanarray
;
142 sc
->sc_wdcdev
.sc_atac
.atac_nchannels
= 1;
144 wdc_allocate_regs(&sc
->sc_wdcdev
);
146 /* Only one channel for this chip; if we are here it's enabled */
147 cp
= &sc
->pciide_channels
[0];
148 sc
->wdc_chanarray
[0] = &cp
->ata_channel
;
149 cp
->name
= PCIIDE_CHANNEL_NAME(0);
150 cp
->ata_channel
.ch_channel
= 0;
151 cp
->ata_channel
.ch_atac
= &sc
->sc_wdcdev
.sc_atac
;
152 cp
->ata_channel
.ch_queue
=
153 malloc(sizeof(struct ata_queue
), M_DEVBUF
, M_NOWAIT
);
154 cp
->ata_channel
.ch_ndrive
= 2;
155 if (cp
->ata_channel
.ch_queue
== NULL
) {
156 aprint_error("%s primary channel: "
157 "can't allocate memory for command queue",
158 device_xname(sc
->sc_wdcdev
.sc_atac
.atac_dev
));
161 aprint_normal_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
162 "primary channel %s to ",
163 (interface
& PCIIDE_INTERFACE_SETTABLE(0)) ?
164 "configured" : "wired");
165 if (interface
& PCIIDE_INTERFACE_PCI(0)) {
166 aprint_normal("native-PCI mode\n");
167 pciide_mapregs_native(pa
, cp
, &cmdsize
, &ctlsize
,
170 aprint_normal("compatibility mode\n");
171 pciide_mapregs_compat(pa
, cp
, sc
->sc_cy_compatchan
, &cmdsize
,
173 if ((cp
->ata_channel
.ch_flags
& ATACH_DISABLED
) == 0)
174 pciide_map_compat_intr(pa
, cp
, sc
->sc_cy_compatchan
);
176 wdcattach(&cp
->ata_channel
);
180 cy693_setup_channel(struct ata_channel
*chp
)
182 struct ata_drive_datas
*drvp
;
184 u_int32_t cy_cmd_ctrl
;
185 u_int32_t idedma_ctl
;
186 struct pciide_channel
*cp
= CHAN_TO_PCHAN(chp
);
187 struct pciide_softc
*sc
= CHAN_TO_PCIIDE(chp
);
190 ATADEBUG_PRINT(("cy693_chip_map: old timings reg 0x%x\n",
191 pci_conf_read(sc
->sc_pc
, sc
->sc_tag
, CY_CMD_CTRL
)),DEBUG_PROBE
);
193 cy_cmd_ctrl
= idedma_ctl
= 0;
195 /* setup DMA if needed */
196 pciide_channel_dma_setup(cp
);
198 for (drive
= 0; drive
< 2; drive
++) {
199 drvp
= &chp
->ch_drive
[drive
];
200 /* If no drive, skip */
201 if ((drvp
->drive_flags
& DRIVE
) == 0)
203 /* add timing values, setup DMA if needed */
204 if (drvp
->drive_flags
& DRIVE_DMA
) {
205 idedma_ctl
|= IDEDMA_CTL_DRV_DMA(drive
);
206 /* use Multiword DMA */
207 if (dma_mode
== -1 || dma_mode
> drvp
->DMA_mode
)
208 dma_mode
= drvp
->DMA_mode
;
210 cy_cmd_ctrl
|= (cy_pio_pulse
[drvp
->PIO_mode
] <<
211 CY_CMD_CTRL_IOW_PULSE_OFF(drive
));
212 cy_cmd_ctrl
|= (cy_pio_rec
[drvp
->PIO_mode
] <<
213 CY_CMD_CTRL_IOW_REC_OFF(drive
));
214 cy_cmd_ctrl
|= (cy_pio_pulse
[drvp
->PIO_mode
] <<
215 CY_CMD_CTRL_IOR_PULSE_OFF(drive
));
216 cy_cmd_ctrl
|= (cy_pio_rec
[drvp
->PIO_mode
] <<
217 CY_CMD_CTRL_IOR_REC_OFF(drive
));
219 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
, CY_CMD_CTRL
, cy_cmd_ctrl
);
220 chp
->ch_drive
[0].DMA_mode
= dma_mode
;
221 chp
->ch_drive
[1].DMA_mode
= dma_mode
;
226 if (sc
->sc_cy_handle
!= NULL
) {
227 /* Note: `multiple' is implied. */
228 cy82c693_write(sc
->sc_cy_handle
,
229 (sc
->sc_cy_compatchan
== 0) ?
230 CY_DMA_IDX_PRIMARY
: CY_DMA_IDX_SECONDARY
, dma_mode
);
233 if (idedma_ctl
!= 0) {
234 /* Add software bits in status register */
235 bus_space_write_1(sc
->sc_dma_iot
, cp
->dma_iohs
[IDEDMA_CTL
], 0,
238 ATADEBUG_PRINT(("cy693_chip_map: new timings reg 0x%x\n",
239 pci_conf_read(sc
->sc_pc
, sc
->sc_tag
, CY_CMD_CTRL
)), DEBUG_PROBE
);