1 /* $NetBSD: svwsata.c,v 1.10 2008/03/18 20:46:37 cube Exp $ */
4 * Copyright (c) 2005 Mark Kettenis
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/cdefs.h>
20 __KERNEL_RCSID(0, "$NetBSD: svwsata.c,v 1.10 2008/03/18 20:46:37 cube Exp $");
22 #include <sys/param.h>
23 #include <sys/systm.h>
25 #include <dev/ata/atareg.h>
26 #include <dev/ata/satareg.h>
27 #include <dev/ata/satavar.h>
28 #include <dev/pci/pcivar.h>
29 #include <dev/pci/pcidevs.h>
30 #include <dev/pci/pciidereg.h>
31 #include <dev/pci/pciidevar.h>
32 #include <dev/pci/pciide_svwsata_reg.h>
34 static int svwsata_match(device_t
, cfdata_t
, void *);
35 static void svwsata_attach(device_t
, device_t
, void *);
37 static void svwsata_chip_map(struct pciide_softc
*, struct pci_attach_args
*);
38 static void svwsata_mapreg_dma(struct pciide_softc
*, struct pci_attach_args
*);
39 static void svwsata_mapchan(struct pciide_channel
*);
41 CFATTACH_DECL_NEW(svwsata
, sizeof(struct pciide_softc
),
42 svwsata_match
, svwsata_attach
, NULL
, NULL
);
44 static const struct pciide_product_desc pciide_svwsata_products
[] = {
45 { PCI_PRODUCT_SERVERWORKS_K2_SATA
,
47 "ServerWorks K2 SATA Controller",
50 { PCI_PRODUCT_SERVERWORKS_FRODO4_SATA
,
52 "ServerWorks Frodo4 SATA Controller",
55 { PCI_PRODUCT_SERVERWORKS_FRODO8_SATA
,
57 "ServerWorks Frodo8 SATA Controller",
60 { PCI_PRODUCT_SERVERWORKS_HT1000_SATA_1
,
62 "ServerWorks HT-1000 SATA Controller",
65 { PCI_PRODUCT_SERVERWORKS_HT1000_SATA_2
,
67 "ServerWorks HT-1000 SATA Controller",
78 svwsata_match(device_t parent
, cfdata_t match
, void *aux
)
80 struct pci_attach_args
*pa
= aux
;
82 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_SERVERWORKS
) {
83 if (pciide_lookup_product(pa
->pa_id
,
84 pciide_svwsata_products
))
91 svwsata_attach(device_t parent
, device_t self
, void *aux
)
93 struct pci_attach_args
*pa
= aux
;
94 struct pciide_softc
*sc
= device_private(self
);
96 sc
->sc_wdcdev
.sc_atac
.atac_dev
= self
;
98 pciide_common_attach(sc
, pa
,
99 pciide_lookup_product(pa
->pa_id
, pciide_svwsata_products
));
103 svwsata_chip_map(struct pciide_softc
*sc
, struct pci_attach_args
*pa
)
105 struct pciide_channel
*cp
;
106 pci_intr_handle_t intrhandle
;
111 if (pciide_chipen(sc
, pa
) == 0)
114 /* The 4-port version has a dummy second function. */
115 if (pci_conf_read(sc
->sc_pc
, sc
->sc_tag
,
116 PCI_MAPREG_START
+ 0x14) == 0) {
121 if (pci_mapreg_map(pa
, PCI_MAPREG_START
+ 0x14,
122 PCI_MAPREG_TYPE_MEM
|
123 PCI_MAPREG_MEM_TYPE_32BIT
, 0,
124 &sc
->sc_ba5_st
, &sc
->sc_ba5_sh
,
126 aprint_error(": unable to map BA5 register space\n");
130 aprint_verbose_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
131 "bus-master DMA support present");
132 svwsata_mapreg_dma(sc
, pa
);
133 aprint_verbose("\n");
135 sc
->sc_wdcdev
.cap
= WDC_CAPABILITY_WIDEREGS
;
137 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_DATA16
| ATAC_CAP_DATA32
;
138 sc
->sc_wdcdev
.sc_atac
.atac_pio_cap
= 4;
140 sc
->sc_wdcdev
.sc_atac
.atac_cap
|= ATAC_CAP_DMA
| ATAC_CAP_UDMA
;
141 sc
->sc_wdcdev
.irqack
= pciide_irqack
;
142 sc
->sc_wdcdev
.sc_atac
.atac_dma_cap
= 2;
143 sc
->sc_wdcdev
.sc_atac
.atac_udma_cap
= 6;
146 sc
->sc_wdcdev
.sc_atac
.atac_channels
= sc
->wdc_chanarray
;
147 sc
->sc_wdcdev
.sc_atac
.atac_nchannels
= 4;
148 sc
->sc_wdcdev
.sc_atac
.atac_set_modes
= sata_setup_channel
;
150 /* We can use SControl and SStatus to probe for drives. */
151 sc
->sc_wdcdev
.sc_atac
.atac_probe
= wdc_sataprobe
;
153 wdc_allocate_regs(&sc
->sc_wdcdev
);
155 /* Map and establish the interrupt handler. */
156 if(pci_intr_map(pa
, &intrhandle
) != 0) {
157 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
158 "couldn't map native-PCI interrupt\n");
161 intrstr
= pci_intr_string(pa
->pa_pc
, intrhandle
);
162 sc
->sc_pci_ih
= pci_intr_establish(pa
->pa_pc
, intrhandle
, IPL_BIO
,
163 pciide_pci_intr
, sc
);
164 if (sc
->sc_pci_ih
!= NULL
) {
165 aprint_normal_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
166 "using %s for native-PCI interrupt\n",
167 intrstr
? intrstr
: "unknown interrupt");
169 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
170 "couldn't establish native-PCI interrupt");
172 aprint_error(" at %s", intrstr
);
177 interface
= PCIIDE_INTERFACE_BUS_MASTER_DMA
|
178 PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1);
181 for (channel
= 0; channel
< sc
->sc_wdcdev
.sc_atac
.atac_nchannels
;
183 cp
= &sc
->pciide_channels
[channel
];
185 if (pciide_chansetup(sc
, channel
, interface
) == 0)
192 svwsata_mapreg_dma(struct pciide_softc
*sc
, struct pci_attach_args
*pa
)
194 struct pciide_channel
*pc
;
198 sc
->sc_wdcdev
.dma_arg
= sc
;
199 sc
->sc_wdcdev
.dma_init
= pciide_dma_init
;
200 sc
->sc_wdcdev
.dma_start
= pciide_dma_start
;
201 sc
->sc_wdcdev
.dma_finish
= pciide_dma_finish
;
203 if (device_cfdata(sc
->sc_wdcdev
.sc_atac
.atac_dev
)->cf_flags
&
204 PCIIDE_OPTIONS_NODMA
) {
206 ", but unused (forced off by config file)");
212 * Slice off a subregion of BA5 for each of the channel's DMA
216 sc
->sc_dma_iot
= sc
->sc_ba5_st
;
217 for (chan
= 0; chan
< 4; chan
++) {
218 pc
= &sc
->pciide_channels
[chan
];
219 for (reg
= 0; reg
< IDEDMA_NREGS
; reg
++) {
221 if (size
> (IDEDMA_SCH_OFFSET
- reg
))
222 size
= IDEDMA_SCH_OFFSET
- reg
;
223 if (bus_space_subregion(sc
->sc_ba5_st
,
225 (chan
<< 8) + SVWSATA_DMA
+ reg
,
226 size
, &pc
->dma_iohs
[reg
]) != 0) {
228 aprint_normal(", but can't subregion offset "
230 (u_long
) (chan
<< 8) + SVWSATA_DMA
+ reg
,
237 /* DMA registers all set up! */
238 sc
->sc_dmat
= pa
->pa_dmat
;
243 svwsata_mapchan(struct pciide_channel
*cp
)
245 struct ata_channel
*wdc_cp
= &cp
->ata_channel
;
246 struct pciide_softc
*sc
= CHAN_TO_PCIIDE(wdc_cp
);
247 struct wdc_regs
*wdr
= CHAN_TO_WDC_REGS(wdc_cp
);
251 cp
->ih
= sc
->sc_pci_ih
;
253 wdr
->cmd_iot
= sc
->sc_ba5_st
;
254 if (bus_space_subregion(sc
->sc_ba5_st
, sc
->sc_ba5_sh
,
255 (wdc_cp
->ch_channel
<< 8) + SVWSATA_TF0
,
256 SVWSATA_TF8
- SVWSATA_TF0
, &wdr
->cmd_baseioh
) != 0) {
257 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
258 "couldn't map %s cmd regs\n", cp
->name
);
262 wdr
->ctl_iot
= sc
->sc_ba5_st
;
263 if (bus_space_subregion(sc
->sc_ba5_st
, sc
->sc_ba5_sh
,
264 (wdc_cp
->ch_channel
<< 8) + SVWSATA_TF8
, 4,
265 &cp
->ctl_baseioh
) != 0) {
266 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
267 "couldn't map %s ctl regs\n", cp
->name
);
270 wdr
->ctl_ioh
= cp
->ctl_baseioh
;
272 for (i
= 0; i
< WDC_NREG
; i
++) {
273 if (bus_space_subregion(wdr
->cmd_iot
, wdr
->cmd_baseioh
,
274 i
<< 2, i
== 0 ? 4 : 1,
275 &wdr
->cmd_iohs
[i
]) != 0) {
276 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
277 "couldn't subregion %s channel cmd regs\n",
282 wdc_init_shadow_regs(wdc_cp
);
283 wdr
->data32iot
= wdr
->cmd_iot
;
284 wdr
->data32ioh
= wdr
->cmd_iohs
[0];
287 wdr
->sata_iot
= sc
->sc_ba5_st
;
288 wdr
->sata_baseioh
= sc
->sc_ba5_sh
;
289 if (bus_space_subregion(wdr
->sata_iot
, wdr
->sata_baseioh
,
290 (wdc_cp
->ch_channel
<< 8) + SVWSATA_SSTATUS
, 1,
291 &wdr
->sata_status
) != 0) {
292 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
293 "couldn't map channel %d sata_status regs\n",
297 if (bus_space_subregion(wdr
->sata_iot
, wdr
->sata_baseioh
,
298 (wdc_cp
->ch_channel
<< 8) + SVWSATA_SERROR
, 1,
299 &wdr
->sata_error
) != 0) {
300 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
301 "couldn't map channel %d sata_error regs\n",
305 if (bus_space_subregion(wdr
->sata_iot
, wdr
->sata_baseioh
,
306 (wdc_cp
->ch_channel
<< 8) + SVWSATA_SCONTROL
, 1,
307 &wdr
->sata_control
) != 0) {
308 aprint_error_dev(sc
->sc_wdcdev
.sc_atac
.atac_dev
,
309 "couldn't map channel %d sata_control regs\n",
318 cp
->ata_channel
.ch_flags
|= ATACH_DISABLED
;