1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * IDE disk driver File: dev_ide.c 5 * 6 * This is a simple driver for IDE hard disks. The disks 7 * are expected to be connected to the generic bus (this 8 * driver doesn't support PCI). 9 * 10 * Author: Mitch Lichtenberg 11 * 12 ********************************************************************* 13 * 14 * Copyright 2000,2001,2002,2003 15 * Broadcom Corporation. All rights reserved. 16 * 17 * This software is furnished under license and may be used and 18 * copied only in accordance with the following terms and 19 * conditions. Subject to these conditions, you may download, 20 * copy, install, use, modify and distribute modified or unmodified 21 * copies of this software in source and/or binary form. No title 22 * or ownership is transferred hereby. 23 * 24 * 1) Any source code used, modified or distributed must reproduce 25 * and retain this copyright notice and list of conditions 26 * as they appear in the source file. 27 * 28 * 2) No right is granted to use any trade name, trademark, or 29 * logo of Broadcom Corporation. The "Broadcom Corporation" 30 * name may not be used to endorse or promote products derived 31 * from this software without the prior written permission of 32 * Broadcom Corporation. 33 * 34 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 35 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 36 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 37 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 38 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 39 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 40 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 42 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 44 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 45 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 46 * THE POSSIBILITY OF SUCH DAMAGE. 47 ********************************************************************* */ 48 49 50#include "cfe.h" 51#include "sbmips32.h" 52 53#include "dev_ide_common.h" 54 55#include "dev_ide.h" 56 57/* ********************************************************************* 58 * Macros 59 ********************************************************************* */ 60 61/* ********************************************************************* 62 * Forward declarations 63 ********************************************************************* */ 64 65static void idedrv_probe(cfe_driver_t *drv, 66 unsigned long probe_a, unsigned long probe_b, 67 void *probe_ptr); 68 69/* ********************************************************************* 70 * Device Dispatch 71 ********************************************************************* */ 72 73static cfe_devdisp_t idedrv_dispatch = { 74 NULL, 75 NULL, 76 NULL, 77 NULL, 78 NULL, 79 NULL, 80 NULL, 81 NULL 82}; 83 84const cfe_driver_t idedrv = { 85 "IDE disk", 86 "ide", 87 CFE_DEV_DISK, 88 &idedrv_dispatch, 89 idedrv_probe 90}; 91 92const cfe_driver_t atapidrv = { 93 "ATAPI device", 94 "atapi", 95 CFE_DEV_DISK, 96 &idedrv_dispatch, 97 idedrv_probe 98}; 99 100 101#define IDE_REG_ADDR_SHIFT 0 102 103 104/* ********************************************************************* 105 * Port I/O routines 106 * 107 * These routines are called back from the common code to do 108 * I/O cycles to the IDE disk. We provide routines for 109 * reading and writing bytes, words, and strings of words. 110 ********************************************************************* */ 111 112static uint8_t idedrv_inb(idecommon_dispatch_t *disp,uint32_t reg) 113{ 114 reg <<= IDE_REG_ADDR_SHIFT; 115 116 return (*((volatile uint8_t *) PHYS_TO_K1(reg+disp->baseaddr))); 117} 118 119static uint16_t idedrv_inw(idecommon_dispatch_t *disp,uint32_t reg) 120{ 121 reg <<= IDE_REG_ADDR_SHIFT; 122 123 return *((volatile uint16_t *) PHYS_TO_K1((reg+disp->baseaddr))); 124} 125 126static void idedrv_ins(idecommon_dispatch_t *disp,uint32_t reg,hsaddr_t buf,int len) 127{ 128 uint16_t data; 129 130 reg <<= IDE_REG_ADDR_SHIFT; 131 132 /* Do 16-bit reads/writes so that the byteswaps will work out right */ 133 134 while (len > 0) { 135 data = *((volatile uint16_t *) PHYS_TO_K1(reg+disp->baseaddr)); 136 hs_write16(buf,data); 137 buf += 2; 138 len--; 139 len--; 140 } 141 142} 143 144static void idedrv_outb(idecommon_dispatch_t *disp,uint32_t reg,uint8_t val) 145{ 146 reg <<= IDE_REG_ADDR_SHIFT; 147 148 *((volatile uint8_t *) PHYS_TO_K1(reg+disp->baseaddr)) = (uint8_t) (val); 149} 150 151static void idedrv_outw(idecommon_dispatch_t *disp,uint32_t reg,uint16_t val) 152{ 153 reg <<= IDE_REG_ADDR_SHIFT; 154 155 *((volatile uint16_t *) PHYS_TO_K1(reg+disp->baseaddr)) = val; 156} 157 158static void idedrv_outs(idecommon_dispatch_t *disp,uint32_t reg,hsaddr_t buf,int len) 159{ 160 uint16_t data; 161 162 reg <<= IDE_REG_ADDR_SHIFT; 163 164 while (len > 0) { 165 data = hs_read16(buf); 166 buf += 2; 167 *((volatile uint16_t *) PHYS_TO_K1(reg+disp->baseaddr)) = data; 168 len--; 169 len--; 170 } 171} 172 173 174 175/* ********************************************************************* 176 * idedrv_probe(drv,probe_a,probe_b,probe_ptr) 177 * 178 * Our probe routine. Attach an IDE device to the firmware. 179 * 180 * Input parameters: 181 * drv - driver structure 182 * probe_a - physical address of IDE registers 183 * probe_b - unit number 184 * probe_ptr - not used 185 * 186 * Return value: 187 * nothing 188 ********************************************************************* */ 189 190static void idedrv_probe(cfe_driver_t *drv, 191 unsigned long probe_a, unsigned long probe_b, 192 void *probe_ptr) 193{ 194 idecommon_t *softc = NULL; 195 idecommon_dispatch_t *disp = NULL; 196 char descr[80]; 197 char unitstr[50]; 198 int res; 199 cfe_driver_t *realdrv; 200 int unit; 201 202 /* 203 * probe_a is the IDE base address 204 * probe_b is a bitmask of unit numbers to check 205 * probe_ptr is unused. 206 */ 207 208 for (unit = 0; unit < 2; unit++) { 209 210 if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_NOPROBE) { 211 continue; 212 } 213 214 softc = (idecommon_t *) KMALLOC(sizeof(idecommon_t),0); 215 disp = (idecommon_dispatch_t *) KMALLOC(sizeof(idecommon_dispatch_t),0); 216 217 if (!softc || !disp) { 218 if (softc) KFREE(softc); 219 if (disp) KFREE(disp); 220 return; /* out of memory, stop here */ 221 } 222 223 softc->idecommon_addr = probe_a; 224 softc->idecommon_unit = unit; 225 softc->idecommon_deferprobe = 0; 226 227 disp->ref = softc; 228 disp->baseaddr = softc->idecommon_addr; 229 softc->idecommon_dispatch = disp; 230 231 disp->outb = idedrv_outb; 232 disp->outw = idedrv_outw; 233 disp->outs = idedrv_outs; 234 235 disp->inb = idedrv_inb; 236 disp->inw = idedrv_inw; 237 disp->ins = idedrv_ins; 238 239 /* 240 * If we're autoprobing, do it now. Loop back if we have 241 * trouble finding the device. 242 * 243 * If not autoprobing, assume the device is there and set the 244 * common routines to double check later. 245 */ 246 247 if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_AUTO) { 248 res = idecommon_devprobe(softc,1); 249 if (res < 0) { 250 KFREE(softc); 251 KFREE(disp); 252 continue; 253 } 254 } 255 else { 256 idecommon_init(softc,IDE_PROBE_GET_TYPE(probe_b,unit)); 257 softc->idecommon_deferprobe = 1; 258 } 259 260 261 xsprintf(descr,"%s unit %d at %08X",drv->drv_description,unit,probe_a); 262 xsprintf(unitstr,"%d",unit); 263 264 realdrv = (cfe_driver_t *) (softc->idecommon_atapi ? &atapidrv : &idedrv); 265 idecommon_attach(&idedrv_dispatch); 266 267 cfe_attach(realdrv,softc,unitstr,descr); 268 } 269} 270 271