th extended reservations for Forbidden Zones paper @ RTAS'20
aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/ata/pata_ns87415.c
blob: 061aa1c41a4859347f51753e3b194ab20a794fe7 (plain) (tree)
1
2
3
4


                                                
                                                   














                                                                              
                                                               









































                                                                                   
 

                                                                          
 

                                                           

                                                            


                                                          
 

































































                                                                             
                                               
































                                                                     
                                                               





                                                                      
                                                  




                                                   
                                                                            




























                                                                       

                                  















































































                                                                          
                                           
 

                                                      
 
                                                          


                                                      
                                                    
 
                                                   

                                                      
 


                                                      

                                                       
                                                       
  
      

                                                
                                

  






                                                



















                                                                                   
                                                      

                                             


                                                            
               

                                                       
                                                      

                                             








                                                        




                                      

                            
                                                                   







                                                       
















                                                            






                                                         
                                                     




















                                                                   
/*
 *    pata_ns87415.c - NS87415 (non PARISC) PATA
 *
 *	(C) 2005 Red Hat <alan@lxorguk.ukuu.org.uk>
 *
 *    This is a fairly generic MWDMA controller. It has some limitations
 *    as it requires timing reloads on PIO/DMA transitions but it is otherwise
 *    fairly well designed.
 *
 *    This driver assumes the firmware has left the chip in a valid ST506
 *    compliant state, either legacy IRQ 14/15 or native INTA shared. You
 *    may need to add platform code if your system fails to do this.
 *
 *    The same cell appears in the 87560 controller used by some PARISC
 *    systems. This has its own special mountain of errata.
 *
 *    TODO:
 *	Test PARISC SuperIO
 *	Get someone to test on SPARC
 *	Implement lazy pio/dma switching for better performance
 *	8bit shared timing.
 *	See if we need to kill the FIFO for ATAPI
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#include <linux/ata.h>

#define DRV_NAME	"pata_ns87415"
#define DRV_VERSION	"0.0.1"

/**
 *	ns87415_set_mode - Initialize host controller mode timings
 *	@ap: Port whose timings we are configuring
 *	@adev: Device whose timings we are configuring
 *	@mode: Mode to set
 *
 *	Program the mode registers for this controller, channel and
 *	device. Because the chip is quite an old design we have to do this
 *	for PIO/DMA switches.
 *
 *	LOCKING:
 *	None (inherited from caller).
 */

static void ns87415_set_mode(struct ata_port *ap, struct ata_device *adev, u8 mode)
{
	struct pci_dev *dev	= to_pci_dev(ap->host->dev);
	int unit		= 2 * ap->port_no + adev->devno;
	int timing		= 0x44 + 2 * unit;
	unsigned long T		= 1000000000 / 33333;	/* PCI clocks */
	struct ata_timing t;
	u16 clocking;
	u8 iordy;
	u8 status;

	/* Timing register format is 17 - low nybble read timing with
	   the high nybble being 16 - x for recovery time in PCI clocks */

	ata_timing_compute(adev, adev->pio_mode, &t, T, 0);

	clocking = 17 - clamp_val(t.active, 2, 17);
	clocking |= (16 - clamp_val(t.recover, 1, 16)) << 4;
 	/* Use the same timing for read and write bytes */
	clocking |= (clocking << 8);
	pci_write_config_word(dev, timing, clocking);

	/* Set the IORDY enable versus DMA enable on or off properly */
	pci_read_config_byte(dev, 0x42, &iordy);
	iordy &= ~(1 << (4 + unit));
	if (mode >= XFER_MW_DMA_0 || !ata_pio_need_iordy(adev))
		iordy |= (1 << (4 + unit));

	/* Paranoia: We shouldn't ever get here with busy write buffers
	   but if so wait */

	pci_read_config_byte(dev, 0x43, &status);
	while (status & 0x03) {
		udelay(1);
		pci_read_config_byte(dev, 0x43, &status);
	}
	/* Flip the IORDY/DMA bits now we are sure the write buffers are
	   clear */
	pci_write_config_byte(dev, 0x42, iordy);

	/* TODO: Set byte 54 command timing to the best 8bit
	   mode shared by all four devices */
}

/**
 *	ns87415_set_piomode - Initialize host controller PATA PIO timings
 *	@ap: Port whose timings we are configuring
 *	@adev: Device to program
 *
 *	Set PIO mode for device, in host controller PCI config space.
 *
 *	LOCKING:
 *	None (inherited from caller).
 */

static void ns87415_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
	ns87415_set_mode(ap, adev, adev->pio_mode);
}

/**
 *	ns87415_bmdma_setup		-	Set up DMA
 *	@qc: Command block
 *
 *	Set up for bus masterng DMA. We have to do this ourselves
 *	rather than use the helper due to a chip erratum
 */

static void ns87415_bmdma_setup(struct ata_queued_cmd *qc)
{
	struct ata_port *ap = qc->ap;
	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
	u8 dmactl;

	/* load PRD table addr. */
	mb();	/* make sure PRD table writes are visible to controller */
	iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);

	/* specify data direction, triple-check start bit is clear */
	dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
	/* Due to an erratum we need to write these bits to the wrong
	   place - which does save us an I/O bizarrely */
	dmactl |= ATA_DMA_INTR | ATA_DMA_ERR;
	if (!rw)
		dmactl |= ATA_DMA_WR;
	iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
	/* issue r/w command */
	ap->ops->sff_exec_command(ap, &qc->tf);
}

/**
 *	ns87415_bmdma_start		-	Begin DMA transfer
 *	@qc: Command block
 *