From 81b7fefb3ad9fade7def74fd91f6cf9833274b31 Mon Sep 17 00:00:00 2001 From: christos Date: Sun, 20 Sep 2009 01:09:24 +0000 Subject: [PATCH] PR/42100: Dave J. Barnes: Support for old toshiba PICCOLO IDE controllers. --- sys/dev/pci/files.pci | 7 +- sys/dev/pci/pcidevs | 7 +- sys/dev/pci/pciide_piccolo_reg.h | 82 ++++++++++ sys/dev/pci/toshide.c | 271 +++++++++++++++++++++++++++++++ 4 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 sys/dev/pci/pciide_piccolo_reg.h create mode 100644 sys/dev/pci/toshide.c diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 8b34cfe8ca18..1897e19de01c 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $NetBSD: files.pci,v 1.319 2009/09/06 17:25:56 sborrill Exp $ +# $NetBSD: files.pci,v 1.320 2009/09/20 01:09:24 christos Exp $ # # Config file and device description for machine-independent PCI code. # Included by ports that need it. Requires that the SCSI files be @@ -337,6 +337,11 @@ device ixpide: ata, ata_dma, ata_udma, pciide_common, wdc_common attach ixpide at pci file dev/pci/ixpide.c ixpide +# Toshiba PICCOLO IDE controllers +device toshide: ata, ata_dma, pciide_common, wdc_common +attach toshide at pci +file dev/pci/toshide.c toshide + # PCI-PCI bridge chips device ppb: pcibus attach ppb at pci diff --git a/sys/dev/pci/pcidevs b/sys/dev/pci/pcidevs index 6e61e2fbe137..1000240ecab5 100644 --- a/sys/dev/pci/pcidevs +++ b/sys/dev/pci/pcidevs @@ -1,4 +1,4 @@ -$NetBSD: pcidevs,v 1.995 2009/08/01 21:34:21 matt Exp $ +$NetBSD: pcidevs,v 1.996 2009/09/20 01:09:24 christos Exp $ /* * Copyright (c) 1995, 1996 Christopher G. Demetriou @@ -3961,11 +3961,16 @@ product TOSHIBA TC35856F 0x0020 TC35856F ATM (\"Meteor\") /* Toshiba products */ product TOSHIBA2 PORTEGE 0x0001 Portege Notebook +product TOSHIBA2 PICCOLO 0x0101 Piccolo IDE Controller +product TOSHIBA2 PICCOLO2 0x0102 Piccolo 2 IDE Controller +product TOSHIBA2 PICCOLO3 0x0103 Piccolo 3 IDE Controller +product TOSHIBA2 PICCOLO5 0x0105 Piccolo 5 IDE Controller product TOSHIBA2 HOST 0x0601 Host Bridge/Controller product TOSHIBA2 ISA 0x0602 PCI-ISA Bridge product TOSHIBA2 ToPIC95 0x0603 ToPIC95 PCI-CardBus Bridge product TOSHIBA2 ToPIC95B 0x060a ToPIC95B PCI-CardBus Bridge product TOSHIBA2 ToPIC97 0x060f ToPIC97 PCI-CardBus Bridge +product TOSHIBA2 SANREMO 0x0618 SanRemo? Triangle Host Bridge product TOSHIBA2 SMCARD 0x0804 Smart Media Controller product TOSHIBA2 SDCARD 0x0805 Secure Digital Card Controller Type-A product TOSHIBA2 ToPIC100 0x0617 ToPIC100 PCI-CardBus Bridge diff --git a/sys/dev/pci/pciide_piccolo_reg.h b/sys/dev/pci/pciide_piccolo_reg.h new file mode 100644 index 000000000000..7b0d6cba05b1 --- /dev/null +++ b/sys/dev/pci/pciide_piccolo_reg.h @@ -0,0 +1,82 @@ +/* $NetBSD: pciide_piccolo.h_reg.h,v 1.0 2008/04/28 00:00:00 djb */ + +/* + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Register definitions for the Toshiba PICCOLO, by SWAG! + */ + +#define PICCOLO_PIO_TIMING 0x50 +#define PICCOLO_DMA_TIMING 0x5c + +#define PICCOLO_PIO_MASK 0xffffe088 +#define PICCOLO_DMA_MASK 0xffffe088 +#define PICCOLO_UDMA_MASK 0x78ffe088 + +/* TIMING SWAG!!! */ + +/* + * first digit is command active, next two are front porch and back porch + * command active >= minimum for mode + * front porch + back porch + command active >= cycle time for mode + * values below may need adjustment + */ +static const u_int32_t piccolo_pio_times[] + __unused = { +/* programmed actual */ + 0x0566, + 0x0433, + 0x0311, + 0x0201, + 0x0200, /* PIO 4, 150ns cycle (120ns is spec), 90ns command active (70ns is spec), 30ns setup and hold */ + 0x0100 + +}; + +static const u_int32_t piccolo_sw_dma_times[] + __unused = { +/* programmed actual */ + 0x0f77 +}; + +static const u_int32_t piccolo_mw_dma_times[] + __unused = { +/* programmed actual */ + 0x0655, + 0x0200, + 0x0200, + 0x0100 +}; + +/* XXX Is MSB UDMA enable? Can't set it. Seems to work without being set. */ +static const u_int32_t piccolo_udma_times[] + __unused = { +/* programmed actual */ + 0x84000222, + 0x83000111, + 0x82000000 /* UDMA 2, 120ns cycle (117ns is spec), 60ns command active (55ns is spec), 30ns setup and hold */ +}; diff --git a/sys/dev/pci/toshide.c b/sys/dev/pci/toshide.c new file mode 100644 index 000000000000..473e76ca7939 --- /dev/null +++ b/sys/dev/pci/toshide.c @@ -0,0 +1,271 @@ +/* $NetBSD: toshide.c,v 1.1 2009/09/20 01:10:12 christos Exp $ */ + +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: toshide.c,v 1.1 2009/09/20 01:10:12 christos Exp $"); + +#include +#include + +#include +#include +#include +#include +#include + +static void piccolo_chip_map(struct pciide_softc *, struct pci_attach_args *); +static void piccolo_setup_channel(struct ata_channel *); + +static int piccolo_match(device_t, cfdata_t, void *); +static void piccolo_attach(device_t, device_t, void *); + +CFATTACH_DECL_NEW(toshide, sizeof(struct pciide_softc), + piccolo_match, piccolo_attach, NULL, NULL); + +static const struct pciide_product_desc pciide_toshiba2_products[] = { + { + PCI_PRODUCT_TOSHIBA2_PICCOLO, + 0, + "Toshiba Piccolo IDE controller", + piccolo_chip_map, + }, + { + PCI_PRODUCT_TOSHIBA2_PICCOLO2, + 0, + "Toshiba Piccolo 2 IDE controller", + piccolo_chip_map, + }, + { + PCI_PRODUCT_TOSHIBA2_PICCOLO3, + 0, + "Toshiba Piccolo 3 IDE controller", + piccolo_chip_map, + }, + { + PCI_PRODUCT_TOSHIBA2_PICCOLO5, + 0, + "Toshiba Piccolo 5 IDE controller", + piccolo_chip_map, + }, + { + 0, + 0, + NULL, + NULL, + } +}; + +static int +piccolo_match(device_t parent, cfdata_t match, void *aux) +{ + struct pci_attach_args *pa = aux; + + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TOSHIBA2) { + if (pciide_lookup_product(pa->pa_id, pciide_toshiba2_products)) + return 2; + } + return 0; +} + +static void +piccolo_attach(device_t parent, device_t self, void *aux) +{ + struct pci_attach_args *pa = aux; + struct pciide_softc *sc = device_private(self); + const struct pciide_product_desc *pp; + + sc->sc_wdcdev.sc_atac.atac_dev = self; + + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TOSHIBA2) + pp = pciide_lookup_product(pa->pa_id, pciide_toshiba2_products); + else + pp = NULL; + if (pp == NULL) + panic("toshide_attach"); + pciide_common_attach(sc, pa, pp); +} + +static void +piccolo_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa) +{ + struct pciide_channel *cp; + bus_size_t cmdsize, ctlsize; + pcireg_t interface; + int channel; + + if (pciide_chipen(sc, pa) == 0) + return; + + aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, + "bus-master DMA support present"); + + pciide_mapreg_dma(sc, pa); + aprint_verbose("\n"); + + sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA32 | ATAC_CAP_DATA16; + sc->sc_wdcdev.sc_atac.atac_pio_cap = 5; + + if (sc->sc_dma_ok) { + sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; + sc->sc_wdcdev.irqack = pciide_irqack; + sc->sc_wdcdev.sc_atac.atac_dma_cap = 3; + sc->sc_wdcdev.sc_atac.atac_udma_cap = 2; + } + + sc->sc_wdcdev.sc_atac.atac_set_modes = piccolo_setup_channel; + + sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; + sc->sc_wdcdev.sc_atac.atac_nchannels = 1; + /* + * XXX one for now. We'll figure out how to talk to the second channel + * later, hopefully! Second interface config is via the + * "alternate PCI Configuration Space" whatever that is! + */ + + interface = PCI_INTERFACE(pa->pa_class); + + wdc_allocate_regs(&sc->sc_wdcdev); + + for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; + channel++) { + cp = &sc->pciide_channels[channel]; + if (pciide_chansetup(sc, channel, interface) == 0) + continue; + + pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, + pciide_pci_intr); + } +} + +static void +piccolo_setup_channel(struct ata_channel *chp) +{ + struct ata_drive_datas *drvp; + struct pciide_channel *cp = CHAN_TO_PCHAN(chp); + struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); + u_int32_t idedma_ctl; + int drive, s; + pcireg_t pxdx, pxdx_prime; +#ifdef TOSHIDE_DEBUG + pcireg_t pxdx_prime; +#endif + + idedma_ctl = 0; + + /* Set up DMA if needed. */ + pciide_channel_dma_setup(cp); + + for (drive = 0; drive < 2; drive++) { + + drvp = &chp->ch_drive[drive]; + /* If no drive, skip */ + if ((drvp->drive_flags & DRIVE) == 0) + continue; + + if (drvp->drive_flags & DRIVE_UDMA) { + /* use Ultra/DMA */ + s = splbio(); + drvp->drive_flags &= ~DRIVE_DMA; + splx(s); + + /* + * Use UDMA - we can go up to mode 2 so no need to + * check anything since nearly all drives with UDMA + * are mode 2 or faster + */ + pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, + PICCOLO_DMA_TIMING); + pxdx &= PICCOLO_UDMA_MASK; + pxdx |= piccolo_udma_times[2]; + pci_conf_write(sc->sc_pc, sc->sc_tag, + PICCOLO_DMA_TIMING, pxdx); +#ifdef TOSHIDE_DEBUG + /* XXX sanity check */ + pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, + PICCOLO_DMA_TIMING); + aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, + "UDMA want %x, set %x, got %x\n", + piccolo_udma_times[2], pxdx, pxdx_prime); +#endif + idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); + + } + else if (drvp->drive_flags & DRIVE_DMA) { + /* + * Use Multiword DMA + */ + if (drvp->PIO_mode > (drvp->DMA_mode + 2)) + drvp->PIO_mode = drvp->DMA_mode + 2; + if (drvp->DMA_mode + 2 > (drvp->PIO_mode)) + drvp->DMA_mode = (drvp->PIO_mode > 2) ? + drvp->PIO_mode - 2 : 0; + + pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, + PICCOLO_DMA_TIMING); + pxdx &= PICCOLO_DMA_MASK; + pxdx |= piccolo_mw_dma_times[drvp->DMA_mode]; + pci_conf_write(sc->sc_pc, sc->sc_tag, + PICCOLO_DMA_TIMING, pxdx); +#ifdef TOSHIDE_DEBUG + /* XXX sanity check */ + pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, + PICCOLO_DMA_TIMING); + aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, + "DMA %d want %x, set %x, got %x\n", + drvp->DMA_mode, + piccolo_mw_dma_times[drvp->DMA_mode], pxdx, + pxdx_prime); +#endif + idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); + + } + else { + pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, + PICCOLO_PIO_TIMING); + pxdx &= PICCOLO_PIO_MASK; + pxdx |= piccolo_pio_times[drvp->PIO_mode]; + pci_conf_write(sc->sc_pc, sc->sc_tag, + PICCOLO_PIO_TIMING, pxdx); +#ifdef TOSHIDE_DEBUG + /* XXX sanity check */ + pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, + PICCOLO_PIO_TIMING); + aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, + "PIO %d want %x, set %x, got %x\n", drvp->PIO_mode, + piccolo_pio_times[drvp->PIO_mode], pxdx, + pxdx_prime); +#endif + } + + } + if (idedma_ctl != 0) { + /* Add software bits in status register */ + bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, + idedma_ctl); + } +}