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