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 "sbmips.h"
52#include "dev_ide_common.h"
53
54#include "dev_ide.h"
55
56/*  *********************************************************************
57    *  Macros
58    ********************************************************************* */
59
60/*  *********************************************************************
61    *  Forward declarations
62    ********************************************************************* */
63
64static void idedrv_probe(cfe_driver_t *drv,
65			      unsigned long probe_a, unsigned long probe_b,
66			      void *probe_ptr);
67
68/*  *********************************************************************
69    *  Device Dispatch
70    ********************************************************************* */
71
72static cfe_devdisp_t idedrv_dispatch = {
73    NULL,
74    NULL,
75    NULL,
76    NULL,
77    NULL,
78    NULL,
79    NULL,
80    NULL
81};
82
83const cfe_driver_t idedrv = {
84    "IDE disk",
85    "ide",
86    CFE_DEV_DISK,
87    &idedrv_dispatch,
88    idedrv_probe
89};
90
91const cfe_driver_t atapidrv = {
92    "ATAPI device",
93    "atapi",
94    CFE_DEV_DISK,
95    &idedrv_dispatch,
96    idedrv_probe
97};
98
99
100#define IDE_REG_ADDR_SHIFT	5
101
102
103/*  *********************************************************************
104    *  Port I/O routines
105    *
106    *  These routines are called back from the common code to do
107    *  I/O cycles to the IDE disk.  We provide routines for
108    *  reading and writing bytes, words, and strings of words.
109    ********************************************************************* */
110
111static uint8_t idedrv_inb(idecommon_dispatch_t *disp,uint32_t reg)
112{
113    reg <<= IDE_REG_ADDR_SHIFT;
114
115    return  (*((volatile uint8_t *) PHYS_TO_K1(reg+disp->baseaddr)));
116}
117
118static uint16_t idedrv_inw(idecommon_dispatch_t *disp,uint32_t reg)
119{
120    reg <<= IDE_REG_ADDR_SHIFT;
121
122    return *((volatile uint16_t *) PHYS_TO_K1((reg+disp->baseaddr)));
123}
124
125static void idedrv_ins(idecommon_dispatch_t *disp,uint32_t reg,hsaddr_t buf,int len)
126{
127    uint16_t data;
128
129    reg <<= IDE_REG_ADDR_SHIFT;
130
131    /* Do 16-bit reads/writes so that the byteswaps will work out right */
132
133    while (len > 0) {
134	data = *((volatile uint16_t *) PHYS_TO_K1(reg+disp->baseaddr));
135	hs_write16(buf,data);
136	buf += sizeof(uint16_t);
137	len--;
138	len--;
139	}
140
141}
142
143static void idedrv_outb(idecommon_dispatch_t *disp,uint32_t reg,uint8_t val)
144{
145    reg <<= IDE_REG_ADDR_SHIFT;
146
147    *((volatile uint8_t *) PHYS_TO_K1(reg+disp->baseaddr)) = (uint8_t) (val);
148}
149
150static void idedrv_outw(idecommon_dispatch_t *disp,uint32_t reg,uint16_t val)
151{
152    reg <<= IDE_REG_ADDR_SHIFT;
153
154    *((volatile uint16_t *) PHYS_TO_K1(reg+disp->baseaddr)) = val;
155}
156
157static void idedrv_outs(idecommon_dispatch_t *disp,uint32_t reg,hsaddr_t buf,int len)
158{
159    uint16_t data;
160
161    reg <<= IDE_REG_ADDR_SHIFT;
162
163    while (len > 0) {
164	data = hs_read16(buf);
165	buf += sizeof(uint16_t);
166	*((volatile uint16_t *) PHYS_TO_K1(reg+disp->baseaddr)) = data;
167	len--;
168	len--;
169	}
170}
171
172
173
174/*  *********************************************************************
175    *  idedrv_probe(drv,probe_a,probe_b,probe_ptr)
176    *
177    *  Our probe routine.  Attach an IDE device to the firmware.
178    *
179    *  Input parameters:
180    *  	   drv - driver structure
181    *  	   probe_a - physical address of IDE registers
182    *  	   probe_b - unit number
183    *  	   probe_ptr - not used
184    *
185    *  Return value:
186    *  	   nothing
187    ********************************************************************* */
188
189static void idedrv_probe(cfe_driver_t *drv,
190			      unsigned long probe_a, unsigned long probe_b,
191			      void *probe_ptr)
192{
193    idecommon_t *softc = NULL;
194    idecommon_dispatch_t *disp = NULL;
195    char descr[80];
196    char unitstr[50];
197    int res;
198    cfe_driver_t *realdrv;
199    int unit;
200
201    /*
202     * probe_a is the IDE base address
203     * probe_b is a bitmask of unit numbers to check
204     * probe_ptr is unused.
205     */
206
207    for (unit = 0; unit < 2; unit++) {
208
209	if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_NOPROBE) {
210	    continue;
211	    }
212
213	softc = (idecommon_t *) KMALLOC(sizeof(idecommon_t),0);
214	disp = (idecommon_dispatch_t *) KMALLOC(sizeof(idecommon_dispatch_t),0);
215
216	if (!softc || !disp) {
217	    if (softc) KFREE(softc);
218	    if (disp) KFREE(disp);
219	    return;		/* out of memory, stop here */
220	    }
221
222	softc->idecommon_addr = probe_a;
223	softc->idecommon_unit = unit;
224	softc->idecommon_deferprobe = 0;
225
226	disp->ref = softc;
227	disp->baseaddr = softc->idecommon_addr;
228	softc->idecommon_dispatch = disp;
229
230	disp->outb = idedrv_outb;
231	disp->outw = idedrv_outw;
232	disp->outs = idedrv_outs;
233
234	disp->inb = idedrv_inb;
235	disp->inw = idedrv_inw;
236	disp->ins = idedrv_ins;
237
238	/*
239	 * If we're autoprobing, do it now.  Loop back if we have
240	 * trouble finding the device.
241	 *
242	 * If not autoprobing, assume the device is there and set the
243	 * common routines to double check later.
244	 */
245
246	if (IDE_PROBE_GET_TYPE(probe_b,unit) == IDE_DEVTYPE_AUTO) {
247	    res = idecommon_devprobe(softc,1);
248	    if (res < 0) {
249		KFREE(softc);
250		KFREE(disp);
251		continue;
252		}
253	    }
254	else {
255	    idecommon_init(softc,IDE_PROBE_GET_TYPE(probe_b,unit));
256	    softc->idecommon_deferprobe = 1;
257	    }
258
259
260	xsprintf(descr,"%s unit %d at %08X",drv->drv_description,unit,probe_a);
261	xsprintf(unitstr,"%d",unit);
262
263	realdrv = (cfe_driver_t *) (softc->idecommon_atapi ? &atapidrv : &idedrv);
264	idecommon_attach(&idedrv_dispatch);
265
266	cfe_attach(realdrv,softc,unitstr,descr);
267	}
268}
269
270