1 1.12 phx /* $NetBSD: pciide.c,v 1.12 2012/01/22 13:08:16 phx Exp $ */ 2 1.1 nisimura 3 1.1 nisimura /*- 4 1.1 nisimura * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 1.1 nisimura * All rights reserved. 6 1.1 nisimura * 7 1.1 nisimura * This code is derived from software contributed to The NetBSD Foundation 8 1.1 nisimura * by Tohru Nishimura. 9 1.1 nisimura * 10 1.1 nisimura * Redistribution and use in source and binary forms, with or without 11 1.1 nisimura * modification, are permitted provided that the following conditions 12 1.1 nisimura * are met: 13 1.1 nisimura * 1. Redistributions of source code must retain the above copyright 14 1.1 nisimura * notice, this list of conditions and the following disclaimer. 15 1.1 nisimura * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 nisimura * notice, this list of conditions and the following disclaimer in the 17 1.1 nisimura * documentation and/or other materials provided with the distribution. 18 1.1 nisimura * 19 1.1 nisimura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 nisimura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 nisimura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 nisimura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 nisimura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 nisimura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 nisimura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 nisimura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 nisimura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 nisimura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 nisimura * POSSIBILITY OF SUCH DAMAGE. 30 1.1 nisimura */ 31 1.1 nisimura 32 1.1 nisimura #include <sys/param.h> 33 1.1 nisimura 34 1.1 nisimura #include <lib/libsa/stand.h> 35 1.1 nisimura 36 1.1 nisimura #include "globals.h" 37 1.1 nisimura 38 1.11 phx static void cmdidefix(struct dkdev_ata *); 39 1.11 phx static void apoidefix(struct dkdev_ata *); 40 1.11 phx static void iteidefix(struct dkdev_ata *); 41 1.3 phx 42 1.1 nisimura static uint32_t pciiobase = PCI_XIOBASE; 43 1.1 nisimura 44 1.1 nisimura struct myops { 45 1.11 phx void (*chipfix)(struct dkdev_ata *); 46 1.1 nisimura int (*presense)(struct dkdev_ata *, int); 47 1.1 nisimura }; 48 1.3 phx static struct myops defaultops = { NULL, NULL }; 49 1.1 nisimura static struct myops cmdideops = { cmdidefix, NULL }; 50 1.8 phx static struct myops apoideops = { apoidefix, NULL }; 51 1.10 phx static struct myops iteideops = { iteidefix, NULL }; 52 1.2 nisimura static struct myops *myops; 53 1.1 nisimura 54 1.1 nisimura int 55 1.1 nisimura pciide_match(unsigned tag, void *data) 56 1.1 nisimura { 57 1.1 nisimura unsigned v; 58 1.1 nisimura 59 1.1 nisimura v = pcicfgread(tag, PCI_ID_REG); 60 1.1 nisimura switch (v) { 61 1.1 nisimura case PCI_DEVICE(0x1095, 0x0680): /* SiI 0680 IDE */ 62 1.2 nisimura myops = &cmdideops; 63 1.2 nisimura return 1; 64 1.9 nisimura case PCI_DEVICE(0x1106, 0x0571): /* VIA 82C586A/B/686A/B IDE */ 65 1.8 phx case PCI_DEVICE(0x1106, 0x1571): /* VIA 82C586 IDE */ 66 1.8 phx case PCI_DEVICE(0x1106, 0x3164): /* VIA VT6410 RAID IDE */ 67 1.8 phx myops = &apoideops; 68 1.8 phx return 1; 69 1.1 nisimura case PCI_DEVICE(0x1283, 0x8211): /* ITE 8211 IDE */ 70 1.10 phx myops = &iteideops; 71 1.10 phx return 1; 72 1.1 nisimura case PCI_DEVICE(0x10ad, 0x0105): /* Symphony Labs 82C105 IDE */ 73 1.1 nisimura case PCI_DEVICE(0x10b8, 0x5229): /* ALi IDE */ 74 1.2 nisimura case PCI_DEVICE(0x1191, 0x0008): /* ACARD ATP865 */ 75 1.6 phx case PCI_DEVICE(0x1191, 0x0009): /* ACARD ATP865A */ 76 1.3 phx myops = &defaultops; 77 1.1 nisimura return 1; 78 1.1 nisimura } 79 1.1 nisimura return 0; 80 1.1 nisimura } 81 1.1 nisimura 82 1.1 nisimura void * 83 1.1 nisimura pciide_init(unsigned tag, void *data) 84 1.1 nisimura { 85 1.12 phx static int cntrl = 0; 86 1.12 phx int native, n, retries; 87 1.1 nisimura unsigned val; 88 1.1 nisimura struct dkdev_ata *l; 89 1.1 nisimura 90 1.1 nisimura l = alloc(sizeof(struct dkdev_ata)); 91 1.1 nisimura memset(l, 0, sizeof(struct dkdev_ata)); 92 1.1 nisimura l->iobuf = allocaligned(512, 16); 93 1.1 nisimura l->tag = tag; 94 1.1 nisimura 95 1.8 phx /* chipset specific fixes */ 96 1.8 phx if (myops->chipfix) 97 1.11 phx (*myops->chipfix)(l); 98 1.8 phx 99 1.1 nisimura val = pcicfgread(tag, PCI_CLASS_REG); 100 1.5 phx native = PCI_CLASS(val) != PCI_CLASS_IDE || 101 1.5 phx (PCI_INTERFACE(val) & 05) != 0; 102 1.8 phx 103 1.1 nisimura if (native) { 104 1.1 nisimura /* native, use BAR 01234 */ 105 1.1 nisimura l->bar[0] = pciiobase + (pcicfgread(tag, 0x10) &~ 01); 106 1.1 nisimura l->bar[1] = pciiobase + (pcicfgread(tag, 0x14) &~ 01); 107 1.1 nisimura l->bar[2] = pciiobase + (pcicfgread(tag, 0x18) &~ 01); 108 1.1 nisimura l->bar[3] = pciiobase + (pcicfgread(tag, 0x1c) &~ 01); 109 1.1 nisimura l->bar[4] = pciiobase + (pcicfgread(tag, 0x20) &~ 01); 110 1.1 nisimura l->chan[0].cmd = l->bar[0]; 111 1.1 nisimura l->chan[0].ctl = l->chan[0].alt = l->bar[1] | 02; 112 1.1 nisimura l->chan[0].dma = l->bar[4] + 0x0; 113 1.1 nisimura l->chan[1].cmd = l->bar[2]; 114 1.1 nisimura l->chan[1].ctl = l->chan[1].alt = l->bar[3] | 02; 115 1.1 nisimura l->chan[1].dma = l->bar[4] + 0x8; 116 1.1 nisimura } 117 1.1 nisimura else { 118 1.1 nisimura /* legacy */ 119 1.1 nisimura l->bar[0]= pciiobase + 0x1f0; 120 1.1 nisimura l->bar[1]= pciiobase + 0x3f4; 121 1.1 nisimura l->bar[2]= pciiobase + 0x170; 122 1.1 nisimura l->bar[3]= pciiobase + 0x374; 123 1.1 nisimura l->chan[0].cmd = l->bar[0]; 124 1.1 nisimura l->chan[0].ctl = l->chan[0].alt = l->bar[1] | 02; 125 1.1 nisimura l->chan[0].dma = 0; 126 1.1 nisimura l->chan[1].cmd = l->bar[2]; 127 1.1 nisimura l->chan[1].ctl = l->chan[1].alt = l->bar[3] | 02; 128 1.1 nisimura l->chan[1].dma = 0; 129 1.1 nisimura } 130 1.1 nisimura 131 1.1 nisimura for (n = 0; n < 2; n++) { 132 1.12 phx if (myops->presense != NULL && (*myops->presense)(l, n) == 0) { 133 1.12 phx DPRINTF(("channel %d not present\n", n)); 134 1.12 phx l->presense[n] = 0; 135 1.12 phx continue; 136 1.12 phx } else if (get_drive_config(cntrl * 2 + n) == 0) { 137 1.12 phx DPRINTF(("channel %d disabled by config\n", n)); 138 1.12 phx l->presense[n] = 0; 139 1.12 phx continue; 140 1.12 phx } 141 1.12 phx 142 1.12 phx if (atachkpwr(l, n) != ATA_PWR_ACTIVE) { 143 1.12 phx /* drive is probably sleeping, wake it up */ 144 1.12 phx for (retries = 0; retries < 10; retries++) { 145 1.12 phx wakeup_drive(l, n); 146 1.12 phx DPRINTF(("channel %d spinning up...\n", n)); 147 1.12 phx delay(1000 * 1000); 148 1.12 phx l->presense[n] = perform_atareset(l, n); 149 1.12 phx if (atachkpwr(l, n) == ATA_PWR_ACTIVE) 150 1.12 phx break; 151 1.12 phx } 152 1.12 phx } else { 153 1.1 nisimura /* check to see whether soft reset works */ 154 1.12 phx DPRINTF(("channel %d active\n", n)); 155 1.1 nisimura l->presense[n] = perform_atareset(l, n); 156 1.12 phx } 157 1.10 phx 158 1.1 nisimura if (l->presense[n]) 159 1.1 nisimura printf("channel %d present\n", n); 160 1.1 nisimura } 161 1.1 nisimura 162 1.12 phx cntrl++; /* increment controller number for next call */ 163 1.1 nisimura return l; 164 1.1 nisimura } 165 1.1 nisimura 166 1.11 phx static void 167 1.1 nisimura cmdidefix(struct dkdev_ata *l) 168 1.1 nisimura { 169 1.8 phx unsigned v; 170 1.1 nisimura 171 1.1 nisimura v = pcicfgread(l->tag, 0x80); 172 1.1 nisimura pcicfgwrite(l->tag, 0x80, (v & ~0xff) | 0x01); 173 1.1 nisimura v = pcicfgread(l->tag, 0x84); 174 1.1 nisimura pcicfgwrite(l->tag, 0x84, (v & ~0xff) | 0x01); 175 1.1 nisimura v = pcicfgread(l->tag, 0xa4); 176 1.1 nisimura pcicfgwrite(l->tag, 0xa4, (v & ~0xffff) | 0x328a); 177 1.1 nisimura v = pcicfgread(l->tag, 0xb4); 178 1.1 nisimura pcicfgwrite(l->tag, 0xb4, (v & ~0xffff) | 0x328a); 179 1.1 nisimura } 180 1.8 phx 181 1.11 phx static void 182 1.8 phx apoidefix(struct dkdev_ata *l) 183 1.8 phx { 184 1.8 phx unsigned v; 185 1.8 phx 186 1.8 phx /* enable primary and secondary channel */ 187 1.8 phx v = pcicfgread(l->tag, 0x40) & ~0x03; 188 1.8 phx pcicfgwrite(l->tag, 0x40, v | 0x03); 189 1.8 phx } 190 1.10 phx 191 1.11 phx static void 192 1.10 phx iteidefix(struct dkdev_ata *l) 193 1.10 phx { 194 1.10 phx unsigned v; 195 1.10 phx 196 1.10 phx /* set PCI mode and 66Mhz reference clock, disable IT8212 RAID */ 197 1.10 phx v = pcicfgread(l->tag, 0x50); 198 1.10 phx pcicfgwrite(l->tag, 0x50, v & ~0x83); 199 1.10 phx 200 1.10 phx /* i/o configuration, enable channels, cables, IORDY */ 201 1.10 phx v = pcicfgread(l->tag, 0x40); 202 1.10 phx pcicfgwrite(l->tag, 0x40, (v & ~0xffffff) | 0x36a0f3); 203 1.10 phx } 204