2005-04-17 02:20:36 +04:00
/* sun3xflop.h: Sun3/80 specific parts of the floppy driver.
*
* Derived partially from asm - sparc / floppy . h , which is :
* Copyright ( C ) 1995 David S . Miller ( davem @ caip . rutgers . edu )
*
* Sun3x version 2 / 4 / 2000 Sam Creasey ( sammy @ sammy . net )
*/
# ifndef __ASM_SUN3X_FLOPPY_H
# define __ASM_SUN3X_FLOPPY_H
# include <asm/page.h>
# include <asm/pgtable.h>
# include <asm/system.h>
# include <asm/irq.h>
# include <asm/sun3x.h>
/* default interrupt vector */
# define SUN3X_FDC_IRQ 0x40
/* some constants */
# define FCR_TC 0x1
# define FCR_EJECT 0x2
# define FCR_MTRON 0x4
# define FCR_DSEL1 0x8
# define FCR_DSEL0 0x10
/* We don't need no stinkin' I/O port allocation crap. */
# undef release_region
# undef request_region
# define release_region(X, Y) do { } while(0)
# define request_region(X, Y, Z) (1)
struct sun3xflop_private {
volatile unsigned char * status_r ;
volatile unsigned char * data_r ;
volatile unsigned char * fcr_r ;
volatile unsigned char * fvr_r ;
unsigned char fcr ;
} sun3x_fdc ;
/* Super paranoid... */
# undef HAVE_DISABLE_HLT
/* Routines unique to each controller type on a Sun. */
static unsigned char sun3x_82072_fd_inb ( int port )
{
static int once = 0 ;
// udelay(5);
switch ( port & 7 ) {
default :
printk ( " floppy: Asked to read unknown port %d \n " , port ) ;
panic ( " floppy: Port bolixed. " ) ;
case 4 : /* FD_STATUS */
return ( * sun3x_fdc . status_r ) & ~ STATUS_DMA ;
case 5 : /* FD_DATA */
return ( * sun3x_fdc . data_r ) ;
case 7 : /* FD_DIR */
/* ugly hack, I can't find a way to actually detect the disk */
if ( ! once ) {
once = 1 ;
return 0x80 ;
}
return 0 ;
} ;
panic ( " sun_82072_fd_inb: How did I get here? " ) ;
}
static void sun3x_82072_fd_outb ( unsigned char value , int port )
{
// udelay(5);
switch ( port & 7 ) {
default :
printk ( " floppy: Asked to write to unknown port %d \n " , port ) ;
panic ( " floppy: Port bolixed. " ) ;
case 2 : /* FD_DOR */
/* Oh geese, 82072 on the Sun has no DOR register,
* so we make do with taunting the FCR .
*
* ASSUMPTIONS : There will only ever be one floppy
* drive attached to a Sun controller
* and it will be at drive zero .
*/
{
unsigned char fcr = sun3x_fdc . fcr ;
if ( value & 0x10 ) {
fcr | = ( FCR_DSEL0 | FCR_MTRON ) ;
} else
fcr & = ~ ( FCR_DSEL0 | FCR_MTRON ) ;
if ( fcr ! = sun3x_fdc . fcr ) {
* ( sun3x_fdc . fcr_r ) = fcr ;
sun3x_fdc . fcr = fcr ;
}
}
break ;
case 5 : /* FD_DATA */
* ( sun3x_fdc . data_r ) = value ;
break ;
case 7 : /* FD_DCR */
* ( sun3x_fdc . status_r ) = value ;
break ;
case 4 : /* FD_STATUS */
* ( sun3x_fdc . status_r ) = value ;
break ;
} ;
return ;
}
2006-10-07 17:16:45 +04:00
asmlinkage irqreturn_t sun3xflop_hardint ( int irq , void * dev_id )
2005-04-17 02:20:36 +04:00
{
register unsigned char st ;
# undef TRACE_FLPY_INT
# define NO_FLOPPY_ASSEMBLER
# ifdef TRACE_FLPY_INT
static int calls = 0 ;
static int bytes = 0 ;
static int dma_wait = 0 ;
# endif
if ( ! doing_pdma ) {
2006-10-07 17:16:45 +04:00
floppy_interrupt ( irq , dev_id ) ;
2005-04-17 02:20:36 +04:00
return IRQ_HANDLED ;
}
// printk("doing pdma\n");// st %x\n", sun_fdc->status_82072);
# ifdef TRACE_FLPY_INT
if ( ! calls )
bytes = virtual_dma_count ;
# endif
{
register int lcount ;
register char * lptr ;
for ( lcount = virtual_dma_count , lptr = virtual_dma_addr ;
lcount ; lcount - - , lptr + + ) {
/* st=fd_inb(virtual_dma_port+4) & 0x80 ; */
st = * ( sun3x_fdc . status_r ) ;
/* if(st != 0xa0) */
/* break; */
if ( ( st & 0x80 ) = = 0 ) {
virtual_dma_count = lcount ;
virtual_dma_addr = lptr ;
return IRQ_HANDLED ;
}
if ( ( st & 0x20 ) = = 0 )
break ;
if ( virtual_dma_mode )
/* fd_outb(*lptr, virtual_dma_port+5); */
* ( sun3x_fdc . data_r ) = * lptr ;
else
/* *lptr = fd_inb(virtual_dma_port+5); */
* lptr = * ( sun3x_fdc . data_r ) ;
}
virtual_dma_count = lcount ;
virtual_dma_addr = lptr ;
/* st = fd_inb(virtual_dma_port+4); */
st = * ( sun3x_fdc . status_r ) ;
}
# ifdef TRACE_FLPY_INT
calls + + ;
# endif
// printk("st=%02x\n", st);
if ( st = = 0x20 )
return IRQ_HANDLED ;
if ( ! ( st & 0x20 ) ) {
virtual_dma_residue + = virtual_dma_count ;
virtual_dma_count = 0 ;
doing_pdma = 0 ;
# ifdef TRACE_FLPY_INT
printk ( " count=%x, residue=%x calls=%d bytes=%x dma_wait=%d \n " ,
virtual_dma_count , virtual_dma_residue , calls , bytes ,
dma_wait ) ;
calls = 0 ;
dma_wait = 0 ;
# endif
2006-10-07 17:16:45 +04:00
floppy_interrupt ( irq , dev_id ) ;
2005-04-17 02:20:36 +04:00
return IRQ_HANDLED ;
}
# ifdef TRACE_FLPY_INT
if ( ! virtual_dma_count )
dma_wait + + ;
# endif
return IRQ_HANDLED ;
}
static int sun3xflop_request_irq ( void )
{
static int once = 0 ;
int error ;
if ( ! once ) {
once = 1 ;
2006-07-02 06:29:19 +04:00
error = request_irq ( FLOPPY_IRQ , sun3xflop_hardint ,
IRQF_DISABLED , " floppy " , NULL ) ;
2005-04-17 02:20:36 +04:00
return ( ( error = = 0 ) ? 0 : - 1 ) ;
} else return 0 ;
}
static void __init floppy_set_flags ( int * ints , int param , int param2 ) ;
static int sun3xflop_init ( void )
{
if ( FLOPPY_IRQ < 0x40 )
FLOPPY_IRQ = SUN3X_FDC_IRQ ;
sun3x_fdc . status_r = ( volatile unsigned char * ) SUN3X_FDC ;
sun3x_fdc . data_r = ( volatile unsigned char * ) ( SUN3X_FDC + 1 ) ;
sun3x_fdc . fcr_r = ( volatile unsigned char * ) SUN3X_FDC_FCR ;
sun3x_fdc . fvr_r = ( volatile unsigned char * ) SUN3X_FDC_FVR ;
sun3x_fdc . fcr = 0 ;
/* Last minute sanity check... */
if ( * sun3x_fdc . status_r = = 0xff ) {
return - 1 ;
}
* sun3x_fdc . fvr_r = FLOPPY_IRQ ;
* sun3x_fdc . fcr_r = FCR_TC ;
udelay ( 10 ) ;
* sun3x_fdc . fcr_r = 0 ;
/* Success... */
2006-01-12 12:06:34 +03:00
floppy_set_flags ( NULL , 1 , FD_BROKEN_DCL ) ; // I don't know how to detect this.
2005-04-17 02:20:36 +04:00
allowed_drive_mask = 0x01 ;
return ( int ) SUN3X_FDC ;
}
/* I'm not precisely sure this eject routine works */
static int sun3x_eject ( void )
{
if ( MACH_IS_SUN3X ) {
sun3x_fdc . fcr | = ( FCR_DSEL0 | FCR_EJECT ) ;
* ( sun3x_fdc . fcr_r ) = sun3x_fdc . fcr ;
udelay ( 10 ) ;
sun3x_fdc . fcr & = ~ ( FCR_DSEL0 | FCR_EJECT ) ;
* ( sun3x_fdc . fcr_r ) = sun3x_fdc . fcr ;
}
return 0 ;
}
# define fd_eject(drive) sun3x_eject()
# endif /* !(__ASM_SUN3X_FLOPPY_H) */