1/*- 2 * Copyright (c) 1998 - 2008 S�ren Schmidt <sos@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include "opt_ata.h" 31#include <sys/param.h> 32#include <sys/module.h> 33#include <sys/systm.h> 34#include <sys/kernel.h> 35#include <sys/ata.h> 36#include <sys/bus.h> 37#include <sys/endian.h> 38#include <sys/malloc.h> 39#include <sys/lock.h> 40#include <sys/mutex.h> 41#include <sys/sema.h> 42#include <sys/taskqueue.h> 43#include <vm/uma.h> 44#include <machine/stdarg.h> 45#include <machine/resource.h> 46#include <machine/bus.h> 47#include <sys/rman.h> 48#include <dev/pci/pcivar.h> 49#include <dev/pci/pcireg.h> 50#include <dev/ata/ata-all.h> 51#include <dev/ata/ata-pci.h> 52#include <ata_if.h> 53 54#ifndef ATA_CAM 55struct ata_serialize { 56 struct mtx locked_mtx; 57 int locked_ch; 58 int restart_ch; 59}; 60#endif 61 62/* local prototypes */ 63static int ata_acard_chipinit(device_t dev); 64static int ata_acard_ch_attach(device_t dev); 65static int ata_acard_status(device_t dev); 66static int ata_acard_850_setmode(device_t dev, int target, int mode); 67static int ata_acard_86X_setmode(device_t dev, int target, int mode); 68#ifndef ATA_CAM 69static int ata_acard_chipdeinit(device_t dev); 70static int ata_serialize(device_t dev, int flags); 71static void ata_serialize_init(struct ata_serialize *serial); 72#endif 73 74/* misc defines */ 75#define ATP_OLD 1 76 77/* 78 * Acard chipset support functions 79 */ 80static int 81ata_acard_probe(device_t dev) 82{ 83 struct ata_pci_controller *ctlr = device_get_softc(dev); 84 static const struct ata_chip_id ids[] = 85 {{ ATA_ATP850R, 0, ATP_OLD, 0x00, ATA_UDMA2, "ATP850" }, 86 { ATA_ATP860A, 0, 0, 0x00, ATA_UDMA4, "ATP860A" }, 87 { ATA_ATP860R, 0, 0, 0x00, ATA_UDMA4, "ATP860R" }, 88 { ATA_ATP865A, 0, 0, 0x00, ATA_UDMA6, "ATP865A" }, 89 { ATA_ATP865R, 0, 0, 0x00, ATA_UDMA6, "ATP865R" }, 90 { 0, 0, 0, 0, 0, 0}}; 91 92 if (pci_get_vendor(dev) != ATA_ACARD_ID) 93 return ENXIO; 94 95 if (!(ctlr->chip = ata_match_chip(dev, ids))) 96 return ENXIO; 97 98 ata_set_desc(dev); 99 ctlr->chipinit = ata_acard_chipinit; 100#ifndef ATA_CAM 101 ctlr->chipdeinit = ata_acard_chipdeinit; 102#endif 103 return (BUS_PROBE_DEFAULT); 104} 105 106static int 107ata_acard_chipinit(device_t dev) 108{ 109 struct ata_pci_controller *ctlr = device_get_softc(dev); 110#ifndef ATA_CAM 111 struct ata_serialize *serial; 112#endif 113 114 if (ata_setup_interrupt(dev, ata_generic_intr)) 115 return ENXIO; 116 117 ctlr->ch_attach = ata_acard_ch_attach; 118 ctlr->ch_detach = ata_pci_ch_detach; 119 if (ctlr->chip->cfg1 == ATP_OLD) { 120 ctlr->setmode = ata_acard_850_setmode; 121#ifndef ATA_CAM 122 ctlr->locking = ata_serialize; 123 serial = malloc(sizeof(struct ata_serialize), 124 M_ATAPCI, M_WAITOK | M_ZERO); 125 ata_serialize_init(serial); 126 ctlr->chipset_data = serial; 127#else 128 /* Work around the lack of channel serialization in ATA_CAM. */ 129 ctlr->channels = 1; 130 device_printf(dev, "second channel ignored\n"); 131#endif 132 } 133 else 134 ctlr->setmode = ata_acard_86X_setmode; 135 return 0; 136} 137 138#ifndef ATA_CAM 139static int 140ata_acard_chipdeinit(device_t dev) 141{ 142 struct ata_pci_controller *ctlr = device_get_softc(dev); 143 struct ata_serialize *serial; 144 145 if (ctlr->chip->cfg1 == ATP_OLD) { 146 serial = ctlr->chipset_data; 147 mtx_destroy(&serial->locked_mtx); 148 free(serial, M_ATAPCI); 149 ctlr->chipset_data = NULL; 150 } 151 return (0); 152} 153#endif 154 155static int 156ata_acard_ch_attach(device_t dev) 157{ 158 struct ata_channel *ch = device_get_softc(dev); 159 160 /* setup the usual register normal pci style */ 161 if (ata_pci_ch_attach(dev)) 162 return ENXIO; 163 164 ch->hw.status = ata_acard_status; 165 ch->flags |= ATA_NO_ATAPI_DMA; 166 return 0; 167} 168 169static int 170ata_acard_status(device_t dev) 171{ 172 struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 173 struct ata_channel *ch = device_get_softc(dev); 174 175 if (ctlr->chip->cfg1 == ATP_OLD && 176 ATA_LOCKING(dev, ATA_LF_WHICH) != ch->unit) 177 return 0; 178 if (ch->dma.flags & ATA_DMA_ACTIVE) { 179 int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 180 181 if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) != 182 ATA_BMSTAT_INTERRUPT) 183 return 0; 184 ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR); 185 DELAY(1); 186 ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, 187 ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 188 DELAY(1); 189 } 190 if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) { 191 DELAY(100); 192 if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) 193 return 0; 194 } 195 return 1; 196} 197 198static int 199ata_acard_850_setmode(device_t dev, int target, int mode) 200{ 201 device_t parent = device_get_parent(dev); 202 struct ata_pci_controller *ctlr = device_get_softc(parent); 203 struct ata_channel *ch = device_get_softc(dev); 204 int devno = (ch->unit << 1) + target; 205 206 mode = min(mode, ctlr->chip->max_dma); 207 /* XXX SOS missing WDMA0+1 + PIO modes */ 208 if (mode >= ATA_WDMA2) { 209 u_int8_t reg54 = pci_read_config(parent, 0x54, 1); 210 211 reg54 &= ~(0x03 << (devno << 1)); 212 if (mode >= ATA_UDMA0) 213 reg54 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 1)); 214 pci_write_config(parent, 0x54, reg54, 1); 215 pci_write_config(parent, 0x4a, 0xa6, 1); 216 pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2); 217 } 218 /* we could set PIO mode timings, but we assume the BIOS did that */ 219 return (mode); 220} 221 222static int 223ata_acard_86X_setmode(device_t dev, int target, int mode) 224{ 225 device_t parent = device_get_parent(dev); 226 struct ata_pci_controller *ctlr = device_get_softc(parent); 227 struct ata_channel *ch = device_get_softc(dev); 228 int devno = (ch->unit << 1) + target; 229 230 mode = min(mode, ctlr->chip->max_dma); 231 /* XXX SOS missing WDMA0+1 + PIO modes */ 232 if (mode >= ATA_WDMA2) { 233 u_int16_t reg44 = pci_read_config(parent, 0x44, 2); 234 235 reg44 &= ~(0x000f << (devno << 2)); 236 if (mode >= ATA_UDMA0) 237 reg44 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 2)); 238 pci_write_config(parent, 0x44, reg44, 2); 239 pci_write_config(parent, 0x4a, 0xa6, 1); 240 pci_write_config(parent, 0x40 + devno, 0x31, 1); 241 } 242 /* we could set PIO mode timings, but we assume the BIOS did that */ 243 return (mode); 244} 245 246#ifndef ATA_CAM 247static void 248ata_serialize_init(struct ata_serialize *serial) 249{ 250 251 mtx_init(&serial->locked_mtx, "ATA serialize lock", NULL, MTX_DEF); 252 serial->locked_ch = -1; 253 serial->restart_ch = -1; 254} 255 256static int 257ata_serialize(device_t dev, int flags) 258{ 259 struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 260 struct ata_channel *ch = device_get_softc(dev); 261 struct ata_serialize *serial; 262 int res; 263 264 serial = ctlr->chipset_data; 265 266 mtx_lock(&serial->locked_mtx); 267 switch (flags) { 268 case ATA_LF_LOCK: 269 if (serial->locked_ch == -1) 270 serial->locked_ch = ch->unit; 271 if (serial->locked_ch != ch->unit) 272 serial->restart_ch = ch->unit; 273 break; 274 275 case ATA_LF_UNLOCK: 276 if (serial->locked_ch == ch->unit) { 277 serial->locked_ch = -1; 278 if (serial->restart_ch != -1) { 279 if ((ch = ctlr->interrupt[serial->restart_ch].argument)) { 280 serial->restart_ch = -1; 281 mtx_unlock(&serial->locked_mtx); 282 ata_start(dev); 283 return -1; 284 } 285 } 286 } 287 break; 288 289 case ATA_LF_WHICH: 290 break; 291 } 292 res = serial->locked_ch; 293 mtx_unlock(&serial->locked_mtx); 294 return res; 295} 296#endif 297 298ATA_DECLARE_DRIVER(ata_acard); 299