ata_kauai.c revision 145311
1139825Simp/*- 2125735Sgrehan * Copyright 2004 by Peter Grehan. All rights reserved. 3125735Sgrehan * 4125735Sgrehan * Redistribution and use in source and binary forms, with or without 5125735Sgrehan * modification, are permitted provided that the following conditions 6125735Sgrehan * are met: 7125735Sgrehan * 1. Redistributions of source code must retain the above copyright 8125735Sgrehan * notice, this list of conditions and the following disclaimer. 9125735Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 10125735Sgrehan * notice, this list of conditions and the following disclaimer in the 11125735Sgrehan * documentation and/or other materials provided with the distribution. 12125735Sgrehan * 3. The name of the author may not be used to endorse or promote products 13125735Sgrehan * derived from this software without specific prior written permission. 14125735Sgrehan * 15125735Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16125735Sgrehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17125735Sgrehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18125735Sgrehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19125735Sgrehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20125735Sgrehan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21125735Sgrehan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22125735Sgrehan * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23125735Sgrehan * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24125735Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25125735Sgrehan * SUCH DAMAGE. 26125735Sgrehan * 27125735Sgrehan */ 28125735Sgrehan#include <sys/cdefs.h> 29125735Sgrehan__FBSDID("$FreeBSD: head/sys/powerpc/powermac/ata_kauai.c 145311 2005-04-20 02:26:31Z grehan $"); 30125735Sgrehan 31125735Sgrehan/* 32125735Sgrehan * Mac 'Kauai' PCI ATA controller 33125735Sgrehan */ 34125735Sgrehan#include "opt_ata.h" 35125735Sgrehan#include <sys/param.h> 36125735Sgrehan#include <sys/systm.h> 37125735Sgrehan#include <sys/kernel.h> 38125735Sgrehan#include <sys/module.h> 39125735Sgrehan#include <sys/bus.h> 40125735Sgrehan#include <sys/malloc.h> 41125735Sgrehan#include <sys/sema.h> 42125735Sgrehan#include <sys/taskqueue.h> 43125735Sgrehan#include <vm/uma.h> 44125735Sgrehan#include <machine/stdarg.h> 45125735Sgrehan#include <machine/resource.h> 46125735Sgrehan#include <machine/bus.h> 47125735Sgrehan#include <sys/rman.h> 48125735Sgrehan#include <sys/ata.h> 49125735Sgrehan#include <dev/ata/ata-all.h> 50144457Sgrehan#include <ata_if.h> 51125735Sgrehan 52125735Sgrehan#include <dev/ofw/openfirm.h> 53125735Sgrehan 54125735Sgrehan#include <dev/pci/pcivar.h> 55125735Sgrehan#include <dev/pci/pcireg.h> 56125735Sgrehan 57125735Sgrehan#define ATA_KAUAI_REGOFFSET 0x2000 58125735Sgrehan 59125735Sgrehan/* 60126394Sgrehan * Offset to alt-control register from base 61126394Sgrehan */ 62126394Sgrehan#define ATA_KAUAI_ALTOFFSET (ATA_KAUAI_REGOFFSET + 0x160) 63126394Sgrehan 64126394Sgrehan/* 65126394Sgrehan * Define the gap between registers 66126394Sgrehan */ 67126394Sgrehan#define ATA_KAUAI_REGGAP 16 68126394Sgrehan 69126394Sgrehan/* 70125735Sgrehan * Define the kauai pci bus attachment. 71125735Sgrehan */ 72125735Sgrehanstatic int ata_kauai_probe(device_t dev); 73144457Sgrehanstatic void ata_kauai_setmode(device_t parent, device_t dev); 74125735Sgrehan 75125735Sgrehanstatic device_method_t ata_kauai_methods[] = { 76125735Sgrehan /* Device interface */ 77125735Sgrehan DEVMETHOD(device_probe, ata_kauai_probe), 78125735Sgrehan DEVMETHOD(device_attach, ata_attach), 79125735Sgrehan DEVMETHOD(device_detach, bus_generic_detach), 80125735Sgrehan DEVMETHOD(device_shutdown, bus_generic_shutdown), 81125735Sgrehan DEVMETHOD(device_suspend, bus_generic_suspend), 82125735Sgrehan DEVMETHOD(device_resume, bus_generic_resume), 83125735Sgrehan 84144457Sgrehan /* ATA interface */ 85144457Sgrehan DEVMETHOD(ata_setmode, ata_kauai_setmode), 86125735Sgrehan { 0, 0 } 87125735Sgrehan}; 88125735Sgrehan 89125735Sgrehanstatic driver_t ata_kauai_driver = { 90125735Sgrehan "ata", 91125735Sgrehan ata_kauai_methods, 92125735Sgrehan sizeof(struct ata_channel), 93125735Sgrehan}; 94125735Sgrehan 95125735SgrehanDRIVER_MODULE(ata, pci, ata_kauai_driver, ata_devclass, 0, 0); 96144359SgrehanMODULE_DEPEND(ata, ata, 1, 1, 1); 97125735Sgrehan 98125735Sgrehan/* 99125735Sgrehan * PCI ID search table 100125735Sgrehan */ 101125735Sgrehanstatic struct kauai_pci_dev { 102125735Sgrehan u_int32_t kpd_devid; 103125735Sgrehan char *kpd_desc; 104125735Sgrehan} kauai_pci_devlist[] = { 105125735Sgrehan { 0x0033106b, "Uninorth2 Kauai ATA Controller" }, 106125735Sgrehan { 0x003b106b, "Intrepid Kauai ATA Controller" }, 107125735Sgrehan { 0x0043106b, "K2 Kauai ATA Controller" }, 108125735Sgrehan { 0, NULL } 109125735Sgrehan}; 110125735Sgrehan 111125735Sgrehanstatic int 112125735Sgrehanata_kauai_probe(device_t dev) 113125735Sgrehan{ 114125735Sgrehan struct ata_channel *ch; 115125735Sgrehan struct resource *mem; 116125735Sgrehan u_long startp, countp; 117125735Sgrehan u_int32_t devid; 118125735Sgrehan int i, found, rid, status; 119125735Sgrehan 120125735Sgrehan found = 0; 121125735Sgrehan devid = pci_get_devid(dev); 122125735Sgrehan for (i = 0; kauai_pci_devlist[i].kpd_desc != NULL; i++) { 123125735Sgrehan if (devid == kauai_pci_devlist[i].kpd_devid) { 124125735Sgrehan found = 1; 125125735Sgrehan device_set_desc(dev, kauai_pci_devlist[i].kpd_desc); 126125735Sgrehan } 127125735Sgrehan } 128125735Sgrehan 129125735Sgrehan if (!found) 130125735Sgrehan return (ENXIO); 131125735Sgrehan 132125735Sgrehan /* 133125735Sgrehan * This device seems to ignore writes to the interrupt 134125735Sgrehan * config register, resulting in interrupt resources 135125735Sgrehan * not being attached. If this is the case, use 136133862Smarius * Open Firmware to determine the irq, and then attach 137125735Sgrehan * the resource. This allows the ATA common code to 138125735Sgrehan * allocate the irq. 139125735Sgrehan */ 140125735Sgrehan status = bus_get_resource(dev, SYS_RES_IRQ, 0, &startp, &countp); 141125735Sgrehan if (status == ENOENT) { 142125735Sgrehan int irq; 143125735Sgrehan 144125735Sgrehan /* 145125735Sgrehan * Aargh, hideous hack until ofw pci intr routine is 146125735Sgrehan * exported 147125735Sgrehan */ 148125735Sgrehan irq = 39; /* XXX */ 149125735Sgrehan bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); 150125735Sgrehan 151125735Sgrehan /* 152125735Sgrehan * Sanity check... 153125735Sgrehan */ 154125735Sgrehan status = bus_get_resource(dev, SYS_RES_IRQ, 0, &startp, 155125735Sgrehan &countp); 156125735Sgrehan if (status == ENOENT || 157125735Sgrehan startp != 39) { 158125735Sgrehan printf("kauai irq not set!\n"); 159125735Sgrehan return (ENXIO); 160125735Sgrehan } 161125735Sgrehan } 162125735Sgrehan 163125735Sgrehan ch = device_get_softc(dev); 164128595Sgrehan bzero(ch, sizeof(struct ata_channel)); 165125735Sgrehan 166126394Sgrehan rid = PCIR_BARS; 167127659Sgrehan mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 168125735Sgrehan if (mem == NULL) { 169125735Sgrehan device_printf(dev, "could not allocate memory\n"); 170125735Sgrehan return (ENXIO); 171125735Sgrehan } 172125735Sgrehan 173125735Sgrehan /* 174125735Sgrehan * Set up the resource vectors 175125735Sgrehan */ 176145221Sgrehan for (i = ATA_DATA; i <= ATA_COMMAND; i++) { 177125735Sgrehan ch->r_io[i].res = mem; 178126394Sgrehan ch->r_io[i].offset = i*ATA_KAUAI_REGGAP + ATA_KAUAI_REGOFFSET; 179125735Sgrehan } 180145311Sgrehan ch->r_io[ATA_CONTROL].res = mem; 181145311Sgrehan ch->r_io[ATA_CONTROL].offset = ATA_KAUAI_ALTOFFSET; 182145221Sgrehan ata_default_registers(ch); 183125735Sgrehan 184125735Sgrehan ch->unit = 0; 185125735Sgrehan ch->flags |= ATA_USE_16BIT|ATA_NO_SLAVE; 186128595Sgrehan ata_generic_hw(ch); 187125735Sgrehan 188125735Sgrehan return (ata_probe(dev)); 189125735Sgrehan} 190125735Sgrehan 191144457Sgrehanstatic void 192144457Sgrehanata_kauai_setmode(device_t parent, device_t dev) 193144457Sgrehan{ 194144457Sgrehan struct ata_device *atadev = device_get_softc(dev); 195144457Sgrehan 196144457Sgrehan /* TODO bang kauai speed register */ 197144457Sgrehan atadev->mode = ATA_PIO; 198144457Sgrehan} 199