ata-via.c revision 330897
1130803Smarcel/*- 2130803Smarcel * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 319370Spst * 419370Spst * Copyright (c) 1998 - 2008 S��ren Schmidt <sos@FreeBSD.org> 519370Spst * All rights reserved. 698944Sobrien * 719370Spst * Redistribution and use in source and binary forms, with or without 898944Sobrien * modification, are permitted provided that the following conditions 998944Sobrien * are met: 1046283Sdfr * 1. Redistributions of source code must retain the above copyright 1198944Sobrien * notice, this list of conditions and the following disclaimer, 1298944Sobrien * without modification, immediately at the beginning of the file. 1398944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1498944Sobrien * notice, this list of conditions and the following disclaimer in the 1598944Sobrien * documentation and/or other materials provided with the distribution. 1698944Sobrien * 1719370Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1819370Spst * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1919370Spst * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2098944Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2119370Spst * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2219370Spst * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23130803Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2419370Spst * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2519370Spst * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2698944Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2798944Sobrien */ 2819370Spst 2919370Spst#include <sys/cdefs.h> 3019370Spst__FBSDID("$FreeBSD: stable/11/sys/dev/ata/chipsets/ata-via.c 330897 2018-03-14 03:19:51Z eadler $"); 3119370Spst 32130803Smarcel#include <sys/param.h> 33130803Smarcel#include <sys/module.h> 3419370Spst#include <sys/systm.h> 3598944Sobrien#include <sys/kernel.h> 3698944Sobrien#include <sys/ata.h> 3798944Sobrien#include <sys/bus.h> 3898944Sobrien#include <sys/endian.h> 3998944Sobrien#include <sys/malloc.h> 4098944Sobrien#include <sys/lock.h> 4198944Sobrien#include <sys/mutex.h> 4298944Sobrien#include <sys/sema.h> 4398944Sobrien#include <sys/taskqueue.h> 4419370Spst#include <vm/uma.h> 4598944Sobrien#include <machine/stdarg.h> 4619370Spst#include <machine/resource.h> 47130803Smarcel#include <machine/bus.h> 4898944Sobrien#include <sys/rman.h> 4998944Sobrien#include <dev/pci/pcivar.h> 5098944Sobrien#include <dev/pci/pcireg.h> 5119370Spst#include <dev/ata/ata-all.h> 5298944Sobrien#include <dev/ata/ata-pci.h> 5398944Sobrien#include <ata_if.h> 5498944Sobrien 5598944Sobrien/* local prototypes */ 5619370Spststatic int ata_via_chipinit(device_t dev); 5798944Sobrienstatic int ata_via_ch_attach(device_t dev); 5819370Spststatic int ata_via_ch_detach(device_t dev); 5998944Sobrienstatic void ata_via_reset(device_t dev); 6098944Sobrienstatic int ata_via_status(device_t dev); 61130803Smarcelstatic int ata_via_old_setmode(device_t dev, int target, int mode); 6298944Sobrienstatic void ata_via_southbridge_fixup(device_t dev); 6398944Sobrienstatic int ata_via_new_setmode(device_t dev, int target, int mode); 6446283Sdfrstatic int ata_via_sata_ch_attach(device_t dev); 6598944Sobrienstatic int ata_via_sata_getrev(device_t dev, int target); 66130803Smarcelstatic int ata_via_sata_setmode(device_t dev, int target, int mode); 6719370Spststatic void ata_via_sata_reset(device_t dev); 6898944Sobrienstatic int ata_via_sata_scr_read(device_t dev, int port, int reg, 6998944Sobrien u_int32_t *result); 7098944Sobrienstatic int ata_via_sata_scr_write(device_t dev, int port, int reg, 7119370Spst u_int32_t value); 72130803Smarcelstatic int ata_via_sata_status(device_t dev); 73130803Smarcel 74130803Smarcel/* misc defines */ 75130803Smarcel#define VIA33 0 76130803Smarcel#define VIA66 1 77130803Smarcel#define VIA100 2 78130803Smarcel#define VIA133 3 79130803Smarcel 80130803Smarcel#define VIACLK 0x01 81130803Smarcel#define VIABUG 0x02 82130803Smarcel#define VIABAR 0x04 83130803Smarcel#define VIASATA 0x10 84130803Smarcel 85130803Smarcel/* 8698944Sobrien * VIA Technologies Inc. chipset support functions 8798944Sobrien */ 8898944Sobrienstatic int 8998944Sobrienata_via_probe(device_t dev) 9098944Sobrien{ 9198944Sobrien struct ata_pci_controller *ctlr = device_get_softc(dev); 9298944Sobrien static const struct ata_chip_id ids[] = 9398944Sobrien {{ ATA_VIA82C586, 0x02, VIA33, 0x00, ATA_UDMA2, "82C586B" }, 9498944Sobrien { ATA_VIA82C586, 0x00, VIA33, 0x00, ATA_WDMA2, "82C586" }, 9598944Sobrien { ATA_VIA82C596, 0x12, VIA66, VIACLK, ATA_UDMA4, "82C596B" }, 9698944Sobrien { ATA_VIA82C596, 0x00, VIA33, 0x00, ATA_UDMA2, "82C596" }, 9798944Sobrien { ATA_VIA82C686, 0x40, VIA100, VIABUG, ATA_UDMA5, "82C686B"}, 9819370Spst { ATA_VIA82C686, 0x10, VIA66, VIACLK, ATA_UDMA4, "82C686A" }, 9919370Spst { ATA_VIA82C686, 0x00, VIA33, 0x00, ATA_UDMA2, "82C686" }, 10019370Spst { ATA_VIA8231, 0x00, VIA100, VIABUG, ATA_UDMA5, "8231" }, 10119370Spst { ATA_VIA8233, 0x00, VIA100, 0x00, ATA_UDMA5, "8233" }, 10298944Sobrien { ATA_VIA8233C, 0x00, VIA100, 0x00, ATA_UDMA5, "8233C" }, 10398944Sobrien { ATA_VIA8233A, 0x00, VIA133, 0x00, ATA_UDMA6, "8233A" }, 10498944Sobrien { ATA_VIA8235, 0x00, VIA133, 0x00, ATA_UDMA6, "8235" }, 10598944Sobrien { ATA_VIA8237, 0x00, VIA133, 0x00, ATA_UDMA6, "8237" }, 10698944Sobrien { ATA_VIA8237A, 0x00, VIA133, 0x00, ATA_UDMA6, "8237A" }, 10719370Spst { ATA_VIA8237S, 0x00, VIA133, 0x00, ATA_UDMA6, "8237S" }, 10898944Sobrien { ATA_VIA8237_5372, 0x00, VIA133, 0x00, ATA_UDMA6, "8237" }, 10998944Sobrien { ATA_VIA8237_7372, 0x00, VIA133, 0x00, ATA_UDMA6, "8237" }, 110130803Smarcel { ATA_VIA8251, 0x00, VIA133, 0x00, ATA_UDMA6, "8251" }, 11198944Sobrien { ATA_VIACX700, 0x00, VIA133, VIASATA, ATA_SA150, "CX700" }, 11298944Sobrien { ATA_VIAVX800, 0x00, VIA133, VIASATA, ATA_SA150, "VX800" }, 11398944Sobrien { ATA_VIAVX855, 0x00, VIA133, 0x00, ATA_UDMA6, "VX855" }, 11498944Sobrien { ATA_VIAVX900, 0x00, VIA133, VIASATA, ATA_SA300, "VX900" }, 11598944Sobrien { 0, 0, 0, 0, 0, 0 }}; 11619370Spst static const struct ata_chip_id new_ids[] = 11719370Spst {{ ATA_VIA6410, 0x00, 0, 0x00, ATA_UDMA6, "6410" }, 11846283Sdfr { ATA_VIA6420, 0x00, 7, 0x00, ATA_SA150, "6420" }, 11946283Sdfr { ATA_VIA6421, 0x00, 6, VIABAR, ATA_SA150, "6421" }, 12019370Spst { ATA_VIA8237A, 0x00, 7, 0x00, ATA_SA150, "8237A" }, 12119370Spst { ATA_VIA8237S, 0x00, 7, 0x00, ATA_SA150, "8237S" }, 122130803Smarcel { ATA_VIA8237_5372, 0x00, 7, 0x00, ATA_SA300, "8237" }, 12319370Spst { ATA_VIA8237_7372, 0x00, 7, 0x00, ATA_SA300, "8237" }, 12419370Spst { 0, 0, 0, 0, 0, 0 }}; 12598944Sobrien 12698944Sobrien if (pci_get_vendor(dev) != ATA_VIA_ID) 12719370Spst return ENXIO; 12846283Sdfr 12946283Sdfr if (pci_get_devid(dev) == ATA_VIA82C571 || 13046283Sdfr pci_get_devid(dev) == ATA_VIACX700IDE || 131130803Smarcel pci_get_devid(dev) == ATA_VIASATAIDE || 13219370Spst pci_get_devid(dev) == ATA_VIASATAIDE2 || 13319370Spst pci_get_devid(dev) == ATA_VIASATAIDE3) { 13419370Spst if (!(ctlr->chip = ata_find_chip(dev, ids, -99))) 13519370Spst return ENXIO; 13619370Spst } 13719370Spst else { 13819370Spst if (!(ctlr->chip = ata_match_chip(dev, new_ids))) 13919370Spst return ENXIO; 14019370Spst } 14119370Spst 14219370Spst ata_set_desc(dev); 14319370Spst ctlr->chipinit = ata_via_chipinit; 14419370Spst return (BUS_PROBE_LOW_PRIORITY); 145130803Smarcel} 14619370Spst 14719370Spststatic int 14819370Spstata_via_chipinit(device_t dev) 149130803Smarcel{ 15019370Spst struct ata_pci_controller *ctlr = device_get_softc(dev); 15198944Sobrien 15219370Spst if (ata_setup_interrupt(dev, ata_generic_intr)) 15398944Sobrien return ENXIO; 15498944Sobrien 15519370Spst /* 2 SATA with "SATA registers" at PCI config space + PATA on secondary */ 15698944Sobrien if (ctlr->chip->cfg2 & VIASATA) { 15798944Sobrien ctlr->ch_attach = ata_via_sata_ch_attach; 15898944Sobrien ctlr->setmode = ata_via_sata_setmode; 15998944Sobrien ctlr->getrev = ata_via_sata_getrev; 16098944Sobrien ctlr->reset = ata_via_sata_reset; 16119370Spst return 0; 16219370Spst } 16319370Spst /* Legacy SATA/SATA+PATA with SATA registers in BAR(5). */ 16419370Spst if (ctlr->chip->max_dma >= ATA_SA150) { 16519370Spst ctlr->r_type2 = SYS_RES_IOPORT; 16619370Spst ctlr->r_rid2 = PCIR_BAR(5); 16719370Spst if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, 16819370Spst &ctlr->r_rid2, RF_ACTIVE))) { 16919370Spst ctlr->ch_attach = ata_via_ch_attach; 17019370Spst ctlr->ch_detach = ata_via_ch_detach; 17119370Spst ctlr->reset = ata_via_reset; 172130803Smarcel } 17319370Spst if (ctlr->chip->cfg2 & VIABAR) { 17419370Spst ctlr->channels = 3; 175130803Smarcel ctlr->setmode = ata_via_new_setmode; 17619370Spst } else 17719370Spst ctlr->setmode = ata_sata_setmode; 178130803Smarcel ctlr->getrev = ata_sata_getrev; 17919370Spst return 0; 18019370Spst } 181130803Smarcel 18219370Spst /* prepare for ATA-66 on the 82C686a and 82C596b */ 18319370Spst if (ctlr->chip->cfg2 & VIACLK) 184130803Smarcel pci_write_config(dev, 0x50, 0x030b030b, 4); 18519370Spst 18619370Spst /* the southbridge might need the data corruption fix */ 187130803Smarcel if (ctlr->chip->cfg2 & VIABUG) 18819370Spst ata_via_southbridge_fixup(dev); 18919370Spst 190130803Smarcel /* set fifo configuration half'n'half */ 19119370Spst pci_write_config(dev, 0x43, 19219370Spst (pci_read_config(dev, 0x43, 1) & 0x90) | 0x2a, 1); 193130803Smarcel 19419370Spst /* set status register read retry */ 19519370Spst pci_write_config(dev, 0x44, pci_read_config(dev, 0x44, 1) | 0x08, 1); 196130803Smarcel 19719370Spst /* set DMA read & end-of-sector fifo flush */ 19819370Spst pci_write_config(dev, 0x46, 199130803Smarcel (pci_read_config(dev, 0x46, 1) & 0x0c) | 0xf0, 1); 20019370Spst 20198944Sobrien /* set sector size */ 20298944Sobrien pci_write_config(dev, 0x60, DEV_BSIZE, 2); 20319370Spst pci_write_config(dev, 0x68, DEV_BSIZE, 2); 204130803Smarcel 20546283Sdfr ctlr->setmode = ata_via_old_setmode; 20619370Spst return 0; 207130803Smarcel} 20846283Sdfr 20946283Sdfrstatic int 21046283Sdfrata_via_ch_attach(device_t dev) 21146283Sdfr{ 212130803Smarcel struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 21346283Sdfr struct ata_channel *ch = device_get_softc(dev); 21446283Sdfr 21546283Sdfr /* newer SATA chips has resources in one BAR for each channel */ 216130803Smarcel if (ctlr->chip->cfg2 & VIABAR) { 21746283Sdfr struct resource *r_io; 21846283Sdfr int i, rid; 21946283Sdfr 220130803Smarcel ata_pci_dmainit(dev); 22146283Sdfr 22246283Sdfr rid = PCIR_BAR(ch->unit); 22398944Sobrien if (!(r_io = bus_alloc_resource_any(device_get_parent(dev), 22498944Sobrien SYS_RES_IOPORT, 22598944Sobrien &rid, RF_ACTIVE))) 22646283Sdfr return ENXIO; 22719370Spst 22819370Spst for (i = ATA_DATA; i <= ATA_COMMAND; i ++) { 229130803Smarcel ch->r_io[i].res = r_io; 23019370Spst ch->r_io[i].offset = i; 23119370Spst } 23246283Sdfr ch->r_io[ATA_CONTROL].res = r_io; 23319370Spst ch->r_io[ATA_CONTROL].offset = 2 + ATA_IOSIZE; 23419370Spst ch->r_io[ATA_IDX_ADDR].res = r_io; 23519370Spst ata_default_registers(dev); 236130803Smarcel for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) { 23798944Sobrien ch->r_io[i].res = ctlr->r_res1; 23898944Sobrien ch->r_io[i].offset = (i - ATA_BMCMD_PORT)+(ch->unit * ATA_BMIOSIZE); 23919370Spst } 24046283Sdfr ata_pci_hw(dev); 24146283Sdfr if (ch->unit >= 2) 24219370Spst return 0; 24319370Spst } 24419370Spst else { 24519370Spst /* setup the usual register normal pci style */ 24619370Spst if (ata_pci_ch_attach(dev)) 24719370Spst return ENXIO; 24819370Spst } 24998944Sobrien 25019370Spst ch->r_io[ATA_SSTATUS].res = ctlr->r_res2; 25119370Spst ch->r_io[ATA_SSTATUS].offset = (ch->unit << ctlr->chip->cfg1); 252130803Smarcel ch->r_io[ATA_SERROR].res = ctlr->r_res2; 253130803Smarcel ch->r_io[ATA_SERROR].offset = 0x04 + (ch->unit << ctlr->chip->cfg1); 25419370Spst ch->r_io[ATA_SCONTROL].res = ctlr->r_res2; 25519370Spst ch->r_io[ATA_SCONTROL].offset = 0x08 + (ch->unit << ctlr->chip->cfg1); 25619370Spst ch->hw.status = ata_via_status; 25719370Spst ch->flags |= ATA_NO_SLAVE; 25819370Spst ch->flags |= ATA_SATA; 25919370Spst ch->flags |= ATA_PERIODIC_POLL; 26019370Spst 261130803Smarcel ata_sata_scr_write(ch, -1, ATA_SERROR, 0xffffffff); 26219370Spst 26319370Spst return 0; 264130803Smarcel} 26598944Sobrien 26619370Spststatic int 26719370Spstata_via_ch_detach(device_t dev) 26819370Spst{ 26919370Spst struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 27019370Spst struct ata_channel *ch = device_get_softc(dev); 27119370Spst 27219370Spst /* newer SATA chips has resources in one BAR for each channel */ 27319370Spst if (ctlr->chip->cfg2 & VIABAR) { 27419370Spst int rid; 27519370Spst 27619370Spst rid = PCIR_BAR(ch->unit); 27719370Spst bus_release_resource(device_get_parent(dev), 27819370Spst SYS_RES_IOPORT, rid, ch->r_io[ATA_CONTROL].res); 27919370Spst 28019370Spst ata_pci_dmafini(dev); 28119370Spst } 28219370Spst else { 28319370Spst /* setup the usual register normal pci style */ 28419370Spst if (ata_pci_ch_detach(dev)) 28519370Spst return ENXIO; 28619370Spst } 28719370Spst 28819370Spst return 0; 28919370Spst} 29019370Spst 29119370Spststatic void 29219370Spstata_via_reset(device_t dev) 293130803Smarcel{ 29419370Spst struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 29519370Spst struct ata_channel *ch = device_get_softc(dev); 296130803Smarcel 29719370Spst if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1)) 29819370Spst ata_generic_reset(dev); 299130803Smarcel else { 30019370Spst if (ata_sata_phy_reset(dev, -1, 1)) 30119370Spst ata_generic_reset(dev); 30219370Spst else 30319370Spst ch->devices = 0; 30419370Spst } 30519370Spst} 30619370Spst 30719370Spststatic int 30819370Spstata_via_status(device_t dev) 30919370Spst{ 31019370Spst 31119370Spst ata_sata_phy_check_events(dev, -1); 31219370Spst return (ata_pci_status(dev)); 31319370Spst} 31419370Spst 31519370Spststatic int 31619370Spstata_via_new_setmode(device_t dev, int target, int mode) 31719370Spst{ 31819370Spst device_t parent = device_get_parent(dev); 31919370Spst struct ata_pci_controller *ctlr = device_get_softc(parent); 320130803Smarcel struct ata_channel *ch = device_get_softc(dev); 321130803Smarcel 32219370Spst if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1)) { 32319370Spst int piomode; 32419370Spst static const uint8_t pio_timings[] = 32519370Spst { 0xa8, 0x65, 0x65, 0x32, 0x20 }; 32619370Spst static const uint8_t dma_timings[] = 32719370Spst { 0xee, 0xe8, 0xe6, 0xe4, 0xe2, 0xe1, 0xe0 }; 32819370Spst 32919370Spst /* This chip can't do WDMA. */ 33019370Spst if (mode >= ATA_WDMA0 && mode < ATA_UDMA0) 33119370Spst mode = ATA_PIO4; 33219370Spst if (mode >= ATA_UDMA0) { 33319370Spst pci_write_config(parent, 0xb3, 33419370Spst dma_timings[mode & ATA_MODE_MASK], 1); 33519370Spst piomode = ATA_PIO4; 33619370Spst } else 33719370Spst piomode = mode; 33819370Spst pci_write_config(parent, 0xab, pio_timings[ata_mode2idx(piomode)], 1); 33919370Spst } else 34019370Spst mode = ata_sata_setmode(dev, target, mode); 34119370Spst return (mode); 34219370Spst} 34319370Spst 34419370Spststatic int 34519370Spstata_via_old_setmode(device_t dev, int target, int mode) 34619370Spst{ 34719370Spst device_t parent = device_get_parent(dev); 34819370Spst struct ata_pci_controller *ctlr = device_get_softc(parent); 34919370Spst struct ata_channel *ch = device_get_softc(dev); 35019370Spst int devno = (ch->unit << 1) + target; 35146283Sdfr int reg = 0x53 - devno; 35219370Spst int piomode; 35346283Sdfr static const uint8_t timings[] = 35419370Spst { 0xa8, 0x65, 0x42, 0x22, 0x20, 0xa8, 0x22, 0x20 }; 35546283Sdfr static const uint8_t modes[][7] = { 35619370Spst { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */ 35719370Spst { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */ 35819370Spst { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */ 35946283Sdfr { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 } }; /* VIA ATA133 */ 36019370Spst 36119370Spst mode = min(mode, ctlr->chip->max_dma); 36219370Spst /* Set UDMA timings */ 36319370Spst if (mode >= ATA_UDMA0) { 364130803Smarcel pci_write_config(parent, reg, 36519370Spst modes[ctlr->chip->cfg1][mode & ATA_MODE_MASK], 1); 36619370Spst piomode = ATA_PIO4; 36719370Spst } else { 36819370Spst pci_write_config(parent, reg, 0x8b, 1); 36919370Spst piomode = mode; 37019370Spst } 37119370Spst /* Set WDMA/PIO timings */ 37219370Spst pci_write_config(parent, reg - 0x08,timings[ata_mode2idx(piomode)], 1); 37319370Spst return (mode); 37419370Spst} 37519370Spst 37619370Spststatic void 37719370Spstata_via_southbridge_fixup(device_t dev) 37819370Spst{ 37946283Sdfr device_t *children; 38046283Sdfr int nchildren, i; 38146283Sdfr 38246283Sdfr if (device_get_children(device_get_parent(dev), &children, &nchildren)) 38319370Spst return; 38419370Spst 38519370Spst for (i = 0; i < nchildren; i++) { 38619370Spst if (pci_get_devid(children[i]) == ATA_VIA8363 || 38719370Spst pci_get_devid(children[i]) == ATA_VIA8371 || 38819370Spst pci_get_devid(children[i]) == ATA_VIA8662 || 38919370Spst pci_get_devid(children[i]) == ATA_VIA8361) { 39019370Spst u_int8_t reg76 = pci_read_config(children[i], 0x76, 1); 39119370Spst 39219370Spst if ((reg76 & 0xf0) != 0xd0) { 39319370Spst device_printf(dev, 39419370Spst "Correcting VIA config for southbridge data corruption bug\n"); 39519370Spst pci_write_config(children[i], 0x75, 0x80, 1); 39619370Spst pci_write_config(children[i], 0x76, (reg76 & 0x0f) | 0xd0, 1); 39719370Spst } 39819370Spst break; 39919370Spst } 40019370Spst } 40119370Spst free(children, M_TEMP); 40219370Spst} 40319370Spst 40419370Spststatic int 40519370Spstata_via_sata_ch_attach(device_t dev) 40619370Spst{ 40719370Spst struct ata_channel *ch = device_get_softc(dev); 40819370Spst 40919370Spst if (ata_pci_ch_attach(dev)) 41019370Spst return ENXIO; 41119370Spst if (ch->unit == 0) { 41219370Spst ch->hw.status = ata_via_sata_status; 41346283Sdfr ch->hw.pm_read = ata_via_sata_scr_read; 41446283Sdfr ch->hw.pm_write = ata_via_sata_scr_write; 41546283Sdfr ch->flags |= ATA_PERIODIC_POLL; 41646283Sdfr ch->flags |= ATA_SATA; 41746283Sdfr ata_sata_scr_write(ch, 0, ATA_SERROR, 0xffffffff); 41898944Sobrien ata_sata_scr_write(ch, 1, ATA_SERROR, 0xffffffff); 41998944Sobrien } 42098944Sobrien return (0); 42198944Sobrien} 42298944Sobrien 42398944Sobrienstatic int 42446283Sdfrata_via_sata_getrev(device_t dev, int target) 42546283Sdfr{ 42619370Spst device_t parent = device_get_parent(dev); 42719370Spst struct ata_channel *ch = device_get_softc(dev); 42819370Spst 42919370Spst if (ch->unit == 0) { 43019370Spst if (pci_read_config(parent, 0xa0 + target, 1) & 0x10) 43119370Spst return (2); 43219370Spst else 43319370Spst return (1); 43446283Sdfr } 43519370Spst return (0); 43619370Spst} 43719370Spst 43819370Spststatic int 43919370Spstata_via_sata_setmode(device_t dev, int target, int mode) 44046283Sdfr{ 44146283Sdfr struct ata_channel *ch = device_get_softc(dev); 44246283Sdfr 44346283Sdfr if (ch->unit == 0) 44419370Spst return (mode); 44519370Spst return (ata_via_old_setmode(dev, target, mode)); 44619370Spst} 44719370Spst 44819370Spststatic void 44919370Spstata_via_sata_reset(device_t dev) 45019370Spst{ 45119370Spst struct ata_channel *ch = device_get_softc(dev); 45298944Sobrien int devs; 45398944Sobrien 45498944Sobrien if (ch->unit == 0) { 45598944Sobrien devs = ata_sata_phy_reset(dev, 0, 0); 45619370Spst DELAY(10000); 45798944Sobrien devs += ata_sata_phy_reset(dev, 1, 0); 45846283Sdfr } else 45998944Sobrien devs = 1; 46098944Sobrien if (devs) 46119370Spst ata_generic_reset(dev); 46298944Sobrien else 46346283Sdfr ch->devices = 0; 46446283Sdfr} 465130803Smarcel 46646283Sdfrstatic int 467130803Smarcelata_via_sata_scr_read(device_t dev, int port, int reg, u_int32_t *result) 46819370Spst{ 46946283Sdfr device_t parent; 47046283Sdfr uint32_t val; 47146283Sdfr 47219370Spst parent = device_get_parent(dev); 47319370Spst port = (port == 1) ? 1 : 0; 47419370Spst switch (reg) { 47519370Spst case ATA_SSTATUS: 47698944Sobrien val = pci_read_config(parent, 0xa0 + port, 1); 47798944Sobrien *result = val & 0x03; 47898944Sobrien if (*result != ATA_SS_DET_NO_DEVICE) { 47998944Sobrien if (val & 0x04) 48019370Spst *result |= ATA_SS_IPM_PARTIAL; 48119370Spst else if (val & 0x08) 48298944Sobrien *result |= ATA_SS_IPM_SLUMBER; 48398944Sobrien else 48419370Spst *result |= ATA_SS_IPM_ACTIVE; 48598944Sobrien if (val & 0x10) 48698944Sobrien *result |= ATA_SS_SPD_GEN2; 48719370Spst else 48898944Sobrien *result |= ATA_SS_SPD_GEN1; 48919370Spst } 49098944Sobrien break; 49198944Sobrien case ATA_SERROR: 49219370Spst *result = pci_read_config(parent, 0xa8 + port * 4, 4); 49398944Sobrien break; 494130803Smarcel case ATA_SCONTROL: 49598944Sobrien val = pci_read_config(parent, 0xa4 + port, 1); 49698944Sobrien *result = 0; 49798944Sobrien if (val & 0x01) 49898944Sobrien *result |= ATA_SC_DET_RESET; 49998944Sobrien if (val & 0x02) 50019370Spst *result |= ATA_SC_DET_DISABLE; 50198944Sobrien if (val & 0x04) 50298944Sobrien *result |= ATA_SC_IPM_DIS_PARTIAL; 50319370Spst if (val & 0x08) 50419370Spst *result |= ATA_SC_IPM_DIS_SLUMBER; 50598944Sobrien break; 50698944Sobrien default: 50719370Spst return (EINVAL); 50898944Sobrien } 50998944Sobrien return (0); 51019370Spst} 511130803Smarcel 51219370Spststatic int 51398944Sobrienata_via_sata_scr_write(device_t dev, int port, int reg, u_int32_t value) 51419370Spst{ 51598944Sobrien device_t parent; 51646283Sdfr uint32_t val; 51746283Sdfr 51819370Spst parent = device_get_parent(dev); 51919370Spst port = (port == 1) ? 1 : 0; 52019370Spst switch (reg) { 52119370Spst case ATA_SERROR: 52298944Sobrien pci_write_config(parent, 0xa8 + port * 4, value, 4); 52319370Spst break; 52419370Spst case ATA_SCONTROL: 52519370Spst val = 0; 52646283Sdfr if (value & ATA_SC_DET_RESET) 52719370Spst val |= 0x01; 52898944Sobrien if (value & ATA_SC_DET_DISABLE) 52919370Spst val |= 0x02; 53019370Spst if (value & ATA_SC_IPM_DIS_PARTIAL) 53119370Spst val |= 0x04; 53219370Spst if (value & ATA_SC_IPM_DIS_SLUMBER) 53319370Spst val |= 0x08; 53419370Spst pci_write_config(parent, 0xa4 + port, val, 1); 53519370Spst break; 53619370Spst default: 53719370Spst return (EINVAL); 53819370Spst } 53998944Sobrien return (0); 54098944Sobrien} 54198944Sobrien 54219370Spststatic int 54398944Sobrienata_via_sata_status(device_t dev) 54498944Sobrien{ 54598944Sobrien 54698944Sobrien ata_sata_phy_check_events(dev, 0); 54798944Sobrien ata_sata_phy_check_events(dev, 1); 54819370Spst return (ata_pci_status(dev)); 549130803Smarcel} 55098944Sobrien 55198944SobrienATA_DECLARE_DRIVER(ata_via); 55298944Sobrien