RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / cfe / cfe / dev / dev_ide_pci.c
blobe2c6849a148510039556ded31ab30edb895e7660
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * PCI IDE disk driver File: dev_ide_pci.c
5 *
6 * This is a simple driver for IDE hard disks that are connected
7 * to PCI IDE controllers, such as a Promise UltraXX.
8 *
9 * Author: Mitch Lichtenberg (mpl@broadcom.com)
11 *********************************************************************
13 * Copyright 2000,2001,2002,2003
14 * Broadcom Corporation. All rights reserved.
16 * This software is furnished under license and may be used and
17 * copied only in accordance with the following terms and
18 * conditions. Subject to these conditions, you may download,
19 * copy, install, use, modify and distribute modified or unmodified
20 * copies of this software in source and/or binary form. No title
21 * or ownership is transferred hereby.
23 * 1) Any source code used, modified or distributed must reproduce
24 * and retain this copyright notice and list of conditions
25 * as they appear in the source file.
27 * 2) No right is granted to use any trade name, trademark, or
28 * logo of Broadcom Corporation. The "Broadcom Corporation"
29 * name may not be used to endorse or promote products derived
30 * from this software without the prior written permission of
31 * Broadcom Corporation.
33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45 * THE POSSIBILITY OF SUCH DAMAGE.
46 ********************************************************************* */
49 #include "lib_types.h"
50 #include "lib_malloc.h"
51 #include "lib_printf.h"
52 #include "lib_string.h"
53 #include "cfe_timer.h"
54 #include "cfe_iocb.h"
55 #include "cfe_device.h"
56 #include "cfe_ioctl.h"
58 #include "dev_ide_common.h"
60 #include "dev_ide.h"
62 #include "pcivar.h"
63 #include "pcireg.h"
65 /* *********************************************************************
66 * Macros
67 ********************************************************************* */
69 #define _BYTESWAP_ /* don't byteswap these disks */
71 #define OUTB(x,y) outb(x,y)
72 #define OUTW(x,y) outw(x,y)
73 #define INB(x) inb(x)
74 #define INW(x) inw(x)
76 /* *********************************************************************
77 * Forward declarations
78 ********************************************************************* */
80 extern void _wbflush(void);
82 static void idedrv_probe(cfe_driver_t *drv,
83 unsigned long probe_a, unsigned long probe_b,
84 void *probe_ptr);
86 /* *********************************************************************
87 * Device Dispatch
88 ********************************************************************* */
90 static cfe_devdisp_t idedrv_dispatch = {
91 NULL,
92 NULL,
93 NULL,
94 NULL,
95 NULL,
96 NULL,
97 NULL,
98 NULL
101 const cfe_driver_t pciidedrv = {
102 "PCI IDE disk",
103 "ide",
104 CFE_DEV_DISK,
105 &idedrv_dispatch,
106 idedrv_probe
109 const cfe_driver_t pciatapidrv = {
110 "PCI ATAPI device",
111 "atapi",
112 CFE_DEV_DISK,
113 &idedrv_dispatch,
114 idedrv_probe
117 /* *********************************************************************
118 * Supported PCI devices
119 ********************************************************************* */
121 #define DEVID(vid,pid) (((pid)<<16)|(vid))
123 static uint32_t pciidedrv_devlist[] = {
124 DEVID(0x105a,0x4d33), /* Promise Ultra33 */
125 DEVID(0x1095,0x0649), /* CMD PCI0649 */
126 DEVID(0x1095,0x0648), /* CMD PCI0648 */
127 0xFFFFFFFF
131 /* *********************************************************************
132 * Port I/O routines
134 * These routines are called back from the common code to do
135 * I/O cycles to the IDE disk. We provide routines for
136 * reading and writing bytes, words, and strings of words.
137 ********************************************************************* */
139 static uint8_t idedrv_inb(idecommon_dispatch_t *disp,uint32_t reg)
141 return INB(reg+disp->baseaddr);
144 static uint16_t idedrv_inw(idecommon_dispatch_t *disp,uint32_t reg)
146 return INW(reg+disp->baseaddr);
149 static void idedrv_ins(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len)
151 uint16_t data;
153 while (len > 0) {
154 data = INW(reg+disp->baseaddr);
156 #ifdef _BYTESWAP_
157 *buf++ = (data >> 8) & 0xFF;
158 *buf++ = (data & 0xFF);
159 #else
160 *buf++ = (data & 0xFF);
161 *buf++ = (data >> 8) & 0xFF;
162 #endif
163 len--;
164 len--;
169 static void idedrv_outb(idecommon_dispatch_t *disp,uint32_t reg,uint8_t val)
171 OUTB(reg+disp->baseaddr,val);
174 static void idedrv_outw(idecommon_dispatch_t *disp,uint32_t reg,uint16_t val)
176 OUTW(reg+disp->baseaddr,val);
179 static void idedrv_outs(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len)
181 uint16_t data;
183 while (len > 0) {
184 #ifdef _BYTESWAP_
185 data = (uint16_t) buf[1] + ((uint16_t) buf[0] << 8);
186 #else
187 data = (uint16_t) buf[0] + ((uint16_t) buf[1] << 8);
188 #endif
190 OUTW(reg+disp->baseaddr,data);
192 buf++;
193 buf++;
194 len--;
195 len--;
200 /* *********************************************************************
201 * pciidedrv_find(devid,list)
203 * Find a particular product ID on the list. Return >= 0 if
204 * the ID is valid.
206 * Input parameters:
207 * devid - product and device ID we have
208 * list - list of product and device IDs we're looking for
210 * Return value:
211 * index into table, or -1 if not found
212 ********************************************************************* */
213 static int pciidedrv_find(uint32_t devid,uint32_t *list)
215 int idx = 0;
217 while (list[idx] != 0xFFFFFFFF) {
218 if (list[idx] == devid) return idx;
219 idx++;
222 return -1;
226 /* *********************************************************************
227 * idedrv_probe(drv,probe_a,probe_b,probe_ptr)
229 * Our probe routine. Attach an IDE device to the firmware.
231 * Input parameters:
232 * drv - driver structure
233 * probe_a - physical address of IDE registers
234 * probe_b - unit number
235 * probe_ptr - not used
237 * Return value:
238 * nothing
239 ********************************************************************* */
241 static void idedrv_probe(cfe_driver_t *drv,
242 unsigned long probe_a, unsigned long probe_b,
243 void *probe_ptr)
245 idecommon_t *softc;
246 idecommon_dispatch_t *disp;
247 char descr[80];
248 char unitstr[50];
249 pcitag_t tag;
250 int index;
251 uint32_t devid;
252 uint32_t reg;
253 int res;
254 int unit;
255 cfe_driver_t *realdrv;
256 int attached = 0;
259 * probe_a is unused
260 * probe_b is unused
261 * probe_ptr is unused.
264 index = 0;
266 for (;;) {
267 if (pci_find_class(PCI_CLASS_MASS_STORAGE,index,&tag) != 0) break;
268 index++;
269 devid = pci_conf_read(tag,PCI_ID_REG);
271 if (pciidedrv_find(devid,pciidedrv_devlist) < 0) {
272 continue;
276 reg = pci_conf_read(tag,PCI_MAPREG(0));
278 if (PCI_MAPREG_TYPE(reg) != PCI_MAPREG_TYPE_IO) {
279 xprintf("Skipping this IDE device, we don't do memory mapped IDE yet\n");
280 continue;
283 reg &= ~PCI_MAPREG_TYPE_MASK;
285 for (unit = 0; unit < 2; unit++) {
288 * If we've deliberately disabled probing of this
289 * device, then skip it.
292 if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_NOPROBE) {
293 continue;
296 softc = (idecommon_t *) KMALLOC(sizeof(idecommon_t),0);
297 disp = (idecommon_dispatch_t *) KMALLOC(sizeof(idecommon_dispatch_t),0);
299 if (!softc || !disp) {
300 if (softc) KFREE(softc);
301 if (disp) KFREE(disp);
302 return; /* out of memory, stop here */
306 softc->idecommon_addr = reg;
307 disp->ref = softc;
308 disp->baseaddr = softc->idecommon_addr;
309 softc->idecommon_deferprobe = 0;
310 softc->idecommon_dispatch = disp;
311 softc->idecommon_unit = unit;
313 disp->outb = idedrv_outb;
314 disp->outw = idedrv_outw;
315 disp->outs = idedrv_outs;
317 disp->inb = idedrv_inb;
318 disp->inw = idedrv_inw;
319 disp->ins = idedrv_ins;
322 * If we're autoprobing, do it now. Loop back if we have
323 * trouble finding the device.
325 * If not autoprobing, assume the device is there and set the
326 * common routines to double check later.
329 if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_AUTO) {
330 res = idecommon_devprobe(softc,1);
331 if (res < 0) {
332 KFREE(softc);
333 KFREE(disp);
334 continue;
337 else {
338 idecommon_init(softc,IDE_PROBE_GET_TYPE(probe_b,unit));
339 softc->idecommon_deferprobe = 1;
342 xsprintf(descr,"%s unit %d at I/O %04X",drv->drv_description,
343 softc->idecommon_unit,softc->idecommon_addr);
344 xsprintf(unitstr,"%d",unit);
346 realdrv = (cfe_driver_t *) (softc->idecommon_atapi ? &pciatapidrv : &pciidedrv);
348 idecommon_attach(&idedrv_dispatch);
349 cfe_attach(realdrv,softc,unitstr,descr);
350 attached++;
355 xprintf("PCIIDE: %d controllers found\n",attached);