ata-all.c revision 47334
1195801Smav/*- 2195801Smav * Copyright (c) 1998,1999 S�ren Schmidt 3195801Smav * All rights reserved. 4195801Smav * 5195801Smav * Redistribution and use in source and binary forms, with or without 6195801Smav * modification, are permitted provided that the following conditions 7195801Smav * are met: 8195801Smav * 1. Redistributions of source code must retain the above copyright 9195801Smav * notice, this list of conditions and the following disclaimer, 10195801Smav * without modification, immediately at the beginning of the file. 11195801Smav * 2. Redistributions in binary form must reproduce the above copyright 12195801Smav * notice, this list of conditions and the following disclaimer in the 13195801Smav * documentation and/or other materials provided with the distribution. 14195801Smav * 3. The name of the author may not be used to endorse or promote products 15195801Smav * derived from this software without specific prior written permission. 16195801Smav * 17195801Smav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18195801Smav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19195801Smav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20195801Smav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21195801Smav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22195801Smav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23195801Smav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24195801Smav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25195801Smav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26195801Smav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27195801Smav * 28195801Smav * $Id: ata-all.c,v 1.13 1999/05/17 15:58:44 sos Exp $ 29195801Smav */ 30195801Smav 31195801Smav#include "ata.h" 32195801Smav#if NATA > 0 33195801Smav#include "isa.h" 34195801Smav#include "pci.h" 35195801Smav#include "atadisk.h" 36195801Smav#include "opt_global.h" 37195801Smav#include <sys/param.h> 38195801Smav#include <sys/systm.h> 39195801Smav#include <sys/kernel.h> 40195801Smav#include <sys/interrupt.h> 41195801Smav#include <sys/conf.h> 42195801Smav#include <sys/module.h> 43195801Smav#include <sys/bus.h> 44195801Smav#include <sys/buf.h> 45195801Smav#include <sys/malloc.h> 46195801Smav#include <sys/devicestat.h> 47195801Smav#include <vm/vm.h> 48195801Smav#include <vm/pmap.h> 49195801Smav#include <machine/resource.h> 50195801Smav#include <machine/bus.h> 51195801Smav#include <sys/rman.h> 52195801Smav#include <machine/clock.h> 53195801Smav#ifdef __i386__ 54195801Smav#include <machine/smp.h> 55195801Smav#include <i386/isa/intr_machdep.h> 56195801Smav#endif 57195801Smav#if NPCI > 0 58195801Smav#include <pci/pcivar.h> 59195801Smav#include <pci/pcireg.h> 60195801Smav#endif 61195801Smav#include <isa/isavar.h> 62195801Smav#include <isa/isareg.h> 63195801Smav#include <dev/ata/ata-all.h> 64195801Smav#include <dev/ata/ata-disk.h> 65195801Smav#include <dev/ata/atapi-all.h> 66195801Smav 67195801Smav/* misc defines */ 68195801Smav#define UNIT(dev) (dev>>3 & 0x1f) /* assume 8 minor # per unit */ 69195801Smav#define MIN(a,b) ((a)>(b)?(b):(a)) 70195801Smav#if SMP == 0 71195801Smav#define isa_apic_irq(x) x 72195801Smav#endif 73195801Smav 74195801Smav/* prototypes */ 75195801Smav#if NPCI > 0 76195801Smavstatic void promise_intr(void *); 77195801Smav#endif 78195801Smavstatic int32_t ata_probe(int32_t, int32_t, int32_t, device_t, int32_t *); 79195801Smavstatic void ataintr(void *); 80195801Smav 81195801Smavstatic int32_t atanlun = 0; 82195801Smavstruct ata_softc *atadevices[MAXATA]; 83195801Smavstatic devclass_t ata_devclass; 84195801Smav 85195801Smav#if NISA > 0 86195801Smav 87195801Smavstatic int 88195801Smavata_isaprobe(device_t dev) 89195801Smav{ 90195801Smav struct resource *port; 91195801Smav int rid; 92195801Smav int32_t ctlr, res; 93195801Smav int32_t lun; 94195801Smav 95195801Smav /* allocate the port range */ 96195801Smav rid = 0; 97195801Smav port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); 98195801Smav if (!port) 99195801Smav return (ENOMEM); 100195801Smav 101195801Smav /* check if allready in use by a PCI device */ 102195801Smav for (ctlr = 0; ctlr < atanlun; ctlr++) { 103195801Smav if (atadevices[ctlr]->ioaddr == rman_get_start(port)) { 104195801Smav printf("ata-isa%d: already registered as ata%d\n", 105195801Smav device_get_unit(dev), ctlr); 106195801Smav bus_release_resource(dev, SYS_RES_IOPORT, 0, port); 107195801Smav return ENXIO; 108195801Smav } 109195801Smav } 110195801Smav 111195801Smav lun = 0; 112195801Smav res = ata_probe(rman_get_start(port), rman_get_start(port) + ATA_ALTPORT, 113195801Smav 0, dev, &lun); 114195801Smav 115195801Smav bus_release_resource(dev, SYS_RES_IOPORT, 0, port); 116195801Smav 117195801Smav if (res) { 118195801Smav isa_set_portsize(dev, res); 119195801Smav *(int *)device_get_softc(dev) = lun; 120195801Smav return 0; 121195801Smav } 122195801Smav 123195801Smav return ENXIO; 124195801Smav} 125195801Smav 126195801Smavstatic int 127195801Smavata_isaattach(device_t dev) 128195801Smav{ 129195801Smav struct resource *port; 130195801Smav struct resource *irq; 131195801Smav void *ih; 132195801Smav int rid; 133195801Smav 134195801Smav /* Allocate the port range and interrupt */ 135195801Smav rid = 0; 136195801Smav port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); 137195801Smav if (!port) 138195801Smav return (ENOMEM); 139195801Smav 140195801Smav rid = 0; 141195801Smav irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE); 142195801Smav if (!irq) { 143195801Smav bus_release_resource(dev, SYS_RES_IOPORT, 0, port); 144195801Smav return (ENOMEM); 145195801Smav } 146195801Smav return bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, 147195801Smav atadevices[*(int *)device_get_softc(dev)], &ih); 148195801Smav} 149195801Smav 150195801Smavstatic device_method_t ata_isa_methods[] = { 151195801Smav /* Device interface */ 152195801Smav DEVMETHOD(device_probe, ata_isaprobe), 153195801Smav DEVMETHOD(device_attach, ata_isaattach), 154195801Smav { 0, 0 } 155195801Smav}; 156195801Smav 157195801Smavstatic driver_t ata_isa_driver = { 158195801Smav "ata", 159195801Smav ata_isa_methods, 160195801Smav sizeof(int), 161195801Smav}; 162195801Smav 163195801SmavDRIVER_MODULE(ata, isa, ata_isa_driver, ata_devclass, 0, 0); 164195801Smav 165195801Smav#endif 166195801Smav 167195801Smav#if NPCI > 0 168195801Smav 169195801Smavstatic const char * 170195801Smavata_pcimatch(device_t dev) 171195801Smav{ 172195801Smav u_int32_t data; 173195801Smav 174195801Smav data = pci_read_config(dev, PCI_CLASS_REG, 4); 175195801Smav if (pci_get_class(dev) == PCIC_STORAGE && 176195801Smav (pci_get_subclass(dev) == PCIS_STORAGE_IDE || 177195801Smav pci_get_subclass(dev) == PCIS_STORAGE_RAID)) { 178195801Smav switch (pci_get_devid(dev)) { 179195801Smav case 0x12308086: 180195801Smav return "Intel PIIX IDE controller"; 181195801Smav case 0x70108086: 182195801Smav return "Intel PIIX3 IDE controller"; 183195801Smav case 0x71118086: 184195801Smav return "Intel PIIX4 IDE controller"; 185195801Smav case 0x4d33105a: 186195801Smav return "Promise Ultra/33 IDE controller"; 187195801Smav case 0x522910b9: 188195801Smav return "AcerLabs Aladdin IDE controller"; 189195801Smav#if 0 190195801Smav case 0x05711106: 191195801Smav return "VIA Apollo IDE controller"; 192195801Smav case 0x06401095: 193195801Smav return "CMD 640 IDE controller"; 194195801Smav case 0x06461095: 195195801Smav return "CMD 646 IDE controller"; 196195801Smav case 0xc6931080: 197195801Smav return "Cypress 82C693 IDE controller"; 198195801Smav case 0x01021078: 199195801Smav return "Cyrix 5530 IDE controller"; 200195801Smav#endif 201195801Smav default: 202195801Smav return "Unknown PCI IDE controller"; 203195801Smav } 204195801Smav } 205195801Smav return NULL; 206195801Smav} 207195801Smav 208195801Smavstatic int 209195801Smavata_pciprobe(device_t dev) 210195801Smav{ 211195801Smav const char *desc = ata_pcimatch(dev); 212195801Smav if (desc) { 213195801Smav device_set_desc(dev, desc); 214195801Smav return 0; 215195801Smav } 216195801Smav else 217195801Smav return ENXIO; 218195801Smav} 219195801Smav 220195801Smavstatic int 221195801Smavata_pciattach(device_t dev) 222195801Smav{ 223195801Smav int unit = device_get_unit(dev); 224195801Smav struct ata_softc *scp; 225195801Smav u_int32_t type; 226195801Smav u_int8_t class, subclass; 227195801Smav u_int32_t cmd; 228195801Smav int32_t iobase_1, iobase_2, altiobase_1, altiobase_2; 229195801Smav int32_t bmaddr_1 = 0, bmaddr_2 = 0, irq1, irq2; 230195801Smav int32_t lun; 231195801Smav 232195801Smav /* set up vendor-specific stuff */ 233195801Smav type = pci_get_devid(dev); 234195801Smav class = pci_get_class(dev); 235195801Smav subclass = pci_get_subclass(dev); 236195801Smav cmd = pci_read_config(dev, PCIR_COMMAND, 4); 237195801Smav 238195801Smav#ifdef ATA_DEBUG 239195801Smav printf("ata-pci%d: type=%08x class=%02x subclass=%02x cmd=%08x\n", 240195801Smav unit, type, class, subclass, cmd); 241195801Smav#endif 242195801Smav 243195801Smav /* if this is a Promise controller handle it specially */ 244195801Smav if (type == 0x4d33105a) { 245195801Smav iobase_1 = pci_read_config(dev, 0x10, 4) & 0xfffc; 246195801Smav altiobase_1 = pci_read_config(dev, 0x14, 4) & 0xfffc; 247195801Smav iobase_2 = pci_read_config(dev, 0x18, 4) & 0xfffc; 248195801Smav altiobase_2 = pci_read_config(dev, 0x1c, 4) & 0xfffc; 249195801Smav irq1 = irq2 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff; 250195801Smav bmaddr_1 = pci_read_config(dev, 0x20, 4) & 0xfffc; 251195801Smav bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1; 252195801Smav outb(bmaddr_1 + 0x1f, inb(bmaddr_1 + 0x1f) | 0x01); 253195801Smav printf("ata-pci%d: Busmastering DMA supported\n", unit); 254195801Smav } 255195801Smav /* everybody else seems to do it this way */ 256195801Smav else { 257195801Smav if ((unit == 0) && 258195801Smav (pci_get_progif(dev) & PCIP_STORAGE_IDE_MODEPRIM) == 0) { 259195801Smav iobase_1 = IO_WD1; 260195801Smav altiobase_1 = iobase_1 + ATA_ALTPORT; 261195801Smav irq1 = 14; 262195801Smav } 263195801Smav else { 264195801Smav iobase_1 = pci_read_config(dev, 0x10, 4) & 0xfffc; 265195801Smav altiobase_1 = pci_read_config(dev, 0x14, 4) & 0xfffc; 266195801Smav irq1 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff; 267195801Smav } 268195801Smav if ((unit == 0) && 269195801Smav (pci_get_progif(dev) & PCIP_STORAGE_IDE_MODESEC) == 0) { 270195801Smav iobase_2 = IO_WD2; 271195801Smav altiobase_2 = iobase_2 + ATA_ALTPORT; 272195801Smav irq2 = 15; 273195801Smav } 274195801Smav else { 275195801Smav iobase_2 = pci_read_config(dev, 0x18, 4) & 0xfffc; 276195801Smav altiobase_2 = pci_read_config(dev, 0x1c, 4) & 0xfffc; 277195801Smav irq2 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff; 278195801Smav } 279195801Smav 280195801Smav /* is this controller busmaster capable ? */ 281195801Smav if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) { 282195801Smav /* is busmastering support turned on ? */ 283195801Smav if ((pci_read_config(dev, PCI_COMMAND_STATUS_REG, 4) & 5) == 5) { 284195801Smav /* is there a valid port range to connect to ? */ 285195801Smav if ((bmaddr_1 = pci_read_config(dev, 0x20, 4) & 0xfffc)) { 286195801Smav bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1; 287195801Smav printf("ata-pci%d: Busmastering DMA supported\n", unit); 288195801Smav } 289195801Smav else 290195801Smav printf("ata-pci%d: Busmastering DMA not configured\n",unit); 291195801Smav } 292195801Smav else 293195801Smav printf("ata-pci%d: Busmastering DMA not enabled\n", unit); 294195801Smav } 295195801Smav else 296195801Smav printf("ata-pci%d: Busmastering DMA not supported\n", unit); 297195801Smav } 298195801Smav 299195801Smav /* now probe the addresse found for "real" ATA/ATAPI hardware */ 300195801Smav lun = 0; 301195801Smav if (ata_probe(iobase_1, altiobase_1, bmaddr_1, dev, &lun)) { 302195801Smav scp = atadevices[lun]; 303195801Smav if (iobase_1 == IO_WD1) 304195801Smav#ifdef __i386__ 305195801Smav inthand_add(device_get_nameunit(dev), irq1, ataintr, scp, 306195801Smav &bio_imask, INTR_EXCL); 307195801Smav#endif 308195801Smav#ifdef __alpha__ 309195801Smav alpha_platform_setup_ide_intr(0, ataintr, scp); 310195801Smav#endif 311195801Smav else { 312195801Smav struct resource *irq; 313195801Smav int rid = 0; 314195801Smav void *ih; 315195801Smav 316195801Smav irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 317195801Smav RF_SHAREABLE | RF_ACTIVE); 318195801Smav if (!irq) 319195801Smav printf("ata_pciattach: Unable to alloc interrupt\n"); 320195801Smav 321195801Smav if (type == 0x4d33105a) 322195801Smav bus_setup_intr(dev, irq, INTR_TYPE_BIO, promise_intr, scp, &ih); 323195801Smav else 324195801Smav bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, scp, &ih); 325195801Smav } 326195801Smav printf("ata%d at 0x%04x irq %d on ata-pci%d\n", 327195801Smav lun, iobase_1, isa_apic_irq(irq1), unit); 328195801Smav } 329195801Smav lun = 1; 330195801Smav if (ata_probe(iobase_2, altiobase_2, bmaddr_2, dev, &lun)) { 331195801Smav scp = atadevices[lun]; 332195801Smav if (iobase_2 == IO_WD2) 333195801Smav#ifdef __i386__ 334195801Smav inthand_add(device_get_nameunit(dev), irq2, ataintr, scp, 335195801Smav &bio_imask, INTR_EXCL); 336195801Smav#endif 337195801Smav#ifdef __alpha__ 338195801Smav alpha_platform_setup_ide_intr(1, ataintr, scp); 339195801Smav#endif 340195801Smav else { 341195801Smav struct resource *irq; 342195801Smav int rid = 0; 343195801Smav void *ih; 344195801Smav 345195801Smav if (type != 0x4d33105a) { 346195801Smav irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 347195801Smav RF_SHAREABLE | RF_ACTIVE); 348195801Smav if (!irq) 349195801Smav printf("ata_pciattach: Unable to alloc interrupt\n"); 350195801Smav 351195801Smav bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, scp, &ih); 352195801Smav } 353195801Smav } 354195801Smav printf("ata%d at 0x%04x irq %d on ata-pci%d\n", 355195801Smav lun, iobase_2, isa_apic_irq(irq2), unit); 356195801Smav } 357195801Smav return 0; 358195801Smav} 359195801Smav 360195801Smavstatic device_method_t ata_pci_methods[] = { 361195801Smav /* Device interface */ 362195801Smav DEVMETHOD(device_probe, ata_pciprobe), 363195801Smav DEVMETHOD(device_attach, ata_pciattach), 364195801Smav { 0, 0 } 365195801Smav}; 366195801Smav 367195801Smavstatic driver_t ata_pci_driver = { 368195801Smav "ata-pci", 369195801Smav ata_pci_methods, 370195801Smav sizeof(int), 371195801Smav}; 372195801Smav 373195801SmavDRIVER_MODULE(ata, pci, ata_pci_driver, ata_devclass, 0, 0); 374195801Smav 375195801Smavstatic void 376195801Smavpromise_intr(void *data) 377195801Smav{ 378195801Smav struct ata_softc *scp = (struct ata_softc *)data; 379195801Smav int32_t channel = inl((pci_read_config(scp->dev, 0x20, 4) & 0xfffc) + 0x1c); 380195801Smav 381195801Smav if (channel & 0x00000400) 382195801Smav ataintr(data); 383195801Smav 384195801Smav if (channel & 0x00004000) 385195801Smav ataintr(atadevices[scp->lun + 1]); 386195801Smav} 387195801Smav#endif 388195801Smav 389195801Smavstatic int32_t 390195801Smavata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr, 391195801Smav device_t dev, int32_t *unit) 392195801Smav{ 393195801Smav struct ata_softc *scp = atadevices[atanlun]; 394195801Smav int32_t mask = 0; 395195801Smav int32_t timeout; 396195801Smav int32_t lun = atanlun; 397195801Smav u_int8_t status0, status1; 398195801Smav 399195801Smav#ifdef ATA_STATIC_ID 400195801Smav atanlun++; 401195801Smav#endif 402195801Smav if (lun > MAXATA) { 403195801Smav printf("ata: unit out of range(%d)\n", lun); 404195801Smav return 0; 405195801Smav } 406195801Smav if (scp) { 407195801Smav printf("ata%d: unit already attached\n", lun); 408195801Smav return 0; 409195801Smav } 410195801Smav scp = malloc(sizeof(struct ata_softc), M_DEVBUF, M_NOWAIT); 411195801Smav if (scp == NULL) { 412195801Smav printf("ata%d: failed to allocate driver storage\n", lun); 413195801Smav return 0; 414195801Smav } 415195801Smav bzero(scp, sizeof(struct ata_softc)); 416195801Smav 417195801Smav scp->unit = *unit; 418195801Smav scp->lun = lun; 419195801Smav scp->ioaddr = ioaddr; 420195801Smav scp->altioaddr = altioaddr; 421195801Smav scp->active = ATA_IDLE; 422195801Smav 423195801Smav#ifdef ATA_DEBUG 424195801Smav printf("ata%d: iobase=0x%04x altiobase=0x%04x\n", 425195801Smav scp->lun, scp->ioaddr, scp->altioaddr); 426195801Smav#endif 427195801Smav 428195801Smav /* do we have any signs of ATA/ATAPI HW being present ? */ 429195801Smav outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER); 430195801Smav DELAY(1); 431195801Smav status0 = inb(scp->ioaddr + ATA_STATUS); 432195801Smav outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); 433195801Smav DELAY(1); 434195801Smav status1 = inb(scp->ioaddr + ATA_STATUS); 435195801Smav if ((status0 & 0xf8) != 0xf8) 436195801Smav mask |= 0x01; 437195801Smav if ((status1 & 0xf8) != 0xf8) 438195801Smav mask |= 0x02; 439195801Smav#ifdef ATA_DEBUG 440195801Smav printf("ata%d: mask=%02x status0=%02x status1=%02x\n", 441195801Smav scp->lun, mask, status0, status1); 442195801Smav#endif 443195801Smav if (!mask) { 444195801Smav free(scp, M_DEVBUF); 445195801Smav return 0; 446195801Smav } 447195801Smav /* assert reset for devices and wait for completition */ 448195801Smav outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER); 449195801Smav DELAY(1); 450195801Smav outb(scp->altioaddr, ATA_A_IDS | ATA_A_RESET); 451195801Smav DELAY(1000); 452195801Smav outb(scp->altioaddr, ATA_A_IDS); 453195801Smav DELAY(1000); 454195801Smav inb(scp->ioaddr + ATA_ERROR); 455195801Smav DELAY(1); 456195801Smav outb(scp->altioaddr, ATA_A_4BIT); 457195801Smav DELAY(1); 458195801Smav 459195801Smav /* wait for BUSY to go inactive */ 460195801Smav for (timeout = 0; timeout < 30000*10; timeout++) { 461195801Smav outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER); 462195801Smav DELAY(1); 463195801Smav status0 = inb(scp->ioaddr + ATA_STATUS); 464195801Smav outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); 465195801Smav DELAY(1); 466195801Smav status1 = inb(scp->ioaddr + ATA_STATUS); 467195801Smav if (mask == 0x01) /* wait for master only */ 468195801Smav if (!(status0 & ATA_S_BSY)) 469195801Smav break; 470195801Smav if (mask == 0x02) /* wait for slave only */ 471195801Smav if (!(status1 & ATA_S_BSY)) 472195801Smav break; 473195801Smav if (mask == 0x03) /* wait for both master & slave */ 474195801Smav if (!(status0 & ATA_S_BSY) && !(status1 & ATA_S_BSY)) 475195801Smav break; 476195801Smav DELAY(100); 477195801Smav } 478195801Smav if (status0 & ATA_S_BSY) 479195801Smav mask &= ~0x01; 480195801Smav if (status1 & ATA_S_BSY) 481195801Smav mask &= ~0x02; 482195801Smav#ifdef ATA_DEBUG 483195801Smav printf("ata%d: mask=%02x status0=%02x status1=%02x\n", 484195801Smav scp->lun, mask, status0, status1); 485195801Smav#endif 486195801Smav if (!mask) { 487195801Smav free(scp, M_DEVBUF); 488195801Smav return 0; 489195801Smav } 490195801Smav /* 491195801Smav * OK, we have at least one device on the chain, 492195801Smav * check for ATAPI signatures, if none check if its 493195801Smav * a good old ATA device. 494195801Smav */ 495195801Smav 496195801Smav outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_MASTER)); 497195801Smav DELAY(1); 498195801Smav if (inb(scp->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB && 499195801Smav inb(scp->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB) { 500195801Smav scp->devices |= ATA_ATAPI_MASTER; 501195801Smav } 502195801Smav outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_SLAVE)); 503195801Smav DELAY(1); 504195801Smav if (inb(scp->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB && 505195801Smav inb(scp->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB) { 506195801Smav scp->devices |= ATA_ATAPI_SLAVE; 507195801Smav } 508195801Smav if (status0 != 0x00 && !(scp->devices & ATA_ATAPI_MASTER)) { 509195801Smav outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_MASTER)); 510195801Smav DELAY(1); 511195801Smav outb(scp->ioaddr + ATA_ERROR, 0x58); 512195801Smav outb(scp->ioaddr + ATA_CYL_LSB, 0xa5); 513195801Smav if (inb(scp->ioaddr + ATA_ERROR) != 0x58 && 514195801Smav inb(scp->ioaddr + ATA_CYL_LSB) == 0xa5) { 515195801Smav scp->devices |= ATA_ATA_MASTER; 516195801Smav } 517195801Smav } 518195801Smav if (status1 != 0x00 && !(scp->devices & ATA_ATAPI_SLAVE)) { 519195801Smav outb(scp->ioaddr + ATA_DRIVE, (ATA_D_IBM | ATA_SLAVE)); 520195801Smav DELAY(1); 521195801Smav outb(scp->ioaddr + ATA_ERROR, 0x58); 522195801Smav outb(scp->ioaddr + ATA_CYL_LSB, 0xa5); 523195801Smav if (inb(scp->ioaddr + ATA_ERROR) != 0x58 && 524195801Smav inb(scp->ioaddr + ATA_CYL_LSB) == 0xa5) { 525195801Smav scp->devices |= ATA_ATA_SLAVE; 526195801Smav } 527195801Smav } 528195801Smav#ifdef ATA_DEBUG 529195801Smav printf("ata%d: devices = 0x%x\n", scp->lun, scp->devices); 530195801Smav#endif 531195801Smav if (!scp->devices) { 532195801Smav free(scp, M_DEVBUF); 533195801Smav return 0; 534195801Smav } 535195801Smav bufq_init(&scp->ata_queue); 536195801Smav TAILQ_INIT(&scp->atapi_queue); 537195801Smav *unit = scp->lun; 538195801Smav scp->dev = dev; 539195801Smav if (bmaddr) 540195801Smav scp->bmaddr = bmaddr; 541195801Smav atadevices[scp->lun] = scp; 542195801Smav#ifndef ATA_STATIC_ID 543195801Smav atanlun++; 544195801Smav#endif 545195801Smav return ATA_IOSIZE; 546195801Smav} 547195801Smav 548195801Smavstatic void 549195801Smavataintr(void *data) 550195801Smav{ 551195801Smav struct ata_softc *scp; 552195801Smav struct atapi_request *atapi_request; 553195801Smav struct buf *ata_request; 554195801Smav u_int8_t status; 555195801Smav static int32_t intr_count = 0; 556195801Smav 557195801Smav scp = (struct ata_softc *)data; 558195801Smav 559195801Smav /* find & call the responsible driver to process this interrupt */ 560195801Smav switch (scp->active) { 561195801Smav#if NATADISK > 0 562195801Smav case ATA_ACTIVE_ATA: 563195801Smav if ((ata_request = bufq_first(&scp->ata_queue))) 564195801Smav if (ad_interrupt(ata_request) == ATA_OP_CONTINUES) 565195801Smav return; 566195801Smav break; 567195801Smav#endif 568195801Smav case ATA_ACTIVE_ATAPI: 569195801Smav if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue))) 570195801Smav if (atapi_interrupt(atapi_request) == ATA_OP_CONTINUES) 571195801Smav return; 572195801Smav break; 573195801Smav 574195801Smav case ATA_WAIT_INTR: 575195801Smav wakeup((caddr_t)scp); 576195801Smav break; 577195801Smav 578195801Smav case ATA_IGNORE_INTR: 579195801Smav break; 580195801Smav 581195801Smav default: 582195801Smav case ATA_IDLE: 583195801Smav status = inb(scp->ioaddr + ATA_STATUS); 584195801Smav if (intr_count++ < 10) 585195801Smav printf("ata%d: unwanted interrupt %d status = %02x\n", 586195801Smav scp->lun, intr_count, status); 587195801Smav return; 588195801Smav } 589195801Smav scp->active = ATA_IDLE; 590195801Smav ata_start(scp); 591195801Smav} 592195801Smav 593195801Smavvoid 594195801Smavata_start(struct ata_softc *scp) 595195801Smav{ 596195801Smav struct buf *ata_request; 597195801Smav struct atapi_request *atapi_request; 598195801Smav 599195801Smav#ifdef ATA_DEBUG 600195801Smav printf("ata_start: entered\n"); 601195801Smav#endif 602195801Smav if (scp->active != ATA_IDLE) { 603195801Smav printf("ata: unwanted ata_start\n"); 604195801Smav return; 605195801Smav } 606195801Smav 607195801Smav#if NATADISK > 0 608195801Smav /* find & call the responsible driver if anything on ATA queue */ 609195801Smav if ((ata_request = bufq_first(&scp->ata_queue))) { 610195801Smav scp->active = ATA_ACTIVE_ATA; 611195801Smav ad_transfer(ata_request); 612195801Smav#ifdef ATA_DEBUG 613195801Smav printf("ata_start: started ata, leaving\n"); 614195801Smav#endif 615195801Smav return; 616195801Smav } 617195801Smav#endif 618195801Smav 619195801Smav /* find & call the responsible driver if anything on ATAPI queue */ 620195801Smav if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue))) { 621195801Smav scp->active = ATA_ACTIVE_ATAPI; 622195801Smav atapi_transfer(atapi_request); 623195801Smav#ifdef ATA_DEBUG 624195801Smav printf("ata_start: started atapi, leaving\n"); 625195801Smav#endif 626195801Smav return; 627195801Smav } 628195801Smav} 629195801Smav 630195801Smavint32_t 631195801Smavata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask) 632195801Smav{ 633195801Smav u_int8_t status; 634195801Smav u_int32_t timeout = 0; 635195801Smav 636195801Smav while (timeout++ <= 500000) { /* timeout 5 secs */ 637195801Smav status = inb(scp->ioaddr + ATA_STATUS); 638195801Smav 639195801Smav /* if drive fails status, reselect the drive just to be sure */ 640195801Smav if (status == 0xff) { 641195801Smav printf("ata%d: %s: no status, reselecting device\n", 642195801Smav scp->lun, device?"slave":"master"); 643195801Smav outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device); 644195801Smav DELAY(1); 645195801Smav status = inb(scp->ioaddr + ATA_STATUS); 646195801Smav } 647195801Smav if (status == 0xff) 648195801Smav return -1; 649195801Smav scp->status = status; 650196655Smav if (!(status & ATA_S_BSY)) { 651196655Smav if (status & ATA_S_ERROR) 652196655Smav scp->error = inb(scp->ioaddr + ATA_ERROR); 653196655Smav if ((status & mask) == mask) 654196655Smav return (status & ATA_S_ERROR); 655196655Smav } 656196655Smav if (timeout > 1000) 657196655Smav DELAY(1000); 658196655Smav else 659196655Smav DELAY(10); 660196655Smav } 661196655Smav return -1; 662196655Smav} 663196655Smav 664196655Smavint32_t 665196655Smavata_command(struct ata_softc *scp, int32_t device, u_int32_t command, 666196655Smav u_int32_t cylinder, u_int32_t head, u_int32_t sector, 667196655Smav u_int32_t count, u_int32_t feature, int32_t flags) 668196655Smav{ 669196655Smav#ifdef ATA_DEBUG 670196655Smavprintf("ata%d: ata_command: addr=%04x, device=%02x, cmd=%02x, c=%d, h=%d, s=%d, count=%d, flags=%02x\n", scp->lun, scp->ioaddr, device, command, cylinder, head, sector, count, flags); 671196655Smav#endif 672196655Smav 673196655Smav /* ready to issue command ? */ 674195801Smav if (ata_wait(scp, device, 0) < 0) { 675195801Smav printf("ata%d: %s: timeout waiting to give command s=%02x e=%02x\n", 676195801Smav scp->lun, device?"slave":"master", scp->status, scp->error); 677195801Smav } 678195801Smav outb(scp->ioaddr + ATA_FEATURE, feature); 679195801Smav outb(scp->ioaddr + ATA_CYL_LSB, cylinder); 680195801Smav outb(scp->ioaddr + ATA_CYL_MSB, cylinder >> 8); 681195801Smav outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device | head); 682195801Smav outb(scp->ioaddr + ATA_SECTOR, sector); 683195801Smav outb(scp->ioaddr + ATA_COUNT, count); 684195801Smav 685195801Smav if (scp->active != ATA_IDLE && flags != ATA_IMMEDIATE) 686195801Smav printf("DANGER active=%d\n", scp->active); 687195801Smav 688195801Smav switch (flags) { 689195801Smav case ATA_WAIT_INTR: 690195801Smav scp->active = ATA_WAIT_INTR; 691195801Smav outb(scp->ioaddr + ATA_CMD, command); 692195801Smav if (tsleep((caddr_t)scp, PRIBIO, "atacmd", 500)) { 693195801Smav printf("ata_command: timeout waiting for interrupt\n"); 694195801Smav scp->active = ATA_IDLE; 695195801Smav return -1; 696195801Smav } 697195801Smav break; 698195801Smav 699195801Smav case ATA_IGNORE_INTR: 700195801Smav scp->active = ATA_IGNORE_INTR; 701195801Smav outb(scp->ioaddr + ATA_CMD, command); 702195801Smav break; 703195801Smav 704195801Smav case ATA_IMMEDIATE: 705195801Smav default: 706195801Smav outb(scp->ioaddr + ATA_CMD, command); 707195801Smav break; 708195801Smav } 709195801Smav#ifdef ATA_DEBUG 710195801Smavprintf("ata_command: leaving\n"); 711195801Smav#endif 712195801Smav return 0; 713195801Smav} 714195801Smav 715195801Smavvoid 716195801Smavbswap(int8_t *buf, int32_t len) 717195801Smav{ 718195801Smav u_int16_t *p = (u_int16_t*)(buf + len); 719195801Smav 720195801Smav while (--p >= (u_int16_t*)buf) 721195801Smav *p = ntohs(*p); 722195801Smav} 723195801Smav 724195801Smavvoid 725195801Smavbtrim(int8_t *buf, int32_t len) 726195801Smav{ 727195801Smav int8_t *p; 728195801Smav 729195801Smav for (p = buf; p < buf+len; ++p) 730195801Smav if (!*p) 731195801Smav *p = ' '; 732195801Smav for (p = buf + len - 1; p >= buf && *p == ' '; --p) 733195801Smav *p = 0; 734196655Smav} 735196655Smav 736196655Smavvoid 737195801Smavbpack(int8_t *src, int8_t *dst, int32_t len) 738195801Smav{ 739195801Smav int32_t i, j, blank; 740195801Smav 741195801Smav for (i = j = blank = 0 ; i < len-1; i++) { 742195801Smav if (blank && src[i] == ' ') continue; 743195801Smav if (blank && src[i] != ' ') { 744195801Smav dst[j++] = src[i]; 745195801Smav blank = 0; 746195801Smav continue; 747195801Smav } 748195801Smav if (src[i] == ' ') 749195801Smav blank = 1; 750195801Smav dst[j++] = src[i]; 751195801Smav } 752195801Smav dst[j] = 0x00; 753195801Smav} 754195801Smav#endif /* NATA > 0 */ 755195801Smav