1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * PCI IDE disk driver File: dev_ide_pci.c
6 * This is a simple driver for IDE hard disks that are connected
7 * to PCI IDE controllers, such as a Promise UltraXX.
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"
55 #include "cfe_device.h"
56 #include "cfe_ioctl.h"
58 #include "dev_ide_common.h"
65 /* *********************************************************************
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)
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
,
86 /* *********************************************************************
88 ********************************************************************* */
90 static cfe_devdisp_t idedrv_dispatch
= {
101 const cfe_driver_t pciidedrv
= {
109 const cfe_driver_t pciatapidrv
= {
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 */
131 /* *********************************************************************
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
)
154 data
= INW(reg
+disp
->baseaddr
);
157 *buf
++ = (data
>> 8) & 0xFF;
158 *buf
++ = (data
& 0xFF);
160 *buf
++ = (data
& 0xFF);
161 *buf
++ = (data
>> 8) & 0xFF;
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
)
185 data
= (uint16_t) buf
[1] + ((uint16_t) buf
[0] << 8);
187 data
= (uint16_t) buf
[0] + ((uint16_t) buf
[1] << 8);
190 OUTW(reg
+disp
->baseaddr
,data
);
200 /* *********************************************************************
201 * pciidedrv_find(devid,list)
203 * Find a particular product ID on the list. Return >= 0 if
207 * devid - product and device ID we have
208 * list - list of product and device IDs we're looking for
211 * index into table, or -1 if not found
212 ********************************************************************* */
213 static int pciidedrv_find(uint32_t devid
,uint32_t *list
)
217 while (list
[idx
] != 0xFFFFFFFF) {
218 if (list
[idx
] == devid
) return idx
;
226 /* *********************************************************************
227 * idedrv_probe(drv,probe_a,probe_b,probe_ptr)
229 * Our probe routine. Attach an IDE device to the firmware.
232 * drv - driver structure
233 * probe_a - physical address of IDE registers
234 * probe_b - unit number
235 * probe_ptr - not used
239 ********************************************************************* */
241 static void idedrv_probe(cfe_driver_t
*drv
,
242 unsigned long probe_a
, unsigned long probe_b
,
246 idecommon_dispatch_t
*disp
;
255 cfe_driver_t
*realdrv
;
261 * probe_ptr is unused.
267 if (pci_find_class(PCI_CLASS_MASS_STORAGE
,index
,&tag
) != 0) break;
269 devid
= pci_conf_read(tag
,PCI_ID_REG
);
271 if (pciidedrv_find(devid
,pciidedrv_devlist
) < 0) {
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");
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
) {
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
;
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);
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
);
355 xprintf("PCIIDE: %d controllers found\n",attached
);