1 /* $NetBSD: stpcide.c,v 1.18 2008/03/18 20:46:37 cube Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: stpcide.c,v 1.18 2008/03/18 20:46:37 cube Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
38 #include <dev/pci/pcivar.h>
39 #include <dev/pci/pcidevs.h>
40 #include <dev/pci/pciidereg.h>
41 #include <dev/pci/pciidevar.h>
43 static void stpc_chip_map(struct pciide_softc
*, struct pci_attach_args
*);
44 static void stpc_setup_channel(struct ata_channel
*);
46 static int stpcide_match(device_t
, cfdata_t
, void *);
47 static void stpcide_attach(device_t
, device_t
, void *);
49 const struct pciide_product_desc pciide_stpc_products
[] = {
52 "STMicroelectronics STPC IDE Controller",
58 CFATTACH_DECL_NEW(stpcide
, sizeof(struct pciide_softc
),
59 stpcide_match
, stpcide_attach
, NULL
, NULL
);
62 stpcide_match(device_t parent
, cfdata_t match
, void *aux
)
64 struct pci_attach_args
*pa
= aux
;
66 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_SGSTHOMSON
) {
67 if (pciide_lookup_product(pa
->pa_id
, pciide_stpc_products
))
74 stpcide_attach(device_t parent
, device_t self
, void *aux
)
76 struct pci_attach_args
*pa
= aux
;
77 struct pciide_softc
*sc
= device_private(self
);
79 sc
->sc_wdcdev
.sc_atac
.atac_dev
= self
;
81 pciide_common_attach(sc
, pa
,
82 pciide_lookup_product(pa
->pa_id
, pciide_stpc_products
));
87 stpc_chip_map(struct pciide_softc
*sc
, struct pci_attach_args
*pa
)
89 struct pciide_channel
*cp
;
91 pcireg_t interface
= PCI_INTERFACE(pa
->pa_class
);
92 bus_size_t cmdsize
, ctlsize
;
94 if (pciide_chipen(sc
, pa
) == 0)
97 aprint_verbose_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
98 "bus-master DMA support present");
99 pciide_mapreg_dma(sc
, pa
);
100 aprint_verbose("\n");
101 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_DATA16
| ATAC_CAP_DATA32
;
103 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_DMA
;
104 sc
->sc_wdcdev
.irqack
= pciide_irqack
;
106 sc
->sc_wdcdev
.sc_atac
.atac_pio_cap
= 4;
107 sc
->sc_wdcdev
.sc_atac
.atac_dma_cap
= 2;
108 sc
->sc_wdcdev
.sc_atac
.atac_udma_cap
= 0;
109 sc
->sc_wdcdev
.sc_atac
.atac_set_modes
= stpc_setup_channel
;
110 sc
->sc_wdcdev
.sc_atac
.atac_channels
= sc
->wdc_chanarray
;
111 sc
->sc_wdcdev
.sc_atac
.atac_nchannels
= PCIIDE_NUM_CHANNELS
;
113 wdc_allocate_regs(&sc
->sc_wdcdev
);
115 for (channel
= 0; channel
< sc
->sc_wdcdev
.sc_atac
.atac_nchannels
;
117 cp
= &sc
->pciide_channels
[channel
];
118 if (pciide_chansetup(sc
, channel
, interface
) == 0)
120 pciide_mapchan(pa
, cp
, interface
, &cmdsize
, &ctlsize
,
126 * IDE timing register (0x40, 0x42, 0x44, and 0x46) assignment.
127 * 33MHz PCI system will have;
138 static const u_int16_t dmatbl
[] = { 0x7C00, 0x1800, 0x0800 };
139 static const u_int16_t piotbl
[] = { 0x03C0, 0x0230, 0x01A0, 0x0110, 0x0010 };
142 stpc_setup_channel(struct ata_channel
*chp
)
144 struct atac_softc
*atac
= chp
->ch_atac
;
145 struct pciide_channel
*cp
= CHAN_TO_PCHAN(chp
);
146 struct pciide_softc
*sc
= CHAN_TO_PCIIDE(chp
);
147 int channel
= chp
->ch_channel
;
148 struct ata_drive_datas
*drvp
;
149 u_int32_t idedma_ctl
, idetim
;
150 int drive
, bits
[2], s
;
152 /* setup DMA if needed */
153 pciide_channel_dma_setup(cp
);
156 bits
[0] = bits
[1] = 0x7F60; /* assume PIO2/DMA0 */
158 /* Per drive settings */
159 for (drive
= 0; drive
< 2; drive
++) {
160 drvp
= &chp
->ch_drive
[drive
];
161 /* If no drive, skip */
162 if ((drvp
->drive_flags
& DRIVE
) == 0)
164 /* add timing values, setup DMA if needed */
165 if ((atac
->atac_cap
& ATAC_CAP_DMA
) &&
166 (drvp
->drive_flags
& DRIVE_DMA
)) {
167 /* use Multiword DMA */
169 drvp
->drive_flags
&= ~DRIVE_UDMA
;
171 idedma_ctl
|= IDEDMA_CTL_DRV_DMA(drive
);
172 bits
[drive
] = 0xe; /* IOCHRDY,wr/post,rd/prefetch */
177 drvp
->drive_flags
&= ~(DRIVE_UDMA
| DRIVE_DMA
);
179 bits
[drive
] = 0x8; /* IOCHRDY */
181 bits
[drive
] |= dmatbl
[drvp
->DMA_mode
] | piotbl
[drvp
->PIO_mode
];
184 idetim
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
185 (channel
== 0) ? 0x40 : 0x44);
186 aprint_normal("wdc%d: IDETIM %08x -> %08x\n",
187 channel
, idetim
, (bits
[1] << 16) | bits
[0]);
189 idetim
= (bits
[1] << 16) | bits
[0];
190 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
,
191 (channel
== 0) ? 0x40 : 0x44, idetim
);
193 if (idedma_ctl
!= 0) {
194 /* Add software bits in status register */
195 bus_space_write_1(sc
->sc_dma_iot
, cp
->dma_iohs
[IDEDMA_CTL
], 0,