1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * PCMCIA IDE disk driver File: dev_pcmcia_pcic.c
6 * This is a stub driver for PCMCIA disks that are connected to
7 * an Intel-style ISA PCIC chip. Don't have one of those on
8 * your BCM12500 eval board? I hope not; this one is just used
9 * on the Algorithmics P5064 so I can learn about the quirks of
10 * real PCMCIA disks. See dev_pcmcia.c for the BCM12500 driver.
12 * Author: Mitch Lichtenberg (mpl@broadcom.com)
14 *********************************************************************
16 * Copyright 2000,2001,2002,2003
17 * Broadcom Corporation. All rights reserved.
19 * This software is furnished under license and may be used and
20 * copied only in accordance with the following terms and
21 * conditions. Subject to these conditions, you may download,
22 * copy, install, use, modify and distribute modified or unmodified
23 * copies of this software in source and/or binary form. No title
24 * or ownership is transferred hereby.
26 * 1) Any source code used, modified or distributed must reproduce
27 * and retain this copyright notice and list of conditions
28 * as they appear in the source file.
30 * 2) No right is granted to use any trade name, trademark, or
31 * logo of Broadcom Corporation. The "Broadcom Corporation"
32 * name may not be used to endorse or promote products derived
33 * from this software without the prior written permission of
34 * Broadcom Corporation.
36 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
37 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
38 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
40 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
41 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
42 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
45 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
46 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
47 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
48 * THE POSSIBILITY OF SUCH DAMAGE.
49 ********************************************************************* */
53 #include "lib_types.h"
54 #include "lib_malloc.h"
55 #include "lib_printf.h"
56 #include "lib_string.h"
57 #include "cfe_timer.h"
59 #include "cfe_device.h"
60 #include "cfe_ioctl.h"
61 #include "cfe_error.h"
62 #include "cfe_console.h"
64 #include "dev_ide_common.h"
70 /* *********************************************************************
72 ********************************************************************* */
75 #define PCMCIA_CARDPRESENT 1
78 #define OUTB(x,y) outb(x,y)
81 #define PCICSET(reg,val) OUTB(0x3E0,(reg)); OUTB(0x3E1,(val))
82 #define PCICGET(reg,val) OUTB(0x3E0,(reg)); val = INB(0x3E1)
83 #define WINBASE(x) (0x10+(x)*8)
85 /* *********************************************************************
87 ********************************************************************* */
89 extern void _wbflush(void);
91 /* *********************************************************************
92 * Forward declarations
93 ********************************************************************* */
95 static void pcmcia_ata_probe(cfe_driver_t
*drv
,
96 unsigned long probe_a
, unsigned long probe_b
,
100 static int pcmcia_ata_open(cfe_devctx_t
*ctx
);
102 /* *********************************************************************
104 ********************************************************************* */
106 const static cfe_devdisp_t pcmcia_ata_dispatch
= {
117 const cfe_driver_t pcmcia_pcic_drv
= {
121 &pcmcia_ata_dispatch
,
126 /* *********************************************************************
129 * These routines are called back from the common code to do
130 * I/O cycles to the IDE disk. We provide routines for
131 * reading and writing bytes, words, and strings of words.
132 ********************************************************************* */
135 static uint8_t pcmcia_inb(idecommon_dispatch_t
*disp
,uint32_t reg
)
137 return *((volatile uint8_t *) PHYS_TO_K1(reg
+disp
->baseaddr
));
140 static uint16_t pcmcia_inw(idecommon_dispatch_t
*disp
,uint32_t reg
)
142 return *((volatile uint16_t *) PHYS_TO_K1((reg
+disp
->baseaddr
)));
145 static void pcmcia_ins(idecommon_dispatch_t
*disp
,uint32_t reg
,uint8_t *buf
,int len
)
150 data
= *((volatile uint16_t *) PHYS_TO_K1(reg
+disp
->baseaddr
));
153 *buf
++ = (data
>> 8) & 0xFF;
154 *buf
++ = (data
& 0xFF);
156 *buf
++ = (data
& 0xFF);
157 *buf
++ = (data
>> 8) & 0xFF;
165 static void pcmcia_outb(idecommon_dispatch_t
*disp
,uint32_t reg
,uint8_t val
)
167 *((volatile uint8_t *) PHYS_TO_K1(reg
+disp
->baseaddr
)) = val
;
171 static void pcmcia_outw(idecommon_dispatch_t
*disp
,uint32_t reg
,uint16_t val
)
173 *((volatile uint16_t *) PHYS_TO_K1(reg
+disp
->baseaddr
)) = val
;
177 static void pcmcia_outs(idecommon_dispatch_t
*disp
,uint32_t reg
,uint8_t *buf
,int len
)
183 data
= (uint16_t) buf
[1] + ((uint16_t) buf
[0] << 8);
185 data
= (uint16_t) buf
[0] + ((uint16_t) buf
[1] << 8);
188 *((volatile uint16_t *) PHYS_TO_K1(reg
+disp
->baseaddr
)) = data
;
199 /* *********************************************************************
202 * Returns TRUE if a PCMCIA card (any card) is present in the
209 * true if card is present.
210 ********************************************************************* */
212 static int pcic_cardpresent(void)
220 return (det
== 0x0C);
223 /* *********************************************************************
226 * Turn on the power to the PCMCIA slot.
233 ********************************************************************* */
235 static void pcic_poweron(void)
244 /* *********************************************************************
245 * pcic_mapwin(win,sysstart,sysend,pcmciaoffset,attr)
247 * Map a window using the PCIC.
250 * win - window number (0-4)
251 * sysstart,sysend - ISA address of the beginning and end of
253 * pcmciaoffset - offset into PCCARD space that the window
254 * should be mapped to
255 * attr - nonzero to map attribute memory
259 ********************************************************************* */
261 static void pcic_mapwin(int win
,uint32_t sysstart
,uint32_t sysend
,uint32_t pcmciaoffset
,int attr
)
267 * Disable the window we're mucking with
275 * Set the start and stop system address registers
278 PCICSET(WINBASE(win
)+0,(sysstart
>> 12) & 0xFF);
279 PCICSET(WINBASE(win
)+1,((sysstart
>> 20) & 0x0F) | 0x80); /* note: 16 bits */
280 PCICSET(WINBASE(win
)+2,(sysend
>> 12) & 0xFF);
281 PCICSET(WINBASE(win
)+3,((sysend
>> 20) & 0x0F) | 0x00);
284 * Set the PCMCIA offset and attribute register
287 offset
= (uint32_t) ((int32_t) pcmciaoffset
- (int32_t) sysstart
);
288 PCICSET(WINBASE(win
)+4,(offset
>> 12) & 0xFF);
289 PCICSET(WINBASE(win
)+5,(((offset
>> 20) & 0x3F) | (attr
? 0x40 : 0x00)));
292 * Reenable the window
300 /* *********************************************************************
303 * Called periodically so we can check for card activity
304 * (report insertions, removals, etc.)
307 * x - void param, it's our idecommon structure
311 ********************************************************************* */
313 static void pcmcia_ata_poll(void *x
)
315 idecommon_t
*softc
= (idecommon_t
*) x
;
319 present
= pcic_cardpresent();
320 oldpresent
= (softc
->idecommon_flags
& PCMCIA_CARDPRESENT
) ? 1 : 0;
322 if (present
== oldpresent
) return;
325 console_log("PCMCIA: Card inserted");
328 console_log("PCMCIA: Card removed");
332 softc
->idecommon_flags
|= PCMCIA_CARDPRESENT
;
335 softc
->idecommon_flags
&= ~PCMCIA_CARDPRESENT
;
339 /* *********************************************************************
340 * pcmcia_ata_probe(drv,probe_a,probe_b,probe_ptr)
342 * Our probe routine. Attach a PCMCIA ATA device to the firmware.
345 * drv - driver structure
346 * probe_a - physical address of IDE registers
347 * probe_b - unit number
348 * probe_ptr - not used
352 ********************************************************************* */
354 static void pcmcia_ata_probe(cfe_driver_t
*drv
,
355 unsigned long probe_a
, unsigned long probe_b
,
359 idecommon_dispatch_t
*disp
;
364 * probe_a is the IDE base address
365 * probe_b is the unit number and other flags
366 * probe_ptr is unused.
369 softc
= (idecommon_t
*) KMALLOC(sizeof(idecommon_t
),0);
370 disp
= (idecommon_dispatch_t
*) KMALLOC(sizeof(idecommon_dispatch_t
),0);
372 softc
->idecommon_addr
= probe_a
;
373 softc
->idecommon_unit
= probe_b
;
376 disp
->baseaddr
= softc
->idecommon_addr
;
377 softc
->idecommon_dispatch
= disp
;
378 /* always defer probing till later */
379 softc
->idecommon_deferprobe
= 1;
381 disp
->outb
= pcmcia_outb
;
382 disp
->outw
= pcmcia_outw
;
383 disp
->outs
= pcmcia_outs
;
385 disp
->inb
= pcmcia_inb
;
386 disp
->inw
= pcmcia_inw
;
387 disp
->ins
= pcmcia_ins
;
389 xsprintf(descr
,"%s unit %d at %08X",drv
->drv_description
,probe_b
,probe_a
);
390 xsprintf(unitstr
,"%d",probe_b
);
391 cfe_attach(drv
,softc
,unitstr
,descr
);
392 softc
->idecommon_flags
= pcic_cardpresent() ? PCMCIA_CARDPRESENT
: 0;
393 cfe_bg_add(pcmcia_ata_poll
,softc
);
398 /* *********************************************************************
399 * pcmcia_ata_open(ctx)
401 * Open routine for the PCMCIA IDE device. It just hooks in
402 * front of the standard IDE disk open processing so we can turn
403 * on the PCIC slot and test for the card's presence.
406 * ctx - device context
409 * 0 if ok, else error code
410 ********************************************************************* */
412 static int pcmcia_ata_open(cfe_devctx_t
*ctx
)
415 idecommon_t
*softc
= ctx
->dev_softc
;
417 if (!pcic_cardpresent()) return CFE_ERR_NOTREADY
;
421 pcic_mapwin(0,0xD0000,0xD0FFF,0,0); /* common memory window */
422 pcic_mapwin(1,0xD1000,0xD1FFF,0,1); /* attribute memory window */
424 res
= idecommon_devprobe(softc
,0);
429 return idecommon_open(ctx
);