cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
/*
2007-05-06 00:03:50 +04:00
* linux / drivers / ide / pci / cmd64x . c Version 1.47 Mar 19 , 2007
2005-04-17 02:20:36 +04:00
*
* cmd64x . c : Enable interrupts at initialization time on Ultra / PCI machines .
* Due to massive hardware bugs , UltraDMA is only supported
* on the 646U 2 and not on the 646U .
*
* Copyright ( C ) 1998 Eddie C . Dost ( ecd @ skynet . be )
* Copyright ( C ) 1998 David S . Miller ( davem @ redhat . com )
*
* Copyright ( C ) 1999 - 2002 Andre Hedrick < andre @ linux - ide . org >
2007-03-03 19:48:53 +03:00
* Copyright ( C ) 2007 MontaVista Software , Inc . < source @ mvista . com >
2005-04-17 02:20:36 +04:00
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/pci.h>
# include <linux/delay.h>
# include <linux/hdreg.h>
# include <linux/ide.h>
# include <linux/init.h>
# include <asm/io.h>
# define DISPLAY_CMD64X_TIMINGS
# define CMD_DEBUG 0
# if CMD_DEBUG
# define cmdprintk(x...) printk(x)
# else
# define cmdprintk(x...)
# endif
/*
* CMD64x specific registers definition .
*/
# define CFR 0x50
2007-05-06 00:03:49 +04:00
# define CFR_INTR_CH0 0x04
2005-04-17 02:20:36 +04:00
# define CNTRL 0x51
2007-05-06 00:03:50 +04:00
# define CNTRL_ENA_1ST 0x04
# define CNTRL_ENA_2ND 0x08
# define CNTRL_DIS_RA0 0x40
# define CNTRL_DIS_RA1 0x80
2005-04-17 02:20:36 +04:00
# define CMDTIM 0x52
# define ARTTIM0 0x53
# define DRWTIM0 0x54
# define ARTTIM1 0x55
# define DRWTIM1 0x56
# define ARTTIM23 0x57
# define ARTTIM23_DIS_RA2 0x04
# define ARTTIM23_DIS_RA3 0x08
# define ARTTIM23_INTR_CH1 0x10
# define ARTTIM2 0x57
# define ARTTIM3 0x57
# define DRWTIM23 0x58
# define DRWTIM2 0x58
# define BRST 0x59
# define DRWTIM3 0x5b
# define BMIDECR0 0x70
# define MRDMODE 0x71
# define MRDMODE_INTR_CH0 0x04
# define MRDMODE_INTR_CH1 0x08
# define MRDMODE_BLK_CH0 0x10
# define MRDMODE_BLK_CH1 0x20
# define BMIDESR0 0x72
# define UDIDETCR0 0x73
# define DTPR0 0x74
# define BMIDECR1 0x78
# define BMIDECSR 0x79
# define BMIDESR1 0x7A
# define UDIDETCR1 0x7B
# define DTPR1 0x7C
# if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS)
# include <linux/stat.h>
# include <linux/proc_fs.h>
static u8 cmd64x_proc = 0 ;
# define CMD_MAX_DEVS 5
static struct pci_dev * cmd_devs [ CMD_MAX_DEVS ] ;
static int n_cmd_devs ;
static char * print_cmd64x_get_info ( char * buf , struct pci_dev * dev , int index )
{
char * p = buf ;
u8 reg72 = 0 , reg73 = 0 ; /* primary */
u8 reg7a = 0 , reg7b = 0 ; /* secondary */
2007-05-06 00:03:50 +04:00
u8 reg50 = 1 , reg51 = 1 , reg57 = 0 , reg71 = 0 ; /* extra */
u8 rev = 0 ;
2005-04-17 02:20:36 +04:00
p + = sprintf ( p , " \n Controller: %d \n " , index ) ;
2007-05-06 00:03:50 +04:00
p + = sprintf ( p , " PCI-%x Chipset. \n " , dev - > device ) ;
2005-04-17 02:20:36 +04:00
( void ) pci_read_config_byte ( dev , CFR , & reg50 ) ;
2007-05-06 00:03:50 +04:00
( void ) pci_read_config_byte ( dev , CNTRL , & reg51 ) ;
( void ) pci_read_config_byte ( dev , ARTTIM23 , & reg57 ) ;
2005-04-17 02:20:36 +04:00
( void ) pci_read_config_byte ( dev , MRDMODE , & reg71 ) ;
( void ) pci_read_config_byte ( dev , BMIDESR0 , & reg72 ) ;
( void ) pci_read_config_byte ( dev , UDIDETCR0 , & reg73 ) ;
( void ) pci_read_config_byte ( dev , BMIDESR1 , & reg7a ) ;
( void ) pci_read_config_byte ( dev , UDIDETCR1 , & reg7b ) ;
2007-05-06 00:03:50 +04:00
/* PCI0643/6 originally didn't have the primary channel enable bit */
( void ) pci_read_config_byte ( dev , PCI_REVISION_ID , & rev ) ;
if ( ( dev - > device = = PCI_DEVICE_ID_CMD_643 ) | |
( dev - > device = = PCI_DEVICE_ID_CMD_646 & & rev < 3 ) )
reg51 | = CNTRL_ENA_1ST ;
p + = sprintf ( p , " ---------------- Primary Channel "
" ---------------- Secondary Channel ------------ \n " ) ;
p + = sprintf ( p , " %s %s \n " ,
( reg51 & CNTRL_ENA_1ST ) ? " enabled " : " disabled " ,
( reg51 & CNTRL_ENA_2ND ) ? " enabled " : " disabled " ) ;
p + = sprintf ( p , " ---------------- drive0 --------- drive1 "
" -------- drive0 --------- drive1 ------ \n " ) ;
p + = sprintf ( p , " DMA enabled: %s %s "
" %s %s \n " ,
( reg72 & 0x20 ) ? " yes " : " no " , ( reg72 & 0x40 ) ? " yes " : " no " ,
( reg7a & 0x20 ) ? " yes " : " no " , ( reg7a & 0x40 ) ? " yes " : " no " ) ;
p + = sprintf ( p , " UltraDMA mode: %s (%c) %s (%c) " ,
( reg73 & 0x01 ) ? " on " : " off " ,
( ( reg73 & 0x30 ) = = 0x30 ) ? ( ( reg73 & 0x04 ) ? ' 3 ' : ' 0 ' ) :
( ( reg73 & 0x30 ) = = 0x20 ) ? ( ( reg73 & 0x04 ) ? ' 3 ' : ' 1 ' ) :
( ( reg73 & 0x30 ) = = 0x10 ) ? ( ( reg73 & 0x04 ) ? ' 4 ' : ' 2 ' ) :
( ( reg73 & 0x30 ) = = 0x00 ) ? ( ( reg73 & 0x04 ) ? ' 5 ' : ' 2 ' ) : ' ? ' ,
( reg73 & 0x02 ) ? " on " : " off " ,
( ( reg73 & 0xC0 ) = = 0xC0 ) ? ( ( reg73 & 0x08 ) ? ' 3 ' : ' 0 ' ) :
( ( reg73 & 0xC0 ) = = 0x80 ) ? ( ( reg73 & 0x08 ) ? ' 3 ' : ' 1 ' ) :
( ( reg73 & 0xC0 ) = = 0x40 ) ? ( ( reg73 & 0x08 ) ? ' 4 ' : ' 2 ' ) :
( ( reg73 & 0xC0 ) = = 0x00 ) ? ( ( reg73 & 0x08 ) ? ' 5 ' : ' 2 ' ) : ' ? ' ) ;
p + = sprintf ( p , " %s (%c) %s (%c) \n " ,
( reg7b & 0x01 ) ? " on " : " off " ,
( ( reg7b & 0x30 ) = = 0x30 ) ? ( ( reg7b & 0x04 ) ? ' 3 ' : ' 0 ' ) :
( ( reg7b & 0x30 ) = = 0x20 ) ? ( ( reg7b & 0x04 ) ? ' 3 ' : ' 1 ' ) :
( ( reg7b & 0x30 ) = = 0x10 ) ? ( ( reg7b & 0x04 ) ? ' 4 ' : ' 2 ' ) :
( ( reg7b & 0x30 ) = = 0x00 ) ? ( ( reg7b & 0x04 ) ? ' 5 ' : ' 2 ' ) : ' ? ' ,
( reg7b & 0x02 ) ? " on " : " off " ,
( ( reg7b & 0xC0 ) = = 0xC0 ) ? ( ( reg7b & 0x08 ) ? ' 3 ' : ' 0 ' ) :
( ( reg7b & 0xC0 ) = = 0x80 ) ? ( ( reg7b & 0x08 ) ? ' 3 ' : ' 1 ' ) :
( ( reg7b & 0xC0 ) = = 0x40 ) ? ( ( reg7b & 0x08 ) ? ' 4 ' : ' 2 ' ) :
( ( reg7b & 0xC0 ) = = 0x00 ) ? ( ( reg7b & 0x08 ) ? ' 5 ' : ' 2 ' ) : ' ? ' ) ;
p + = sprintf ( p , " Interrupt: %s, %s %s, %s \n " ,
( reg71 & MRDMODE_BLK_CH0 ) ? " blocked " : " enabled " ,
( reg50 & CFR_INTR_CH0 ) ? " pending " : " clear " ,
( reg71 & MRDMODE_BLK_CH1 ) ? " blocked " : " enabled " ,
( reg57 & ARTTIM23_INTR_CH1 ) ? " pending " : " clear " ) ;
2005-04-17 02:20:36 +04:00
return ( char * ) p ;
}
static int cmd64x_get_info ( char * buffer , char * * addr , off_t offset , int count )
{
char * p = buffer ;
int i ;
for ( i = 0 ; i < n_cmd_devs ; i + + ) {
struct pci_dev * dev = cmd_devs [ i ] ;
p = print_cmd64x_get_info ( p , dev , i ) ;
}
return p - buffer ; /* => must be less than 4k! */
}
# endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */
2007-03-17 23:57:24 +03:00
static u8 quantize_timing ( int timing , int quant )
{
return ( timing + quant - 1 ) / quant ;
}
2005-04-17 02:20:36 +04:00
/*
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
* This routine calculates active / recovery counts and then writes them into
* the chipset registers .
2005-04-17 02:20:36 +04:00
*/
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
static void program_cycle_times ( ide_drive_t * drive , int cycle_time , int active_time )
2005-04-17 02:20:36 +04:00
{
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
struct pci_dev * dev = HWIF ( drive ) - > pci_dev ;
int clock_time = 1000 / system_bus_clock ( ) ;
u8 cycle_count , active_count , recovery_count , drwtim ;
static const u8 recovery_values [ ] =
2005-04-17 02:20:36 +04:00
{ 15 , 15 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 0 } ;
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
static const u8 drwtim_regs [ 4 ] = { DRWTIM0 , DRWTIM1 , DRWTIM2 , DRWTIM3 } ;
cmdprintk ( " program_cycle_times parameters: total=%d, active=%d \n " ,
cycle_time , active_time ) ;
cycle_count = quantize_timing ( cycle_time , clock_time ) ;
active_count = quantize_timing ( active_time , clock_time ) ;
recovery_count = cycle_count - active_count ;
2005-04-17 02:20:36 +04:00
/*
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
* In case we ' ve got too long recovery phase , try to lengthen
* the active phase
2005-04-17 02:20:36 +04:00
*/
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
if ( recovery_count > 16 ) {
active_count + = recovery_count - 16 ;
recovery_count = 16 ;
2005-04-17 02:20:36 +04:00
}
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
if ( active_count > 16 ) /* shouldn't actually happen... */
active_count = 16 ;
cmdprintk ( " Final counts: total=%d, active=%d, recovery=%d \n " ,
cycle_count , active_count , recovery_count ) ;
2005-04-17 02:20:36 +04:00
/*
* Convert values to internal chipset representation
*/
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
recovery_count = recovery_values [ recovery_count ] ;
active_count & = 0x0f ;
2005-04-17 02:20:36 +04:00
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
/* Program the active/recovery counts into the DRWTIM register */
drwtim = ( active_count < < 4 ) | recovery_count ;
( void ) pci_write_config_byte ( dev , drwtim_regs [ drive - > dn ] , drwtim ) ;
cmdprintk ( " Write 0x%02x to reg 0x%x \n " , drwtim , drwtim_regs [ drive - > dn ] ) ;
2005-04-17 02:20:36 +04:00
}
/*
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
* This routine selects drive ' s best PIO mode and writes into the chipset
* registers setup / active / recovery timings .
2005-04-17 02:20:36 +04:00
*/
2007-03-03 19:48:53 +03:00
static u8 cmd64x_tune_pio ( ide_drive_t * drive , u8 mode_wanted )
2005-04-17 02:20:36 +04:00
{
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
ide_hwif_t * hwif = HWIF ( drive ) ;
struct pci_dev * dev = hwif - > pci_dev ;
2007-03-17 23:57:24 +03:00
ide_pio_data_t pio ;
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
u8 pio_mode , setup_count , arttim = 0 ;
static const u8 setup_values [ ] = { 0x40 , 0x40 , 0x40 , 0x80 , 0 , 0xc0 } ;
static const u8 arttim_regs [ 4 ] = { ARTTIM0 , ARTTIM1 , ARTTIM23 , ARTTIM23 } ;
2007-03-17 23:57:24 +03:00
pio_mode = ide_get_best_pio_mode ( drive , mode_wanted , 5 , & pio ) ;
2005-04-17 02:20:36 +04:00
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
cmdprintk ( " %s: PIO mode wanted %d, selected %d (%d ns)%s \n " ,
drive - > name , mode_wanted , pio_mode , pio . cycle_time ,
pio . overridden ? " (overriding vendor mode) " : " " ) ;
2005-04-17 02:20:36 +04:00
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
program_cycle_times ( drive , pio . cycle_time ,
ide_pio_timings [ pio_mode ] . active_time ) ;
2005-04-17 02:20:36 +04:00
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
setup_count = quantize_timing ( ide_pio_timings [ pio_mode ] . setup_time ,
1000 / system_bus_clock ( ) ) ;
/*
* The primary channel has individual address setup timing registers
* for each drive and the hardware selects the slowest timing itself .
* The secondary channel has one common register and we have to select
* the slowest address setup timing ourselves .
*/
if ( hwif - > channel ) {
ide_drive_t * drives = hwif - > drives ;
drive - > drive_data = setup_count ;
setup_count = max ( drives [ 0 ] . drive_data , drives [ 1 ] . drive_data ) ;
2005-04-17 02:20:36 +04:00
}
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
if ( setup_count > 5 ) /* shouldn't actually happen... */
setup_count = 5 ;
cmdprintk ( " Final address setup count: %d \n " , setup_count ) ;
2005-04-17 02:20:36 +04:00
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
/*
* Program the address setup clocks into the ARTTIM registers .
* Avoid clearing the secondary channel ' s interrupt bit .
*/
( void ) pci_read_config_byte ( dev , arttim_regs [ drive - > dn ] , & arttim ) ;
if ( hwif - > channel )
arttim & = ~ ARTTIM23_INTR_CH1 ;
arttim & = ~ 0xc0 ;
arttim | = setup_values [ setup_count ] ;
( void ) pci_write_config_byte ( dev , arttim_regs [ drive - > dn ] , arttim ) ;
cmdprintk ( " Write 0x%02x to reg 0x%x \n " , arttim , arttim_regs [ drive - > dn ] ) ;
2007-03-03 19:48:53 +03:00
return pio_mode ;
}
/*
* Attempts to set drive ' s PIO mode .
* Special cases are 8 : prefetch off , 9 : prefetch on ( both never worked ) ,
* and 255 : auto - select best mode ( used at boot time ) .
*/
static void cmd64x_tune_drive ( ide_drive_t * drive , u8 pio )
{
/*
* Filter out the prefetch control values
* to prevent PIO5 from being programmed
*/
if ( pio = = 8 | | pio = = 9 )
return ;
pio = cmd64x_tune_pio ( drive , pio ) ;
( void ) ide_config_drive_speed ( drive , XFER_PIO_0 + pio ) ;
2005-04-17 02:20:36 +04:00
}
static u8 cmd64x_ratemask ( ide_drive_t * drive )
{
struct pci_dev * dev = HWIF ( drive ) - > pci_dev ;
u8 mode = 0 ;
switch ( dev - > device ) {
case PCI_DEVICE_ID_CMD_649 :
mode = 3 ;
break ;
case PCI_DEVICE_ID_CMD_648 :
mode = 2 ;
break ;
case PCI_DEVICE_ID_CMD_643 :
return 0 ;
case PCI_DEVICE_ID_CMD_646 :
{
unsigned int class_rev = 0 ;
pci_read_config_dword ( dev ,
PCI_CLASS_REVISION , & class_rev ) ;
class_rev & = 0xff ;
/*
* UltraDMA only supported on PCI646U and PCI646U2 , which
* correspond to revisions 0x03 , 0x05 and 0x07 respectively .
* Actually , although the CMD tech support people won ' t
* tell me the details , the 0x03 revision cannot support
* UDMA correctly without hardware modifications , and even
* then it only works with Quantum disks due to some
* hold time assumptions in the 646U part which are fixed
* in the 646U 2.
*
* So we only do UltraDMA on revision 0x05 and 0x07 chipsets .
*/
switch ( class_rev ) {
case 0x07 :
case 0x05 :
return 1 ;
case 0x03 :
case 0x01 :
default :
return 0 ;
}
}
}
if ( ! eighty_ninty_three ( drive ) )
mode = min ( mode , ( u8 ) 1 ) ;
return mode ;
}
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
static int cmd64x_tune_chipset ( ide_drive_t * drive , u8 speed )
2005-04-17 02:20:36 +04:00
{
ide_hwif_t * hwif = HWIF ( drive ) ;
struct pci_dev * dev = hwif - > pci_dev ;
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
u8 unit = drive - > dn & 0x01 ;
u8 regU = 0 , pciU = hwif - > channel ? UDIDETCR1 : UDIDETCR0 ;
2005-04-17 02:20:36 +04:00
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
speed = ide_rate_filter ( cmd64x_ratemask ( drive ) , speed ) ;
2005-04-17 02:20:36 +04:00
2007-03-03 19:48:53 +03:00
if ( speed > = XFER_SW_DMA_0 ) {
2005-04-17 02:20:36 +04:00
( void ) pci_read_config_byte ( dev , pciU , & regU ) ;
regU & = ~ ( unit ? 0xCA : 0x35 ) ;
}
switch ( speed ) {
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
case XFER_UDMA_5 :
regU | = unit ? 0x0A : 0x05 ;
break ;
case XFER_UDMA_4 :
regU | = unit ? 0x4A : 0x15 ;
break ;
case XFER_UDMA_3 :
regU | = unit ? 0x8A : 0x25 ;
break ;
case XFER_UDMA_2 :
regU | = unit ? 0x42 : 0x11 ;
break ;
case XFER_UDMA_1 :
regU | = unit ? 0x82 : 0x21 ;
break ;
case XFER_UDMA_0 :
regU | = unit ? 0xC2 : 0x31 ;
break ;
case XFER_MW_DMA_2 :
program_cycle_times ( drive , 120 , 70 ) ;
break ;
case XFER_MW_DMA_1 :
program_cycle_times ( drive , 150 , 80 ) ;
break ;
case XFER_MW_DMA_0 :
program_cycle_times ( drive , 480 , 215 ) ;
break ;
case XFER_PIO_5 :
case XFER_PIO_4 :
case XFER_PIO_3 :
case XFER_PIO_2 :
case XFER_PIO_1 :
case XFER_PIO_0 :
( void ) cmd64x_tune_pio ( drive , speed - XFER_PIO_0 ) ;
break ;
default :
return 1 ;
2005-04-17 02:20:36 +04:00
}
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
if ( speed > = XFER_SW_DMA_0 )
2005-04-17 02:20:36 +04:00
( void ) pci_write_config_byte ( dev , pciU , regU ) ;
cmd64x: fix multiword and remove single-word DMA support
Fix the multiword DMA and drop the single-word DMA support (which nobody will
miss, I think). In order to do it, a number of changes was necessary:
- rename program_drive_counts() to program_cycle_times(), pass to it cycle's
total/active times instead of the clock counts, and convert them into the
active/recovery clocks there instead of cmd64x_tune_pio() -- this causes
quantize_timing() to also move;
- contrarywise, move all the code handling the address setup timing into
cmd64x_tune_pio(), so that setting MWDMA mode wouldn't change address setup;
- remove from the speedproc() method the bogus code pretending to set the DMA
timings by twiddling bits in the BMIDE status register, handle setting MWDMA
by just calling program_cycle_times(); while at it, improve the style of that
whole switch statement;
- stop fiddling with the DMA capable bits in the speedproc() method -- they do
not enable DMA, and are properly dealt with by the dma_host_{on,off} methods;
- don't set hwif->swdma_mask in the init_hwif() method anymore.
In addition to those changes, do the following:
- in cmd64x_tune_pio(), when writing to ARTTIM23 register preserve the interrupt
status bit, eliminate local_irq_{save|restore}() around this code as there's
*no* actual race with the interrupt handler, and move cmdprintk() to a more
fitting place -- after ide_get_best_pio_mode() call;
- make {arttim|drwtim}_regs arrays single-dimensional, indexed with drive->dn;
- rename {setup|recovery}_counts[] into more fitting {setup|recovery}_values[];
- in the speedproc() method, get rid of the duplicate reads/writes from/to the
UDIDETCRx registers and of the extra variable used to store the transfer mode
value after filtering, use another method of determining master/slave drive,
and cleanup useless parens;
- beautify cmdprintk() output here and there.
While at it, remove meaningless comment about the driver being used only on
UltraSPARC and long non-relevant RCS tag. :-)
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2007-05-06 00:03:49 +04:00
return ide_config_drive_speed ( drive , speed ) ;
2005-04-17 02:20:36 +04:00
}
static int config_chipset_for_dma ( ide_drive_t * drive )
{
u8 speed = ide_dma_speed ( drive , cmd64x_ratemask ( drive ) ) ;
if ( ! speed )
return 0 ;
2007-02-17 04:40:24 +03:00
if ( cmd64x_tune_chipset ( drive , speed ) )
return 0 ;
2005-04-17 02:20:36 +04:00
return ide_dma_enable ( drive ) ;
}
static int cmd64x_config_drive_for_dma ( ide_drive_t * drive )
{
2007-02-17 04:40:25 +03:00
if ( ide_use_dma ( drive ) & & config_chipset_for_dma ( drive ) )
2007-02-17 04:40:26 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
2007-02-17 04:40:25 +03:00
if ( ide_use_fast_pio ( drive ) )
2007-03-03 19:48:53 +03:00
cmd64x_tune_drive ( drive , 255 ) ;
2007-02-17 04:40:25 +03:00
2007-02-17 04:40:26 +03:00
return - 1 ;
2005-04-17 02:20:36 +04:00
}
2007-05-06 00:03:50 +04:00
static int cmd648_ide_dma_end ( ide_drive_t * drive )
2005-04-17 02:20:36 +04:00
{
2007-05-06 00:03:50 +04:00
ide_hwif_t * hwif = HWIF ( drive ) ;
int err = __ide_dma_end ( drive ) ;
u8 irq_mask = hwif - > channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0 ;
u8 mrdmode = inb ( hwif - > dma_master + 0x01 ) ;
/* clear the interrupt bit */
outb ( mrdmode | irq_mask , hwif - > dma_master + 0x01 ) ;
return err ;
2005-04-17 02:20:36 +04:00
}
static int cmd64x_ide_dma_end ( ide_drive_t * drive )
{
ide_hwif_t * hwif = HWIF ( drive ) ;
struct pci_dev * dev = hwif - > pci_dev ;
2007-05-06 00:03:50 +04:00
int irq_reg = hwif - > channel ? ARTTIM23 : CFR ;
u8 irq_mask = hwif - > channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0 ;
u8 irq_stat = 0 ;
int err = __ide_dma_end ( drive ) ;
2005-04-17 02:20:36 +04:00
2007-05-06 00:03:50 +04:00
( void ) pci_read_config_byte ( dev , irq_reg , & irq_stat ) ;
/* clear the interrupt bit */
( void ) pci_write_config_byte ( dev , irq_reg , irq_stat | irq_mask ) ;
return err ;
}
static int cmd648_ide_dma_test_irq ( ide_drive_t * drive )
{
ide_hwif_t * hwif = HWIF ( drive ) ;
u8 irq_mask = hwif - > channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0 ;
u8 dma_stat = inb ( hwif - > dma_status ) ;
u8 mrdmode = inb ( hwif - > dma_master + 0x01 ) ;
# ifdef DEBUG
printk ( " %s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x \n " ,
drive - > name , dma_stat , mrdmode , irq_mask ) ;
# endif
if ( ! ( mrdmode & irq_mask ) )
return 0 ;
/* return 1 if INTR asserted */
if ( dma_stat & 4 )
return 1 ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
static int cmd64x_ide_dma_test_irq ( ide_drive_t * drive )
{
2007-05-06 00:03:49 +04:00
ide_hwif_t * hwif = HWIF ( drive ) ;
struct pci_dev * dev = hwif - > pci_dev ;
2007-05-06 00:03:50 +04:00
int irq_reg = hwif - > channel ? ARTTIM23 : CFR ;
u8 irq_mask = hwif - > channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0 ;
u8 dma_stat = inb ( hwif - > dma_status ) ;
u8 irq_stat = 0 ;
2007-05-06 00:03:49 +04:00
( void ) pci_read_config_byte ( dev , irq_reg , & irq_stat ) ;
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
2007-05-06 00:03:50 +04:00
printk ( " %s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x \n " ,
drive - > name , dma_stat , irq_stat , irq_mask ) ;
2005-04-17 02:20:36 +04:00
# endif
2007-05-06 00:03:50 +04:00
if ( ! ( irq_stat & irq_mask ) )
2005-04-17 02:20:36 +04:00
return 0 ;
/* return 1 if INTR asserted */
2007-05-06 00:03:50 +04:00
if ( dma_stat & 4 )
2005-04-17 02:20:36 +04:00
return 1 ;
return 0 ;
}
/*
* ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old
* event order for DMA transfers .
*/
static int cmd646_1_ide_dma_end ( ide_drive_t * drive )
{
ide_hwif_t * hwif = HWIF ( drive ) ;
u8 dma_stat = 0 , dma_cmd = 0 ;
drive - > waiting_for_dma = 0 ;
/* get DMA status */
2007-02-17 04:40:25 +03:00
dma_stat = inb ( hwif - > dma_status ) ;
2005-04-17 02:20:36 +04:00
/* read DMA command state */
2007-02-17 04:40:25 +03:00
dma_cmd = inb ( hwif - > dma_command ) ;
2005-04-17 02:20:36 +04:00
/* stop DMA */
2007-02-17 04:40:25 +03:00
outb ( dma_cmd & ~ 1 , hwif - > dma_command ) ;
2005-04-17 02:20:36 +04:00
/* clear the INTR & ERROR bits */
2007-02-17 04:40:25 +03:00
outb ( dma_stat | 6 , hwif - > dma_status ) ;
2005-04-17 02:20:36 +04:00
/* and free any DMA resources */
ide_destroy_dmatable ( drive ) ;
/* verify good DMA status */
return ( dma_stat & 7 ) ! = 4 ;
}
static unsigned int __devinit init_chipset_cmd64x ( struct pci_dev * dev , const char * name )
{
u32 class_rev = 0 ;
u8 mrdmode = 0 ;
pci_read_config_dword ( dev , PCI_CLASS_REVISION , & class_rev ) ;
class_rev & = 0xff ;
switch ( dev - > device ) {
case PCI_DEVICE_ID_CMD_643 :
break ;
case PCI_DEVICE_ID_CMD_646 :
printk ( KERN_INFO " %s: chipset revision 0x%02X, " , name , class_rev ) ;
switch ( class_rev ) {
case 0x07 :
case 0x05 :
printk ( " UltraDMA Capable " ) ;
break ;
case 0x03 :
printk ( " MultiWord DMA Force Limited " ) ;
break ;
case 0x01 :
default :
printk ( " MultiWord DMA Limited, IRQ workaround enabled " ) ;
break ;
}
printk ( " \n " ) ;
break ;
case PCI_DEVICE_ID_CMD_648 :
case PCI_DEVICE_ID_CMD_649 :
break ;
default :
break ;
}
/* Set a good latency timer and cache line size value. */
( void ) pci_write_config_byte ( dev , PCI_LATENCY_TIMER , 64 ) ;
/* FIXME: pci_set_master() to ensure a good latency timer value */
/* Setup interrupts. */
( void ) pci_read_config_byte ( dev , MRDMODE , & mrdmode ) ;
mrdmode & = ~ ( 0x30 ) ;
( void ) pci_write_config_byte ( dev , MRDMODE , mrdmode ) ;
/* Use MEMORY READ LINE for reads.
* NOTE : Although not mentioned in the PCI0646U specs ,
* these bits are write only and won ' t be read
* back as set or not . The PCI0646U2 specs clarify
* this point .
*/
( void ) pci_write_config_byte ( dev , MRDMODE , mrdmode | 0x02 ) ;
/* Set reasonable active/recovery/address-setup values. */
( void ) pci_write_config_byte ( dev , ARTTIM0 , 0x40 ) ;
( void ) pci_write_config_byte ( dev , DRWTIM0 , 0x3f ) ;
( void ) pci_write_config_byte ( dev , ARTTIM1 , 0x40 ) ;
( void ) pci_write_config_byte ( dev , DRWTIM1 , 0x3f ) ;
# ifdef __i386__
( void ) pci_write_config_byte ( dev , ARTTIM23 , 0x1c ) ;
# else
( void ) pci_write_config_byte ( dev , ARTTIM23 , 0x5c ) ;
# endif
( void ) pci_write_config_byte ( dev , DRWTIM23 , 0x3f ) ;
( void ) pci_write_config_byte ( dev , DRWTIM3 , 0x3f ) ;
# ifdef CONFIG_PPC
( void ) pci_write_config_byte ( dev , UDIDETCR0 , 0xf0 ) ;
# endif /* CONFIG_PPC */
# if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS)
cmd_devs [ n_cmd_devs + + ] = dev ;
if ( ! cmd64x_proc ) {
cmd64x_proc = 1 ;
ide_pci_create_host_proc ( " cmd64x " , cmd64x_get_info ) ;
}
# endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */
return 0 ;
}
static unsigned int __devinit ata66_cmd64x ( ide_hwif_t * hwif )
{
u8 ata66 = 0 , mask = ( hwif - > channel ) ? 0x02 : 0x01 ;
switch ( hwif - > pci_dev - > device ) {
case PCI_DEVICE_ID_CMD_643 :
case PCI_DEVICE_ID_CMD_646 :
return ata66 ;
default :
break ;
}
pci_read_config_byte ( hwif - > pci_dev , BMIDECSR , & ata66 ) ;
return ( ata66 & mask ) ? 1 : 0 ;
}
static void __devinit init_hwif_cmd64x ( ide_hwif_t * hwif )
{
struct pci_dev * dev = hwif - > pci_dev ;
unsigned int class_rev ;
hwif - > autodma = 0 ;
pci_read_config_dword ( dev , PCI_CLASS_REVISION , & class_rev ) ;
class_rev & = 0xff ;
2007-03-03 19:48:53 +03:00
hwif - > tuneproc = & cmd64x_tune_drive ;
2005-04-17 02:20:36 +04:00
hwif - > speedproc = & cmd64x_tune_chipset ;
2007-03-03 19:48:53 +03:00
hwif - > drives [ 0 ] . autotune = hwif - > drives [ 1 ] . autotune = 1 ;
if ( ! hwif - > dma_base )
2005-04-17 02:20:36 +04:00
return ;
hwif - > atapi_dma = 1 ;
hwif - > ultra_mask = 0x3f ;
hwif - > mwdma_mask = 0x07 ;
if ( dev - > device = = PCI_DEVICE_ID_CMD_643 )
hwif - > ultra_mask = 0x80 ;
if ( dev - > device = = PCI_DEVICE_ID_CMD_646 )
hwif - > ultra_mask = ( class_rev > 0x04 ) ? 0x07 : 0x80 ;
if ( dev - > device = = PCI_DEVICE_ID_CMD_648 )
hwif - > ultra_mask = 0x1f ;
hwif - > ide_dma_check = & cmd64x_config_drive_for_dma ;
if ( ! ( hwif - > udma_four ) )
hwif - > udma_four = ata66_cmd64x ( hwif ) ;
2007-05-06 00:03:50 +04:00
switch ( dev - > device ) {
case PCI_DEVICE_ID_CMD_648 :
case PCI_DEVICE_ID_CMD_649 :
alt_irq_bits :
hwif - > ide_dma_end = & cmd648_ide_dma_end ;
hwif - > ide_dma_test_irq = & cmd648_ide_dma_test_irq ;
break ;
case PCI_DEVICE_ID_CMD_646 :
2005-04-17 02:20:36 +04:00
hwif - > chipset = ide_cmd646 ;
if ( class_rev = = 0x01 ) {
hwif - > ide_dma_end = & cmd646_1_ide_dma_end ;
2007-05-06 00:03:50 +04:00
break ;
} else if ( class_rev > = 0x03 )
goto alt_irq_bits ;
/* fall thru */
default :
hwif - > ide_dma_end = & cmd64x_ide_dma_end ;
hwif - > ide_dma_test_irq = & cmd64x_ide_dma_test_irq ;
break ;
2005-04-17 02:20:36 +04:00
}
if ( ! noautodma )
hwif - > autodma = 1 ;
hwif - > drives [ 0 ] . autodma = hwif - > autodma ;
hwif - > drives [ 1 ] . autodma = hwif - > autodma ;
}
2007-05-06 00:03:49 +04:00
static int __devinit init_setup_cmd64x ( struct pci_dev * dev , ide_pci_device_t * d )
{
return ide_setup_pci_device ( dev , d ) ;
}
static int __devinit init_setup_cmd646 ( struct pci_dev * dev , ide_pci_device_t * d )
{
u8 rev = 0 ;
/*
* The original PCI0646 didn ' t have the primary channel enable bit ,
* it appeared starting with PCI0646U ( i . e . revision ID 3 ) .
*/
pci_read_config_byte ( dev , PCI_REVISION_ID , & rev ) ;
if ( rev < 3 )
d - > enablebits [ 0 ] . reg = 0 ;
return ide_setup_pci_device ( dev , d ) ;
}
2005-04-17 02:20:36 +04:00
static ide_pci_device_t cmd64x_chipsets [ ] __devinitdata = {
{ /* 0 */
. name = " CMD643 " ,
2007-05-06 00:03:49 +04:00
. init_setup = init_setup_cmd64x ,
2005-04-17 02:20:36 +04:00
. init_chipset = init_chipset_cmd64x ,
. init_hwif = init_hwif_cmd64x ,
. channels = 2 ,
. autodma = AUTODMA ,
2007-05-06 00:03:49 +04:00
. enablebits = { { 0x00 , 0x00 , 0x00 } , { 0x51 , 0x08 , 0x08 } } ,
2005-04-17 02:20:36 +04:00
. bootable = ON_BOARD ,
} , { /* 1 */
. name = " CMD646 " ,
2007-05-06 00:03:49 +04:00
. init_setup = init_setup_cmd646 ,
2005-04-17 02:20:36 +04:00
. init_chipset = init_chipset_cmd64x ,
. init_hwif = init_hwif_cmd64x ,
. channels = 2 ,
. autodma = AUTODMA ,
2007-05-06 00:03:49 +04:00
. enablebits = { { 0x51 , 0x04 , 0x04 } , { 0x51 , 0x08 , 0x08 } } ,
2005-04-17 02:20:36 +04:00
. bootable = ON_BOARD ,
} , { /* 2 */
. name = " CMD648 " ,
2007-05-06 00:03:49 +04:00
. init_setup = init_setup_cmd64x ,
2005-04-17 02:20:36 +04:00
. init_chipset = init_chipset_cmd64x ,
. init_hwif = init_hwif_cmd64x ,
. channels = 2 ,
. autodma = AUTODMA ,
2007-05-06 00:03:49 +04:00
. enablebits = { { 0x51 , 0x04 , 0x04 } , { 0x51 , 0x08 , 0x08 } } ,
2005-04-17 02:20:36 +04:00
. bootable = ON_BOARD ,
} , { /* 3 */
. name = " CMD649 " ,
2007-05-06 00:03:49 +04:00
. init_setup = init_setup_cmd64x ,
2005-04-17 02:20:36 +04:00
. init_chipset = init_chipset_cmd64x ,
. init_hwif = init_hwif_cmd64x ,
. channels = 2 ,
. autodma = AUTODMA ,
2007-05-06 00:03:49 +04:00
. enablebits = { { 0x51 , 0x04 , 0x04 } , { 0x51 , 0x08 , 0x08 } } ,
2005-04-17 02:20:36 +04:00
. bootable = ON_BOARD ,
}
} ;
2007-05-06 00:03:49 +04:00
/*
* We may have to modify enablebits for PCI0646 , so we ' d better pass
* a local copy of the ide_pci_device_t structure down the call chain . . .
*/
2005-04-17 02:20:36 +04:00
static int __devinit cmd64x_init_one ( struct pci_dev * dev , const struct pci_device_id * id )
{
2007-05-06 00:03:49 +04:00
ide_pci_device_t d = cmd64x_chipsets [ id - > driver_data ] ;
return d . init_setup ( dev , & d ) ;
2005-04-17 02:20:36 +04:00
}
static struct pci_device_id cmd64x_pci_tbl [ ] = {
{ PCI_VENDOR_ID_CMD , PCI_DEVICE_ID_CMD_643 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , 0 } ,
{ PCI_VENDOR_ID_CMD , PCI_DEVICE_ID_CMD_646 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , 1 } ,
{ PCI_VENDOR_ID_CMD , PCI_DEVICE_ID_CMD_648 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , 2 } ,
{ PCI_VENDOR_ID_CMD , PCI_DEVICE_ID_CMD_649 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , 3 } ,
{ 0 , } ,
} ;
MODULE_DEVICE_TABLE ( pci , cmd64x_pci_tbl ) ;
static struct pci_driver driver = {
. name = " CMD64x_IDE " ,
. id_table = cmd64x_pci_tbl ,
. probe = cmd64x_init_one ,
} ;
2007-01-27 15:46:56 +03:00
static int __init cmd64x_ide_init ( void )
2005-04-17 02:20:36 +04:00
{
return ide_pci_register_driver ( & driver ) ;
}
module_init ( cmd64x_ide_init ) ;
MODULE_AUTHOR ( " Eddie Dost, David Miller, Andre Hedrick " ) ;
MODULE_DESCRIPTION ( " PCI driver module for CMD64x IDE " ) ;
MODULE_LICENSE ( " GPL " ) ;