Path: blob/main/sys/dev/ata/chipsets/ata-siliconimage.c
39536 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 1998 - 2008 Søren Schmidt <[email protected]>4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer,11* without modification, immediately at the beginning of the file.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR17* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES18* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.19* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,20* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT21* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,22* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY23* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF25* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.26*/2728#include <sys/param.h>29#include <sys/module.h>30#include <sys/systm.h>31#include <sys/kernel.h>32#include <sys/ata.h>33#include <sys/bus.h>34#include <sys/endian.h>35#include <sys/malloc.h>36#include <sys/lock.h>37#include <sys/mutex.h>38#include <sys/sema.h>39#include <sys/stdarg.h>40#include <sys/taskqueue.h>41#include <vm/uma.h>42#include <machine/resource.h>43#include <machine/bus.h>44#include <sys/rman.h>45#include <dev/pci/pcivar.h>46#include <dev/pci/pcireg.h>47#include <dev/ata/ata-all.h>48#include <dev/ata/ata-pci.h>49#include <ata_if.h>5051/* local prototypes */52static int ata_cmd_ch_attach(device_t dev);53static int ata_cmd_status(device_t dev);54static int ata_cmd_setmode(device_t dev, int target, int mode);55static int ata_sii_ch_attach(device_t dev);56static int ata_sii_ch_detach(device_t dev);57static int ata_sii_status(device_t dev);58static void ata_sii_reset(device_t dev);59static int ata_sii_setmode(device_t dev, int target, int mode);6061/* misc defines */62#define SII_MEMIO 163#define SII_INTR 0x0164#define SII_SETCLK 0x0265#define SII_BUG 0x0466#define SII_4CH 0x086768/*69* Silicon Image Inc. (SiI) (former CMD) chipset support functions70*/71static int72ata_sii_probe(device_t dev)73{74struct ata_pci_controller *ctlr = device_get_softc(dev);75static const struct ata_chip_id ids[] =76{{ ATA_SII3114, 0x00, SII_MEMIO, SII_4CH, ATA_SA150, "3114" },77{ ATA_SII3512, 0x02, SII_MEMIO, 0, ATA_SA150, "3512" },78{ ATA_SII3112, 0x02, SII_MEMIO, 0, ATA_SA150, "3112" },79{ ATA_SII3112_1, 0x02, SII_MEMIO, 0, ATA_SA150, "3112" },80{ ATA_SII3512, 0x00, SII_MEMIO, SII_BUG, ATA_SA150, "3512" },81{ ATA_SII3112, 0x00, SII_MEMIO, SII_BUG, ATA_SA150, "3112" },82{ ATA_SII3112_1, 0x00, SII_MEMIO, SII_BUG, ATA_SA150, "3112" },83{ ATA_SII0680, 0x00, SII_MEMIO, SII_SETCLK, ATA_UDMA6, "680" },84{ ATA_CMD649, 0x00, 0, SII_INTR, ATA_UDMA5, "(CMD) 649" },85{ ATA_CMD648, 0x00, 0, SII_INTR, ATA_UDMA4, "(CMD) 648" },86{ ATA_CMD646, 0x07, 0, 0, ATA_UDMA2, "(CMD) 646U2" },87{ ATA_CMD646, 0x00, 0, 0, ATA_WDMA2, "(CMD) 646" },88{ 0, 0, 0, 0, 0, 0}};8990if (pci_get_vendor(dev) != ATA_SILICON_IMAGE_ID)91return ENXIO;9293if (!(ctlr->chip = ata_match_chip(dev, ids)))94return ENXIO;9596ata_set_desc(dev);97ctlr->chipinit = ata_sii_chipinit;98return (BUS_PROBE_LOW_PRIORITY);99}100101int102ata_sii_chipinit(device_t dev)103{104struct ata_pci_controller *ctlr = device_get_softc(dev);105106if (ata_setup_interrupt(dev, ata_generic_intr))107return ENXIO;108109switch (ctlr->chip->cfg1) {110case SII_MEMIO:111ctlr->r_type2 = SYS_RES_MEMORY;112ctlr->r_rid2 = PCIR_BAR(5);113if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,114&ctlr->r_rid2, RF_ACTIVE))){115if (ctlr->chip->chipid != ATA_SII0680 ||116(pci_read_config(dev, 0x8a, 1) & 1))117return ENXIO;118}119120if (ctlr->chip->cfg2 & SII_SETCLK) {121if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)122pci_write_config(dev, 0x8a,123(pci_read_config(dev, 0x8a, 1) & 0xcf)|0x10,1);124if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10)125device_printf(dev, "%s could not set ATA133 clock\n",126ctlr->chip->text);127}128129/* if we have 4 channels enable the second set */130if (ctlr->chip->cfg2 & SII_4CH) {131ATA_OUTL(ctlr->r_res2, 0x0200, 0x00000002);132ctlr->channels = 4;133}134135/* dont block interrupts from any channel */136pci_write_config(dev, 0x48,137(pci_read_config(dev, 0x48, 4) & ~0x03c00000), 4);138139/* enable PCI interrupt as BIOS might not */140pci_write_config(dev, 0x8a, (pci_read_config(dev, 0x8a, 1) & 0x3f), 1);141142if (ctlr->r_res2) {143ctlr->ch_attach = ata_sii_ch_attach;144ctlr->ch_detach = ata_sii_ch_detach;145}146147if (ctlr->chip->max_dma >= ATA_SA150) {148ctlr->reset = ata_sii_reset;149ctlr->setmode = ata_sata_setmode;150ctlr->getrev = ata_sata_getrev;151}152else153ctlr->setmode = ata_sii_setmode;154break;155156default:157if ((pci_read_config(dev, 0x51, 1) & 0x08) != 0x08) {158device_printf(dev, "HW has secondary channel disabled\n");159ctlr->channels = 1;160}161162/* enable interrupt as BIOS might not */163pci_write_config(dev, 0x71, 0x01, 1);164165ctlr->ch_attach = ata_cmd_ch_attach;166ctlr->ch_detach = ata_pci_ch_detach;167ctlr->setmode = ata_cmd_setmode;168break;169}170return 0;171}172173static int174ata_cmd_ch_attach(device_t dev)175{176struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));177struct ata_channel *ch = device_get_softc(dev);178179/* setup the usual register normal pci style */180if (ata_pci_ch_attach(dev))181return ENXIO;182183if (ctlr->chip->cfg2 & SII_INTR)184ch->hw.status = ata_cmd_status;185186ch->flags |= ATA_NO_ATAPI_DMA;187188return 0;189}190191static int192ata_cmd_status(device_t dev)193{194struct ata_channel *ch = device_get_softc(dev);195u_int8_t reg71;196197if (((reg71 = pci_read_config(device_get_parent(dev), 0x71, 1)) &198(ch->unit ? 0x08 : 0x04))) {199pci_write_config(device_get_parent(dev), 0x71,200reg71 & ~(ch->unit ? 0x04 : 0x08), 1);201return ata_pci_status(dev);202}203return 0;204}205206static int207ata_cmd_setmode(device_t dev, int target, int mode)208{209device_t parent = device_get_parent(dev);210struct ata_pci_controller *ctlr = device_get_softc(parent);211struct ata_channel *ch = device_get_softc(dev);212int devno = (ch->unit << 1) + target;213int treg = 0x54 + ((devno < 3) ? (devno << 1) : 7);214int ureg = ch->unit ? 0x7b : 0x73;215int piomode;216static const uint8_t piotimings[] =217{ 0xa9, 0x57, 0x44, 0x32, 0x3f, 0x87, 0x32, 0x3f };218static const uint8_t udmatimings[][2] =219{ { 0x31, 0xc2 }, { 0x21, 0x82 }, { 0x11, 0x42 },220{ 0x25, 0x8a }, { 0x15, 0x4a }, { 0x05, 0x0a } };221222mode = min(mode, ctlr->chip->max_dma);223if (mode >= ATA_UDMA0) {224u_int8_t umode = pci_read_config(parent, ureg, 1);225226umode &= ~(target == 0 ? 0x35 : 0xca);227umode |= udmatimings[mode & ATA_MODE_MASK][target];228pci_write_config(parent, ureg, umode, 1);229piomode = ATA_PIO4;230} else {231pci_write_config(parent, ureg,232pci_read_config(parent, ureg, 1) &233~(target == 0 ? 0x35 : 0xca), 1);234piomode = mode;235}236pci_write_config(parent, treg, piotimings[ata_mode2idx(piomode)], 1);237return (mode);238}239240static int241ata_sii_ch_attach(device_t dev)242{243struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));244struct ata_channel *ch = device_get_softc(dev);245int unit01 = (ch->unit & 1), unit10 = (ch->unit & 2);246int i;247248for (i = ATA_DATA; i <= ATA_COMMAND; i++) {249ch->r_io[i].res = ctlr->r_res2;250ch->r_io[i].offset = 0x80 + i + (unit01 << 6) + (unit10 << 8);251}252ch->r_io[ATA_CONTROL].res = ctlr->r_res2;253ch->r_io[ATA_CONTROL].offset = 0x8a + (unit01 << 6) + (unit10 << 8);254ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;255ata_default_registers(dev);256257ch->r_io[ATA_BMCMD_PORT].res = ctlr->r_res2;258ch->r_io[ATA_BMCMD_PORT].offset = 0x00 + (unit01 << 3) + (unit10 << 8);259ch->r_io[ATA_BMSTAT_PORT].res = ctlr->r_res2;260ch->r_io[ATA_BMSTAT_PORT].offset = 0x02 + (unit01 << 3) + (unit10 << 8);261ch->r_io[ATA_BMDTP_PORT].res = ctlr->r_res2;262ch->r_io[ATA_BMDTP_PORT].offset = 0x04 + (unit01 << 3) + (unit10 << 8);263264if (ctlr->chip->max_dma >= ATA_SA150) {265ch->r_io[ATA_SSTATUS].res = ctlr->r_res2;266ch->r_io[ATA_SSTATUS].offset = 0x104 + (unit01 << 7) + (unit10 << 8);267ch->r_io[ATA_SERROR].res = ctlr->r_res2;268ch->r_io[ATA_SERROR].offset = 0x108 + (unit01 << 7) + (unit10 << 8);269ch->r_io[ATA_SCONTROL].res = ctlr->r_res2;270ch->r_io[ATA_SCONTROL].offset = 0x100 + (unit01 << 7) + (unit10 << 8);271ch->flags |= ATA_NO_SLAVE;272ch->flags |= ATA_SATA;273ch->flags |= ATA_KNOWN_PRESENCE;274275/* enable PHY state change interrupt */276ATA_OUTL(ctlr->r_res2, 0x148 + (unit01 << 7) + (unit10 << 8),(1 << 16));277}278279if (ctlr->chip->cfg2 & SII_BUG) {280/* work around errata in early chips */281ch->dma.boundary = 8192;282ch->dma.segsize = 15 * DEV_BSIZE;283}284285ata_pci_hw(dev);286ch->hw.status = ata_sii_status;287if (ctlr->chip->cfg2 & SII_SETCLK)288ch->flags |= ATA_CHECKS_CABLE;289290ata_pci_dmainit(dev);291292return 0;293}294295static int296ata_sii_ch_detach(device_t dev)297{298299ata_pci_dmafini(dev);300return (0);301}302303static int304ata_sii_status(device_t dev)305{306struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));307struct ata_channel *ch = device_get_softc(dev);308int offset0 = ((ch->unit & 1) << 3) + ((ch->unit & 2) << 8);309int offset1 = ((ch->unit & 1) << 6) + ((ch->unit & 2) << 8);310311/* do we have any PHY events ? */312if (ctlr->chip->max_dma >= ATA_SA150 &&313(ATA_INL(ctlr->r_res2, 0x10 + offset0) & 0x00000010))314ata_sata_phy_check_events(dev, -1);315316if (ATA_INL(ctlr->r_res2, 0xa0 + offset1) & 0x00000800)317return ata_pci_status(dev);318else319return 0;320}321322static void323ata_sii_reset(device_t dev)324{325struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));326struct ata_channel *ch = device_get_softc(dev);327int offset = ((ch->unit & 1) << 7) + ((ch->unit & 2) << 8);328uint32_t val;329330/* Apply R_ERR on DMA activate FIS errata workaround. */331val = ATA_INL(ctlr->r_res2, 0x14c + offset);332if ((val & 0x3) == 0x1)333ATA_OUTL(ctlr->r_res2, 0x14c + offset, val & ~0x3);334335if (ata_sata_phy_reset(dev, -1, 1))336ata_generic_reset(dev);337else338ch->devices = 0;339}340341static int342ata_sii_setmode(device_t dev, int target, int mode)343{344device_t parent = device_get_parent(dev);345struct ata_pci_controller *ctlr = device_get_softc(parent);346struct ata_channel *ch = device_get_softc(dev);347int rego = (ch->unit << 4) + (target << 1);348int mreg = ch->unit ? 0x84 : 0x80;349int mask = 0x03 << (target << 2);350int mval = pci_read_config(parent, mreg, 1) & ~mask;351int piomode;352u_int8_t preg = 0xa4 + rego;353u_int8_t dreg = 0xa8 + rego;354u_int8_t ureg = 0xac + rego;355static const uint16_t piotimings[] =356{ 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };357static const uint16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 };358static const uint8_t udmatimings[] =359{ 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 };360361mode = min(mode, ctlr->chip->max_dma);362363if (ctlr->chip->cfg2 & SII_SETCLK) {364if (ata_dma_check_80pin && mode > ATA_UDMA2 &&365(pci_read_config(parent, 0x79, 1) &366(ch->unit ? 0x02 : 0x01))) {367ata_print_cable(dev, "controller");368mode = ATA_UDMA2;369}370}371if (mode >= ATA_UDMA0) {372pci_write_config(parent, mreg,373mval | (0x03 << (target << 2)), 1);374pci_write_config(parent, ureg,375(pci_read_config(parent, ureg, 1) & ~0x3f) |376udmatimings[mode & ATA_MODE_MASK], 1);377piomode = ATA_PIO4;378} else if (mode >= ATA_WDMA0) {379pci_write_config(parent, mreg,380mval | (0x02 << (target << 2)), 1);381pci_write_config(parent, dreg, dmatimings[mode & ATA_MODE_MASK], 2);382piomode = (mode == ATA_WDMA0) ? ATA_PIO0 :383(mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4;384} else {385pci_write_config(parent, mreg,386mval | (0x01 << (target << 2)), 1);387piomode = mode;388}389pci_write_config(parent, preg, piotimings[ata_mode2idx(piomode)], 2);390return (mode);391}392393ATA_DECLARE_DRIVER(ata_sii);394395396