Path: blob/main/sys/dev/ata/chipsets/ata-serverworks.c
39537 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_serverworks_chipinit(device_t dev);53static int ata_serverworks_ch_attach(device_t dev);54static int ata_serverworks_ch_detach(device_t dev);55static void ata_serverworks_tf_read(struct ata_request *request);56static void ata_serverworks_tf_write(struct ata_request *request);57static int ata_serverworks_setmode(device_t dev, int target, int mode);58static void ata_serverworks_sata_reset(device_t dev);59static int ata_serverworks_status(device_t dev);6061/* misc defines */62#define SWKS_33 063#define SWKS_66 164#define SWKS_100 265#define SWKS_MIO 36667/*68* ServerWorks chipset support functions69*/70static int71ata_serverworks_probe(device_t dev)72{73struct ata_pci_controller *ctlr = device_get_softc(dev);74static const struct ata_chip_id ids[] =75{{ ATA_ROSB4, 0x00, SWKS_33, 0, ATA_WDMA2, "ROSB4" },76{ ATA_CSB5, 0x92, SWKS_100, 0, ATA_UDMA5, "CSB5" },77{ ATA_CSB5, 0x00, SWKS_66, 0, ATA_UDMA4, "CSB5" },78{ ATA_CSB6, 0x00, SWKS_100, 0, ATA_UDMA5, "CSB6" },79{ ATA_CSB6_1, 0x00, SWKS_66, 0, ATA_UDMA4, "CSB6" },80{ ATA_HT1000, 0x00, SWKS_100, 0, ATA_UDMA5, "HT1000" },81{ ATA_HT1000_S1, 0x00, SWKS_MIO, 4, ATA_SA150, "HT1000" },82{ ATA_HT1000_S2, 0x00, SWKS_MIO, 4, ATA_SA150, "HT1000" },83{ ATA_K2, 0x00, SWKS_MIO, 4, ATA_SA150, "K2" },84{ ATA_FRODO4, 0x00, SWKS_MIO, 4, ATA_SA150, "Frodo4" },85{ ATA_FRODO8, 0x00, SWKS_MIO, 8, ATA_SA150, "Frodo8" },86{ 0, 0, 0, 0, 0, 0}};8788if (pci_get_vendor(dev) != ATA_SERVERWORKS_ID)89return ENXIO;9091if (!(ctlr->chip = ata_match_chip(dev, ids)))92return ENXIO;9394ata_set_desc(dev);95ctlr->chipinit = ata_serverworks_chipinit;96return (BUS_PROBE_LOW_PRIORITY);97}9899static int100ata_serverworks_status(device_t dev)101{102struct ata_channel *ch = device_get_softc(dev);103struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));104105/*106* Check if this interrupt belongs to our channel.107*/108if (!(ATA_INL(ctlr->r_res2, 0x1f80) & (1 << ch->unit)))109return (0);110111/*112* We need to do a 4-byte read on the status reg before the values113* will report correctly114*/115116ATA_IDX_INL(ch,ATA_STATUS);117118return ata_pci_status(dev);119}120121static int122ata_serverworks_chipinit(device_t dev)123{124struct ata_pci_controller *ctlr = device_get_softc(dev);125126if (ata_setup_interrupt(dev, ata_generic_intr))127return ENXIO;128129if (ctlr->chip->cfg1 == SWKS_MIO) {130ctlr->r_type2 = SYS_RES_MEMORY;131ctlr->r_rid2 = PCIR_BAR(5);132if (!(ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,133&ctlr->r_rid2, RF_ACTIVE)))134return ENXIO;135136ctlr->channels = ctlr->chip->cfg2;137ctlr->ch_attach = ata_serverworks_ch_attach;138ctlr->ch_detach = ata_serverworks_ch_detach;139ctlr->setmode = ata_sata_setmode;140ctlr->getrev = ata_sata_getrev;141ctlr->reset = ata_serverworks_sata_reset;142return 0;143}144else if (ctlr->chip->cfg1 == SWKS_33) {145device_t *children;146int nchildren, i;147148/* locate the ISA part in the southbridge and enable UDMA33 */149if (!device_get_children(device_get_parent(dev), &children,&nchildren)){150for (i = 0; i < nchildren; i++) {151if (pci_get_devid(children[i]) == ATA_ROSB4_ISA) {152pci_write_config(children[i], 0x64,153(pci_read_config(children[i], 0x64, 4) &154~0x00002000) | 0x00004000, 4);155break;156}157}158free(children, M_TEMP);159}160}161else {162pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x40) |163((ctlr->chip->cfg1 == SWKS_100) ? 0x03 : 0x02), 1);164}165ctlr->setmode = ata_serverworks_setmode;166return 0;167}168169static int170ata_serverworks_ch_attach(device_t dev)171{172struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));173struct ata_channel *ch = device_get_softc(dev);174int ch_offset;175int i;176177ch_offset = ch->unit * 0x100;178179for (i = ATA_DATA; i < ATA_MAX_RES; i++)180ch->r_io[i].res = ctlr->r_res2;181182/* setup ATA registers */183ch->r_io[ATA_DATA].offset = ch_offset + 0x00;184ch->r_io[ATA_FEATURE].offset = ch_offset + 0x04;185ch->r_io[ATA_COUNT].offset = ch_offset + 0x08;186ch->r_io[ATA_SECTOR].offset = ch_offset + 0x0c;187ch->r_io[ATA_CYL_LSB].offset = ch_offset + 0x10;188ch->r_io[ATA_CYL_MSB].offset = ch_offset + 0x14;189ch->r_io[ATA_DRIVE].offset = ch_offset + 0x18;190ch->r_io[ATA_COMMAND].offset = ch_offset + 0x1c;191ch->r_io[ATA_CONTROL].offset = ch_offset + 0x20;192ata_default_registers(dev);193194/* setup DMA registers */195ch->r_io[ATA_BMCMD_PORT].offset = ch_offset + 0x30;196ch->r_io[ATA_BMSTAT_PORT].offset = ch_offset + 0x32;197ch->r_io[ATA_BMDTP_PORT].offset = ch_offset + 0x34;198199/* setup SATA registers */200ch->r_io[ATA_SSTATUS].offset = ch_offset + 0x40;201ch->r_io[ATA_SERROR].offset = ch_offset + 0x44;202ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x48;203204ch->flags |= ATA_NO_SLAVE | ATA_SATA | ATA_KNOWN_PRESENCE;205ata_pci_hw(dev);206ch->hw.tf_read = ata_serverworks_tf_read;207ch->hw.tf_write = ata_serverworks_tf_write;208209if (ctlr->chip->chipid == ATA_K2) {210/*211* Set SICR registers to turn off waiting for a status message212* before sending FIS. Values obtained from the Darwin driver.213*/214215ATA_OUTL(ctlr->r_res2, ch_offset + 0x80,216ATA_INL(ctlr->r_res2, ch_offset + 0x80) & ~0x00040000);217ATA_OUTL(ctlr->r_res2, ch_offset + 0x88, 0);218219/*220* Some controllers have a bug where they will send the command221* to the drive before seeing a DMA start, and then can begin222* receiving data before the DMA start arrives. The controller223* will then become confused and either corrupt the data or crash.224* Remedy this by starting DMA before sending the drive command.225*/226227ch->flags |= ATA_DMA_BEFORE_CMD;228229/*230* The status register must be read as a long to fill the other231* registers.232*/233234ch->hw.status = ata_serverworks_status;235ch->flags |= ATA_STATUS_IS_LONG;236}237238/* chip does not reliably do 64K DMA transfers */239ch->dma.max_iosize = 64 * DEV_BSIZE;240241ata_pci_dmainit(dev);242243return 0;244}245246static int247ata_serverworks_ch_detach(device_t dev)248{249250ata_pci_dmafini(dev);251return (0);252}253254static void255ata_serverworks_tf_read(struct ata_request *request)256{257struct ata_channel *ch = device_get_softc(request->parent);258259if (request->flags & ATA_R_48BIT) {260u_int16_t temp;261262request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT);263temp = ATA_IDX_INW(ch, ATA_SECTOR);264request->u.ata.lba = (u_int64_t)(temp & 0x00ff) |265((u_int64_t)(temp & 0xff00) << 24);266temp = ATA_IDX_INW(ch, ATA_CYL_LSB);267request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 8) |268((u_int64_t)(temp & 0xff00) << 32);269temp = ATA_IDX_INW(ch, ATA_CYL_MSB);270request->u.ata.lba |= ((u_int64_t)(temp & 0x00ff) << 16) |271((u_int64_t)(temp & 0xff00) << 40);272}273else {274request->u.ata.count = ATA_IDX_INW(ch, ATA_COUNT) & 0x00ff;275request->u.ata.lba = (ATA_IDX_INW(ch, ATA_SECTOR) & 0x00ff) |276((ATA_IDX_INW(ch, ATA_CYL_LSB) & 0x00ff) << 8) |277((ATA_IDX_INW(ch, ATA_CYL_MSB) & 0x00ff) << 16) |278((ATA_IDX_INW(ch, ATA_DRIVE) & 0xf) << 24);279}280}281282static void283ata_serverworks_tf_write(struct ata_request *request)284{285struct ata_channel *ch = device_get_softc(request->parent);286287if (request->flags & ATA_R_48BIT) {288ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);289ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);290ATA_IDX_OUTW(ch, ATA_SECTOR, ((request->u.ata.lba >> 16) & 0xff00) |291(request->u.ata.lba & 0x00ff));292ATA_IDX_OUTW(ch, ATA_CYL_LSB, ((request->u.ata.lba >> 24) & 0xff00) |293((request->u.ata.lba >> 8) & 0x00ff));294ATA_IDX_OUTW(ch, ATA_CYL_MSB, ((request->u.ata.lba >> 32) & 0xff00) |295((request->u.ata.lba >> 16) & 0x00ff));296ATA_IDX_OUTW(ch, ATA_DRIVE, ATA_D_LBA | ATA_DEV(request->unit));297}298else {299ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);300ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);301ATA_IDX_OUTW(ch, ATA_SECTOR, request->u.ata.lba);302ATA_IDX_OUTW(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);303ATA_IDX_OUTW(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);304ATA_IDX_OUTW(ch, ATA_DRIVE,305ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) |306((request->u.ata.lba >> 24) & 0x0f));307}308}309310static int311ata_serverworks_setmode(device_t dev, int target, int mode)312{313device_t parent = device_get_parent(dev);314struct ata_pci_controller *ctlr = device_get_softc(parent);315struct ata_channel *ch = device_get_softc(dev);316int devno = (ch->unit << 1) + target;317int offset = (devno ^ 0x01) << 3;318int piomode;319static const uint8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };320static const uint8_t dmatimings[] = { 0x77, 0x21, 0x20 };321322mode = min(mode, ctlr->chip->max_dma);323if (mode >= ATA_UDMA0) {324/* Set UDMA mode, enable UDMA, set WDMA2/PIO4 */325pci_write_config(parent, 0x56,326(pci_read_config(parent, 0x56, 2) &327~(0xf << (devno << 2))) |328((mode & ATA_MODE_MASK) << (devno << 2)), 2);329pci_write_config(parent, 0x54,330pci_read_config(parent, 0x54, 1) |331(0x01 << devno), 1);332pci_write_config(parent, 0x44,333(pci_read_config(parent, 0x44, 4) &334~(0xff << offset)) |335(dmatimings[2] << offset), 4);336piomode = ATA_PIO4;337} else if (mode >= ATA_WDMA0) {338/* Disable UDMA, set WDMA mode and timings, calculate PIO. */339pci_write_config(parent, 0x54,340pci_read_config(parent, 0x54, 1) &341~(0x01 << devno), 1);342pci_write_config(parent, 0x44,343(pci_read_config(parent, 0x44, 4) &344~(0xff << offset)) |345(dmatimings[mode & ATA_MODE_MASK] << offset), 4);346piomode = (mode == ATA_WDMA0) ? ATA_PIO0 :347(mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4;348} else {349/* Disable UDMA, set requested PIO. */350pci_write_config(parent, 0x54,351pci_read_config(parent, 0x54, 1) &352~(0x01 << devno), 1);353piomode = mode;354}355/* Set PIO mode and timings, calculated above. */356if (ctlr->chip->cfg1 != SWKS_33) {357pci_write_config(parent, 0x4a,358(pci_read_config(parent, 0x4a, 2) &359~(0xf << (devno << 2))) |360((piomode - ATA_PIO0) << (devno<<2)),2);361}362pci_write_config(parent, 0x40,363(pci_read_config(parent, 0x40, 4) &364~(0xff << offset)) |365(piotimings[ata_mode2idx(piomode)] << offset), 4);366return (mode);367}368369static void370ata_serverworks_sata_reset(device_t dev)371{372struct ata_channel *ch = device_get_softc(dev);373374if (ata_sata_phy_reset(dev, -1, 0))375ata_generic_reset(dev);376else377ch->devices = 0;378}379380ATA_DECLARE_DRIVER(ata_serverworks);381382383