2005-04-17 02:20:36 +04:00
/* $Id: parport.h,v 1.11 2001/05/11 07:54:24 davem Exp $
* parport . h : sparc64 specific parport initialization and dma .
*
* Copyright ( C ) 1999 Eddie C . Dost ( ecd @ skynet . be )
*/
# ifndef _ASM_SPARC64_PARPORT_H
# define _ASM_SPARC64_PARPORT_H 1
# include <asm/ebus.h>
# include <asm/isa.h>
# include <asm/ns87303.h>
# define PARPORT_PC_MAX_PORTS PARPORT_MAX
2005-05-04 08:39:32 +04:00
/*
* While sparc64 doesn ' t have an ISA DMA API , we provide something that looks
* close enough to make parport_pc happy
*/
# define HAS_DMA
2005-04-17 02:20:36 +04:00
static struct sparc_ebus_info {
struct ebus_dma_info info ;
unsigned int addr ;
unsigned int count ;
} sparc_ebus_dmas [ PARPORT_PC_MAX_PORTS ] ;
static __inline__ void enable_dma ( unsigned int dmanr )
{
2005-07-07 02:41:54 +04:00
ebus_dma_enable ( & sparc_ebus_dmas [ dmanr ] . info , 1 ) ;
2005-04-17 02:20:36 +04:00
if ( ebus_dma_request ( & sparc_ebus_dmas [ dmanr ] . info ,
sparc_ebus_dmas [ dmanr ] . addr ,
sparc_ebus_dmas [ dmanr ] . count ) )
BUG ( ) ;
}
static __inline__ void disable_dma ( unsigned int dmanr )
{
ebus_dma_enable ( & sparc_ebus_dmas [ dmanr ] . info , 0 ) ;
}
static __inline__ void clear_dma_ff ( unsigned int dmanr )
{
/* nothing */
}
static __inline__ void set_dma_mode ( unsigned int dmanr , char mode )
{
ebus_dma_prepare ( & sparc_ebus_dmas [ dmanr ] . info , ( mode ! = DMA_MODE_WRITE ) ) ;
}
static __inline__ void set_dma_addr ( unsigned int dmanr , unsigned int addr )
{
sparc_ebus_dmas [ dmanr ] . addr = addr ;
}
static __inline__ void set_dma_count ( unsigned int dmanr , unsigned int count )
{
sparc_ebus_dmas [ dmanr ] . count = count ;
}
static __inline__ unsigned int get_dma_residue ( unsigned int dmanr )
{
return ebus_dma_residue ( & sparc_ebus_dmas [ dmanr ] . info ) ;
}
static int ebus_ecpp_p ( struct linux_ebus_device * edev )
{
2006-06-23 06:12:03 +04:00
if ( ! strcmp ( edev - > prom_node - > name , " ecpp " ) )
2005-04-17 02:20:36 +04:00
return 1 ;
2006-06-23 06:12:03 +04:00
if ( ! strcmp ( edev - > prom_node - > name , " parallel " ) ) {
char * compat ;
compat = of_get_property ( edev - > prom_node ,
" compatible " , NULL ) ;
if ( compat & &
( ! strcmp ( compat , " ecpp " ) | |
! strcmp ( compat , " ns87317-ecpp " ) | |
! strcmp ( compat + 13 , " ecpp " ) ) )
2005-04-17 02:20:36 +04:00
return 1 ;
}
return 0 ;
}
static int parport_isa_probe ( int count )
{
struct sparc_isa_bridge * isa_br ;
struct sparc_isa_device * isa_dev ;
for_each_isa ( isa_br ) {
for_each_isadev ( isa_dev , isa_br ) {
struct sparc_isa_device * child ;
unsigned long base ;
2006-06-23 06:12:03 +04:00
if ( strcmp ( isa_dev - > prom_node - > name , " dma " ) )
2005-04-17 02:20:36 +04:00
continue ;
child = isa_dev - > child ;
while ( child ) {
2006-06-23 06:12:03 +04:00
if ( ! strcmp ( child - > prom_node - > name , " parallel " ) )
2005-04-17 02:20:36 +04:00
break ;
child = child - > next ;
}
if ( ! child )
continue ;
base = child - > resource . start ;
/* No DMA, see commentary in
* asm - sparc64 / floppy . h : isa_floppy_init ( )
*/
if ( parport_pc_probe_port ( base , base + 0x400 ,
child - > irq , PARPORT_DMA_NOFIFO ,
child - > bus - > self ) )
count + + ;
}
}
return count ;
}
static int parport_pc_find_nonpci_ports ( int autoirq , int autodma )
{
struct linux_ebus * ebus ;
struct linux_ebus_device * edev ;
int count = 0 ;
for_each_ebus ( ebus ) {
for_each_ebusdev ( edev , ebus ) {
if ( ebus_ecpp_p ( edev ) ) {
unsigned long base = edev - > resource [ 0 ] . start ;
unsigned long config = edev - > resource [ 1 ] . start ;
unsigned long d_base = edev - > resource [ 2 ] . start ;
unsigned long d_len ;
spin_lock_init ( & sparc_ebus_dmas [ count ] . info . lock ) ;
d_len = ( edev - > resource [ 2 ] . end -
d_base ) + 1 ;
sparc_ebus_dmas [ count ] . info . regs =
ioremap ( d_base , d_len ) ;
if ( ! sparc_ebus_dmas [ count ] . info . regs )
continue ;
sparc_ebus_dmas [ count ] . info . flags = 0 ;
sparc_ebus_dmas [ count ] . info . callback = NULL ;
sparc_ebus_dmas [ count ] . info . client_cookie = NULL ;
sparc_ebus_dmas [ count ] . info . irq = 0xdeadbeef ;
strcpy ( sparc_ebus_dmas [ count ] . info . name , " parport " ) ;
if ( ebus_dma_register ( & sparc_ebus_dmas [ count ] . info ) )
continue ;
ebus_dma_irq_enable ( & sparc_ebus_dmas [ count ] . info , 1 ) ;
/* Configure IRQ to Push Pull, Level Low */
/* Enable ECP, set bit 2 of the CTR first */
outb ( 0x04 , base + 0x02 ) ;
ns87303_modify ( config , PCR ,
PCR_EPP_ENABLE |
PCR_IRQ_ODRAIN ,
PCR_ECP_ENABLE |
PCR_ECP_CLK_ENA |
PCR_IRQ_POLAR ) ;
/* CTR bit 5 controls direction of port */
ns87303_modify ( config , PTR ,
0 , PTR_LPT_REG_DIR ) ;
if ( parport_pc_probe_port ( base , base + 0x400 ,
edev - > irqs [ 0 ] ,
count , ebus - > self ) )
count + + ;
}
}
}
count = parport_isa_probe ( count ) ;
return count ;
}
# endif /* !(_ASM_SPARC64_PARPORT_H */