1 /* $NetBSD: toshide.c,v 1.1 2009/09/20 01:10:12 christos Exp $ */
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: toshide.c,v 1.1 2009/09/20 01:10:12 christos Exp $");
32 #include <sys/param.h>
33 #include <sys/systm.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_piccolo_reg.h>
41 static void piccolo_chip_map(struct pciide_softc
*, struct pci_attach_args
*);
42 static void piccolo_setup_channel(struct ata_channel
*);
44 static int piccolo_match(device_t
, cfdata_t
, void *);
45 static void piccolo_attach(device_t
, device_t
, void *);
47 CFATTACH_DECL_NEW(toshide
, sizeof(struct pciide_softc
),
48 piccolo_match
, piccolo_attach
, NULL
, NULL
);
50 static const struct pciide_product_desc pciide_toshiba2_products
[] = {
52 PCI_PRODUCT_TOSHIBA2_PICCOLO
,
54 "Toshiba Piccolo IDE controller",
58 PCI_PRODUCT_TOSHIBA2_PICCOLO2
,
60 "Toshiba Piccolo 2 IDE controller",
64 PCI_PRODUCT_TOSHIBA2_PICCOLO3
,
66 "Toshiba Piccolo 3 IDE controller",
70 PCI_PRODUCT_TOSHIBA2_PICCOLO5
,
72 "Toshiba Piccolo 5 IDE controller",
84 piccolo_match(device_t parent
, cfdata_t match
, void *aux
)
86 struct pci_attach_args
*pa
= aux
;
88 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_TOSHIBA2
) {
89 if (pciide_lookup_product(pa
->pa_id
, pciide_toshiba2_products
))
96 piccolo_attach(device_t parent
, device_t self
, void *aux
)
98 struct pci_attach_args
*pa
= aux
;
99 struct pciide_softc
*sc
= device_private(self
);
100 const struct pciide_product_desc
*pp
;
102 sc
->sc_wdcdev
.sc_atac
.atac_dev
= self
;
104 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_TOSHIBA2
)
105 pp
= pciide_lookup_product(pa
->pa_id
, pciide_toshiba2_products
);
109 panic("toshide_attach");
110 pciide_common_attach(sc
, pa
, pp
);
114 piccolo_chip_map(struct pciide_softc
*sc
, struct pci_attach_args
*pa
)
116 struct pciide_channel
*cp
;
117 bus_size_t cmdsize
, ctlsize
;
121 if (pciide_chipen(sc
, pa
) == 0)
124 aprint_verbose_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
125 "bus-master DMA support present");
127 pciide_mapreg_dma(sc
, pa
);
128 aprint_verbose("\n");
130 sc
->sc_wdcdev
.sc_atac
.atac_cap
= ATAC_CAP_DATA32
| ATAC_CAP_DATA16
;
131 sc
->sc_wdcdev
.sc_atac
.atac_pio_cap
= 5;
134 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_DMA
| ATAC_CAP_UDMA
;
135 sc
->sc_wdcdev
.irqack
= pciide_irqack
;
136 sc
->sc_wdcdev
.sc_atac
.atac_dma_cap
= 3;
137 sc
->sc_wdcdev
.sc_atac
.atac_udma_cap
= 2;
140 sc
->sc_wdcdev
.sc_atac
.atac_set_modes
= piccolo_setup_channel
;
142 sc
->sc_wdcdev
.sc_atac
.atac_channels
= sc
->wdc_chanarray
;
143 sc
->sc_wdcdev
.sc_atac
.atac_nchannels
= 1;
145 * XXX one for now. We'll figure out how to talk to the second channel
146 * later, hopefully! Second interface config is via the
147 * "alternate PCI Configuration Space" whatever that is!
150 interface
= PCI_INTERFACE(pa
->pa_class
);
152 wdc_allocate_regs(&sc
->sc_wdcdev
);
154 for (channel
= 0; channel
< sc
->sc_wdcdev
.sc_atac
.atac_nchannels
;
156 cp
= &sc
->pciide_channels
[channel
];
157 if (pciide_chansetup(sc
, channel
, interface
) == 0)
160 pciide_mapchan(pa
, cp
, interface
, &cmdsize
, &ctlsize
,
166 piccolo_setup_channel(struct ata_channel
*chp
)
168 struct ata_drive_datas
*drvp
;
169 struct pciide_channel
*cp
= CHAN_TO_PCHAN(chp
);
170 struct pciide_softc
*sc
= CHAN_TO_PCIIDE(chp
);
171 u_int32_t idedma_ctl
;
180 /* Set up DMA if needed. */
181 pciide_channel_dma_setup(cp
);
183 for (drive
= 0; drive
< 2; drive
++) {
185 drvp
= &chp
->ch_drive
[drive
];
186 /* If no drive, skip */
187 if ((drvp
->drive_flags
& DRIVE
) == 0)
190 if (drvp
->drive_flags
& DRIVE_UDMA
) {
193 drvp
->drive_flags
&= ~DRIVE_DMA
;
197 * Use UDMA - we can go up to mode 2 so no need to
198 * check anything since nearly all drives with UDMA
199 * are mode 2 or faster
201 pxdx
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
203 pxdx
&= PICCOLO_UDMA_MASK
;
204 pxdx
|= piccolo_udma_times
[2];
205 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
,
206 PICCOLO_DMA_TIMING
, pxdx
);
208 /* XXX sanity check */
209 pxdx_prime
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
211 aprint_verbose_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
212 "UDMA want %x, set %x, got %x\n",
213 piccolo_udma_times
[2], pxdx
, pxdx_prime
);
215 idedma_ctl
|= IDEDMA_CTL_DRV_DMA(drive
);
218 else if (drvp
->drive_flags
& DRIVE_DMA
) {
222 if (drvp
->PIO_mode
> (drvp
->DMA_mode
+ 2))
223 drvp
->PIO_mode
= drvp
->DMA_mode
+ 2;
224 if (drvp
->DMA_mode
+ 2 > (drvp
->PIO_mode
))
225 drvp
->DMA_mode
= (drvp
->PIO_mode
> 2) ?
226 drvp
->PIO_mode
- 2 : 0;
228 pxdx
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
230 pxdx
&= PICCOLO_DMA_MASK
;
231 pxdx
|= piccolo_mw_dma_times
[drvp
->DMA_mode
];
232 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
,
233 PICCOLO_DMA_TIMING
, pxdx
);
235 /* XXX sanity check */
236 pxdx_prime
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
238 aprint_verbose_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
239 "DMA %d want %x, set %x, got %x\n",
241 piccolo_mw_dma_times
[drvp
->DMA_mode
], pxdx
,
244 idedma_ctl
|= IDEDMA_CTL_DRV_DMA(drive
);
248 pxdx
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
250 pxdx
&= PICCOLO_PIO_MASK
;
251 pxdx
|= piccolo_pio_times
[drvp
->PIO_mode
];
252 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
,
253 PICCOLO_PIO_TIMING
, pxdx
);
255 /* XXX sanity check */
256 pxdx_prime
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
258 aprint_verbose_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
259 "PIO %d want %x, set %x, got %x\n", drvp
->PIO_mode
,
260 piccolo_pio_times
[drvp
->PIO_mode
], pxdx
,
266 if (idedma_ctl
!= 0) {
267 /* Add software bits in status register */
268 bus_space_write_1(sc
->sc_dma_iot
, cp
->dma_iohs
[IDEDMA_CTL
], 0,