summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/dev/dev_ide_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/dev/dev_ide_pci.c')
-rw-r--r--cfe/cfe/dev/dev_ide_pci.c358
1 files changed, 358 insertions, 0 deletions
diff --git a/cfe/cfe/dev/dev_ide_pci.c b/cfe/cfe/dev/dev_ide_pci.c
new file mode 100644
index 0000000..ecf4c2a
--- /dev/null
+++ b/cfe/cfe/dev/dev_ide_pci.c
@@ -0,0 +1,358 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PCI IDE disk driver File: dev_ide_pci.c
+ *
+ * This is a simple driver for IDE hard disks that are connected
+ * to PCI IDE controllers, such as a Promise UltraXX.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "cfe_timer.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+
+#include "dev_ide_common.h"
+
+#include "dev_ide.h"
+
+#include "pcivar.h"
+#include "pcireg.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define _BYTESWAP_ /* don't byteswap these disks */
+
+#define OUTB(x,y) outb(x,y)
+#define OUTW(x,y) outw(x,y)
+#define INB(x) inb(x)
+#define INW(x) inw(x)
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+extern void _wbflush(void);
+
+static void idedrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+/* *********************************************************************
+ * Device Dispatch
+ ********************************************************************* */
+
+static cfe_devdisp_t idedrv_dispatch = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t pciidedrv = {
+ "PCI IDE disk",
+ "ide",
+ CFE_DEV_DISK,
+ &idedrv_dispatch,
+ idedrv_probe
+};
+
+const cfe_driver_t pciatapidrv = {
+ "PCI ATAPI device",
+ "atapi",
+ CFE_DEV_DISK,
+ &idedrv_dispatch,
+ idedrv_probe
+};
+
+/* *********************************************************************
+ * Supported PCI devices
+ ********************************************************************* */
+
+#define DEVID(vid,pid) (((pid)<<16)|(vid))
+
+static uint32_t pciidedrv_devlist[] = {
+ DEVID(0x105a,0x4d33), /* Promise Ultra33 */
+ DEVID(0x1095,0x0649), /* CMD PCI0649 */
+ DEVID(0x1095,0x0648), /* CMD PCI0648 */
+ 0xFFFFFFFF
+};
+
+
+/* *********************************************************************
+ * Port I/O routines
+ *
+ * These routines are called back from the common code to do
+ * I/O cycles to the IDE disk. We provide routines for
+ * reading and writing bytes, words, and strings of words.
+ ********************************************************************* */
+
+static uint8_t idedrv_inb(idecommon_dispatch_t *disp,uint32_t reg)
+{
+ return INB(reg+disp->baseaddr);
+}
+
+static uint16_t idedrv_inw(idecommon_dispatch_t *disp,uint32_t reg)
+{
+ return INW(reg+disp->baseaddr);
+}
+
+static void idedrv_ins(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len)
+{
+ uint16_t data;
+
+ while (len > 0) {
+ data = INW(reg+disp->baseaddr);
+
+#ifdef _BYTESWAP_
+ *buf++ = (data >> 8) & 0xFF;
+ *buf++ = (data & 0xFF);
+#else
+ *buf++ = (data & 0xFF);
+ *buf++ = (data >> 8) & 0xFF;
+#endif
+ len--;
+ len--;
+ }
+
+}
+
+static void idedrv_outb(idecommon_dispatch_t *disp,uint32_t reg,uint8_t val)
+{
+ OUTB(reg+disp->baseaddr,val);
+}
+
+static void idedrv_outw(idecommon_dispatch_t *disp,uint32_t reg,uint16_t val)
+{
+ OUTW(reg+disp->baseaddr,val);
+}
+
+static void idedrv_outs(idecommon_dispatch_t *disp,uint32_t reg,uint8_t *buf,int len)
+{
+ uint16_t data;
+
+ while (len > 0) {
+#ifdef _BYTESWAP_
+ data = (uint16_t) buf[1] + ((uint16_t) buf[0] << 8);
+#else
+ data = (uint16_t) buf[0] + ((uint16_t) buf[1] << 8);
+#endif
+
+ OUTW(reg+disp->baseaddr,data);
+
+ buf++;
+ buf++;
+ len--;
+ len--;
+ }
+}
+
+
+/* *********************************************************************
+ * pciidedrv_find(devid,list)
+ *
+ * Find a particular product ID on the list. Return >= 0 if
+ * the ID is valid.
+ *
+ * Input parameters:
+ * devid - product and device ID we have
+ * list - list of product and device IDs we're looking for
+ *
+ * Return value:
+ * index into table, or -1 if not found
+ ********************************************************************* */
+static int pciidedrv_find(uint32_t devid,uint32_t *list)
+{
+ int idx = 0;
+
+ while (list[idx] != 0xFFFFFFFF) {
+ if (list[idx] == devid) return idx;
+ idx++;
+ }
+
+ return -1;
+}
+
+
+/* *********************************************************************
+ * idedrv_probe(drv,probe_a,probe_b,probe_ptr)
+ *
+ * Our probe routine. Attach an IDE device to the firmware.
+ *
+ * Input parameters:
+ * drv - driver structure
+ * probe_a - physical address of IDE registers
+ * probe_b - unit number
+ * probe_ptr - not used
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void idedrv_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ idecommon_t *softc;
+ idecommon_dispatch_t *disp;
+ char descr[80];
+ char unitstr[50];
+ pcitag_t tag;
+ int index;
+ uint32_t devid;
+ uint32_t reg;
+ int res;
+ int unit;
+ cfe_driver_t *realdrv;
+ int attached = 0;
+
+ /*
+ * probe_a is unused
+ * probe_b is unused
+ * probe_ptr is unused.
+ */
+
+ index = 0;
+
+ for (;;) {
+ if (pci_find_class(PCI_CLASS_MASS_STORAGE,index,&tag) != 0) break;
+ index++;
+ devid = pci_conf_read(tag,PCI_ID_REG);
+
+ if (pciidedrv_find(devid,pciidedrv_devlist) < 0) {
+ continue;
+ }
+
+
+ reg = pci_conf_read(tag,PCI_MAPREG(0));
+
+ if (PCI_MAPREG_TYPE(reg) != PCI_MAPREG_TYPE_IO) {
+ xprintf("Skipping this IDE device, we don't do memory mapped IDE yet\n");
+ continue;
+ }
+
+ reg &= ~PCI_MAPREG_TYPE_MASK;
+
+ for (unit = 0; unit < 2; unit++) {
+
+ /*
+ * If we've deliberately disabled probing of this
+ * device, then skip it.
+ */
+
+ if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_NOPROBE) {
+ continue;
+ }
+
+ softc = (idecommon_t *) KMALLOC(sizeof(idecommon_t),0);
+ disp = (idecommon_dispatch_t *) KMALLOC(sizeof(idecommon_dispatch_t),0);
+
+ if (!softc || !disp) {
+ if (softc) KFREE(softc);
+ if (disp) KFREE(disp);
+ return; /* out of memory, stop here */
+ }
+
+
+ softc->idecommon_addr = reg;
+ disp->ref = softc;
+ disp->baseaddr = softc->idecommon_addr;
+ softc->idecommon_deferprobe = 0;
+ softc->idecommon_dispatch = disp;
+ softc->idecommon_unit = unit;
+
+ disp->outb = idedrv_outb;
+ disp->outw = idedrv_outw;
+ disp->outs = idedrv_outs;
+
+ disp->inb = idedrv_inb;
+ disp->inw = idedrv_inw;
+ disp->ins = idedrv_ins;
+
+ /*
+ * If we're autoprobing, do it now. Loop back if we have
+ * trouble finding the device.
+ *
+ * If not autoprobing, assume the device is there and set the
+ * common routines to double check later.
+ */
+
+ if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_AUTO) {
+ res = idecommon_devprobe(softc,1);
+ if (res < 0) {
+ KFREE(softc);
+ KFREE(disp);
+ continue;
+ }
+ }
+ else {
+ idecommon_init(softc,IDE_PROBE_GET_TYPE(probe_b,unit));
+ softc->idecommon_deferprobe = 1;
+ }
+
+ xsprintf(descr,"%s unit %d at I/O %04X",drv->drv_description,
+ softc->idecommon_unit,softc->idecommon_addr);
+ xsprintf(unitstr,"%d",unit);
+
+ realdrv = (cfe_driver_t *) (softc->idecommon_atapi ? &pciatapidrv : &pciidedrv);
+
+ idecommon_attach(&idedrv_dispatch);
+ cfe_attach(realdrv,softc,unitstr,descr);
+ attached++;
+ }
+
+ }
+
+ xprintf("PCIIDE: %d controllers found\n",attached);
+}
+
+