1 /* $NetBSD: ixpide.c,v 1.14 2008/11/04 16:05:29 reinoud Exp $ */
4 * Copyright (c) 2004 The NetBSD Foundation.
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: ixpide.c,v 1.14 2008/11/04 16:05:29 reinoud 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_ixp_reg.h>
41 static bool ixpide_resume(device_t
, pmf_qual_t
);
42 static bool ixpide_suspend(device_t
, pmf_qual_t
);
43 static int ixpide_match(device_t
, cfdata_t
, void *);
44 static void ixpide_attach(device_t
, device_t
, void *);
46 static void ixp_chip_map(struct pciide_softc
*, struct pci_attach_args
*);
47 static void ixp_setup_channel(struct ata_channel
*);
49 CFATTACH_DECL_NEW(ixpide
, sizeof(struct pciide_softc
),
50 ixpide_match
, ixpide_attach
, NULL
, NULL
);
52 static const char ixpdesc
[] = "ATI Technologies IXP IDE Controller";
54 static const struct pciide_product_desc pciide_ixpide_products
[] = {
55 { PCI_PRODUCT_ATI_IXP_IDE_200
, 0, ixpdesc
, ixp_chip_map
},
56 { PCI_PRODUCT_ATI_IXP_IDE_300
, 0, ixpdesc
, ixp_chip_map
},
57 { PCI_PRODUCT_ATI_IXP_IDE_400
, 0, ixpdesc
, ixp_chip_map
},
58 { PCI_PRODUCT_ATI_IXP_IDE_600
, 0, ixpdesc
, ixp_chip_map
},
59 { PCI_PRODUCT_ATI_SB400_SATA_1
, 0, ixpdesc
, ixp_chip_map
},
60 { PCI_PRODUCT_ATI_SB400_SATA_2
, 0, ixpdesc
, ixp_chip_map
},
61 { PCI_PRODUCT_ATI_SB600_SATA_1
, 0, ixpdesc
, ixp_chip_map
},
62 { PCI_PRODUCT_ATI_SB600_SATA_2
, 0, ixpdesc
, ixp_chip_map
},
63 { PCI_PRODUCT_ATI_SB700_SATA_IDE
, 0, ixpdesc
, ixp_chip_map
},
64 { PCI_PRODUCT_ATI_SB700_IDE
, 0, ixpdesc
, ixp_chip_map
},
69 ixpide_match(device_t parent
, cfdata_t cfdata
, void *aux
)
71 struct pci_attach_args
*pa
= (struct pci_attach_args
*)aux
;
73 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_ATI
&&
74 PCI_CLASS(pa
->pa_class
) == PCI_CLASS_MASS_STORAGE
&&
75 PCI_SUBCLASS(pa
->pa_class
) == PCI_SUBCLASS_MASS_STORAGE_IDE
&&
76 pciide_lookup_product(pa
->pa_id
, pciide_ixpide_products
))
82 ixpide_attach(device_t parent
, device_t self
, void *aux
)
84 struct pci_attach_args
*pa
= aux
;
85 struct pciide_softc
*sc
= device_private(self
);
87 sc
->sc_wdcdev
.sc_atac
.atac_dev
= self
;
89 pciide_common_attach(sc
, pa
,
90 pciide_lookup_product(pa
->pa_id
, pciide_ixpide_products
));
92 if (!pmf_device_register(self
, ixpide_suspend
, ixpide_resume
))
93 aprint_error_dev(self
, "couldn't establish power handler\n");
97 ixp_chip_map(struct pciide_softc
*sc
, struct pci_attach_args
*pa
)
99 struct pciide_channel
*cp
;
102 bus_size_t cmdsize
, ctlsize
;
104 if (pciide_chipen(sc
, pa
) == 0)
107 aprint_verbose_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
108 "bus-master DMA support present");
109 pciide_mapreg_dma(sc
, pa
);
110 aprint_verbose("\n");
112 sc
->sc_wdcdev
.sc_atac
.atac_cap
= ATAC_CAP_DATA16
| ATAC_CAP_DATA32
;
114 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_DMA
| ATAC_CAP_UDMA
;
115 sc
->sc_wdcdev
.irqack
= pciide_irqack
;
118 sc
->sc_wdcdev
.sc_atac
.atac_pio_cap
= 4;
119 sc
->sc_wdcdev
.sc_atac
.atac_dma_cap
= 2;
120 sc
->sc_wdcdev
.sc_atac
.atac_udma_cap
= 6;
121 sc
->sc_wdcdev
.sc_atac
.atac_set_modes
= ixp_setup_channel
;
122 sc
->sc_wdcdev
.sc_atac
.atac_channels
= sc
->wdc_chanarray
;
123 sc
->sc_wdcdev
.sc_atac
.atac_nchannels
= PCIIDE_NUM_CHANNELS
;
125 interface
= PCI_INTERFACE(pa
->pa_class
);
127 wdc_allocate_regs(&sc
->sc_wdcdev
);
129 for (channel
= 0; channel
< sc
->sc_wdcdev
.sc_atac
.atac_nchannels
;
131 cp
= &sc
->pciide_channels
[channel
];
132 if (pciide_chansetup(sc
, channel
, interface
) == 0)
134 pciide_mapchan(pa
, cp
, interface
, &cmdsize
, &ctlsize
,
139 /* Values from linux driver */
140 static const uint8_t ixp_pio_timings
[] = {
141 0x5d, 0x47, 0x34, 0x22, 0x20
144 static const uint8_t ixp_mdma_timings
[] = {
149 ixpide_resume(device_t dv
, pmf_qual_t qual
)
151 struct pciide_softc
*sc
= device_private(dv
);
153 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
, IXP_MDMA_TIMING
,
155 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
, IXP_PIO_TIMING
,
162 ixpide_suspend(device_t dv
, pmf_qual_t qual
)
164 struct pciide_softc
*sc
= device_private(dv
);
166 sc
->sc_pm_reg
[0] = pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
168 sc
->sc_pm_reg
[1] = pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
175 ixp_setup_channel(struct ata_channel
*chp
)
178 struct pciide_channel
*cp
= CHAN_TO_PCHAN(chp
);
179 pcireg_t udma
, mdma_timing
, pio
, pio_timing
;
180 struct ata_drive_datas
*drvp
;
181 struct pciide_softc
*sc
= CHAN_TO_PCIIDE(chp
);
183 pio_timing
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
, IXP_PIO_TIMING
);
184 pio
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
, IXP_PIO_CTL
);
185 mdma_timing
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
, IXP_MDMA_TIMING
);
186 udma
= pci_conf_read(sc
->sc_pc
, sc
->sc_tag
, IXP_UDMA_CTL
);
188 pciide_channel_dma_setup(cp
);
190 for (drive
= 0; drive
< 2; drive
++) {
191 drvp
= &chp
->ch_drive
[drive
];
192 if ((drvp
->drive_flags
& DRIVE
) == 0)
194 if (drvp
->drive_flags
& DRIVE_UDMA
) {
196 drvp
->drive_flags
&= ~DRIVE_DMA
;
198 IXP_UDMA_ENABLE(udma
, chp
->ch_channel
, drive
);
199 IXP_SET_MODE(udma
, chp
->ch_channel
, drive
, drvp
->UDMA_mode
);
200 } else if (drvp
->drive_flags
& DRIVE_DMA
) {
201 IXP_UDMA_DISABLE(udma
, chp
->ch_channel
, drive
);
202 IXP_SET_TIMING(mdma_timing
, chp
->ch_channel
, drive
,
203 ixp_mdma_timings
[drvp
->DMA_mode
]);
205 IXP_UDMA_DISABLE(udma
, chp
->ch_channel
, drive
);
208 * Set PIO mode and timings
209 * Linux driver avoids PIO mode 1, let's do it too.
211 if (drvp
->PIO_mode
== 1)
214 IXP_SET_MODE(pio
, chp
->ch_channel
, drive
, drvp
->PIO_mode
);
215 IXP_SET_TIMING(pio_timing
, chp
->ch_channel
, drive
,
216 ixp_pio_timings
[drvp
->PIO_mode
]);
218 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
, IXP_UDMA_CTL
, udma
);
219 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
, IXP_MDMA_TIMING
, mdma_timing
);
220 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
, IXP_PIO_CTL
, pio
);
221 pci_conf_write(sc
->sc_pc
, sc
->sc_tag
, IXP_PIO_TIMING
, pio_timing
);
222 ATADEBUG_PRINT(("ixp_setup_channel: udma = %08x, mdma_timing = %08x, pio_mode = %08x,"
223 " pio_timing = %08x\n", udma
, mdma_timing
, pio
, pio_timing
), DEBUG_PROBE
);