pdc202xx_new.c

来自「linux 内核源代码」· C语言 代码 · 共 602 行 · 第 1/2 页

C
602
字号
/* *  Promise TX2/TX4/TX2000/133 IDE driver * *  This program is free software; you can redistribute it and/or *  modify it under the terms of the GNU General Public License *  as published by the Free Software Foundation; either version *  2 of the License, or (at your option) any later version. * *  Split from: *  linux/drivers/ide/pdc202xx.c	Version 0.35	Mar. 30, 2002 *  Copyright (C) 1998-2002		Andre Hedrick <andre@linux-ide.org> *  Copyright (C) 2005-2007		MontaVista Software, Inc. *  Portions Copyright (C) 1999 Promise Technology, Inc. *  Author: Frank Tiernan (frankt@promise.com) *  Released under terms of General Public License */#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/blkdev.h>#include <linux/hdreg.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/ide.h>#include <asm/io.h>#include <asm/irq.h>#ifdef CONFIG_PPC_PMAC#include <asm/prom.h>#include <asm/pci-bridge.h>#endif#undef DEBUG#ifdef DEBUG#define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args)#else#define DBG(fmt, args...)#endifstatic const char *pdc_quirk_drives[] = {	"QUANTUM FIREBALLlct08 08",	"QUANTUM FIREBALLP KA6.4",	"QUANTUM FIREBALLP KA9.1",	"QUANTUM FIREBALLP LM20.4",	"QUANTUM FIREBALLP KX13.6",	"QUANTUM FIREBALLP KX20.5",	"QUANTUM FIREBALLP KX27.3",	"QUANTUM FIREBALLP LM20.5",	NULL};static u8 max_dma_rate(struct pci_dev *pdev){	u8 mode;	switch(pdev->device) {		case PCI_DEVICE_ID_PROMISE_20277:		case PCI_DEVICE_ID_PROMISE_20276:		case PCI_DEVICE_ID_PROMISE_20275:		case PCI_DEVICE_ID_PROMISE_20271:		case PCI_DEVICE_ID_PROMISE_20269:			mode = 4;			break;		case PCI_DEVICE_ID_PROMISE_20270:		case PCI_DEVICE_ID_PROMISE_20268:			mode = 3;			break;		default:			return 0;	}	return mode;}/** * get_indexed_reg - Get indexed register * @hwif: for the port address * @index: index of the indexed register */static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index){	u8 value;	outb(index, hwif->dma_vendor1);	value = inb(hwif->dma_vendor3);	DBG("index[%02X] value[%02X]\n", index, value);	return value;}/** * set_indexed_reg - Set indexed register * @hwif: for the port address * @index: index of the indexed register */static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value){	outb(index, hwif->dma_vendor1);	outb(value, hwif->dma_vendor3);	DBG("index[%02X] value[%02X]\n", index, value);}/* * ATA Timing Tables based on 133 MHz PLL output clock. * * If the PLL outputs 100 MHz clock, the ASIC hardware will set * the timing registers automatically when "set features" command is * issued to the device. However, if the PLL output clock is 133 MHz, * the following tables must be used. */static struct pio_timing {	u8 reg0c, reg0d, reg13;} pio_timings [] = {	{ 0xfb, 0x2b, 0xac },	/* PIO mode 0, IORDY off, Prefetch off */	{ 0x46, 0x29, 0xa4 },	/* PIO mode 1, IORDY off, Prefetch off */	{ 0x23, 0x26, 0x64 },	/* PIO mode 2, IORDY off, Prefetch off */	{ 0x27, 0x0d, 0x35 },	/* PIO mode 3, IORDY on,  Prefetch off */	{ 0x23, 0x09, 0x25 },	/* PIO mode 4, IORDY on,  Prefetch off */};static struct mwdma_timing {	u8 reg0e, reg0f;} mwdma_timings [] = {	{ 0xdf, 0x5f }, 	/* MWDMA mode 0 */	{ 0x6b, 0x27 }, 	/* MWDMA mode 1 */	{ 0x69, 0x25 }, 	/* MWDMA mode 2 */};static struct udma_timing {	u8 reg10, reg11, reg12;} udma_timings [] = {	{ 0x4a, 0x0f, 0xd5 },	/* UDMA mode 0 */	{ 0x3a, 0x0a, 0xd0 },	/* UDMA mode 1 */	{ 0x2a, 0x07, 0xcd },	/* UDMA mode 2 */	{ 0x1a, 0x05, 0xcd },	/* UDMA mode 3 */	{ 0x1a, 0x03, 0xcd },	/* UDMA mode 4 */	{ 0x1a, 0x02, 0xcb },	/* UDMA mode 5 */	{ 0x1a, 0x01, 0xcb },	/* UDMA mode 6 */};static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed){	ide_hwif_t *hwif	= HWIF(drive);	u8 adj			= (drive->dn & 1) ? 0x08 : 0x00;	/*	 * IDE core issues SETFEATURES_XFER to the drive first (thanks to	 * IDE_HFLAG_POST_SET_MODE in ->host_flags).  PDC202xx hardware will	 * automatically set the timing registers based on 100 MHz PLL output.	 *	 * As we set up the PLL to output 133 MHz for UltraDMA/133 capable	 * chips, we must override the default register settings...	 */	if (max_dma_rate(hwif->pci_dev) == 4) {		u8 mode = speed & 0x07;		switch (speed) {			case XFER_UDMA_6:			case XFER_UDMA_5:			case XFER_UDMA_4:			case XFER_UDMA_3:			case XFER_UDMA_2:			case XFER_UDMA_1:			case XFER_UDMA_0:				set_indexed_reg(hwif, 0x10 + adj,						udma_timings[mode].reg10);				set_indexed_reg(hwif, 0x11 + adj,						udma_timings[mode].reg11);				set_indexed_reg(hwif, 0x12 + adj,						udma_timings[mode].reg12);				break;			case XFER_MW_DMA_2:			case XFER_MW_DMA_1:			case XFER_MW_DMA_0:				set_indexed_reg(hwif, 0x0e + adj,						mwdma_timings[mode].reg0e);				set_indexed_reg(hwif, 0x0f + adj,						mwdma_timings[mode].reg0f);				break;			case XFER_PIO_4:			case XFER_PIO_3:			case XFER_PIO_2:			case XFER_PIO_1:			case XFER_PIO_0:				set_indexed_reg(hwif, 0x0c + adj,						pio_timings[mode].reg0c);				set_indexed_reg(hwif, 0x0d + adj,						pio_timings[mode].reg0d);				set_indexed_reg(hwif, 0x13 + adj,						pio_timings[mode].reg13);				break;			default:				printk(KERN_ERR "pdc202xx_new: "				       "Unknown speed %d ignored\n", speed);		}	} else if (speed == XFER_UDMA_2) {		/* Set tHOLD bit to 0 if using UDMA mode 2 */		u8 tmp = get_indexed_reg(hwif, 0x10 + adj);		set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f); 	}}static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio){	pdcnew_set_mode(drive, XFER_PIO_0 + pio);}static u8 pdcnew_cable_detect(ide_hwif_t *hwif){	if (get_indexed_reg(hwif, 0x0b) & 0x04)		return ATA_CBL_PATA40;	else		return ATA_CBL_PATA80;}static int pdcnew_quirkproc(ide_drive_t *drive){	const char **list, *model = drive->id->model;	for (list = pdc_quirk_drives; *list != NULL; list++)		if (strstr(model, *list) != NULL)			return 2;	return 0;}static void pdcnew_reset(ide_drive_t *drive){	/*	 * Deleted this because it is redundant from the caller.	 */	printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n",		HWIF(drive)->channel ? "Secondary" : "Primary");}/** * read_counter - Read the byte count registers * @dma_base: for the port address */static long __devinit read_counter(u32 dma_base){	u32  pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08;	u8   cnt0, cnt1, cnt2, cnt3;	long count = 0, last;	int  retry = 3;	do {		last = count;		/* Read the current count */		outb(0x20, pri_dma_base + 0x01);		cnt0 = inb(pri_dma_base + 0x03);		outb(0x21, pri_dma_base + 0x01);		cnt1 = inb(pri_dma_base + 0x03);		outb(0x20, sec_dma_base + 0x01);		cnt2 = inb(sec_dma_base + 0x03);		outb(0x21, sec_dma_base + 0x01);		cnt3 = inb(sec_dma_base + 0x03);		count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0;		/*		 * The 30-bit decrementing counter is read in 4 pieces.		 * Incorrect value may be read when the most significant bytes		 * are changing...		 */	} while (retry-- && (((last ^ count) & 0x3fff8000) || last < count));	DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n",		  cnt0, cnt1, cnt2, cnt3);	return count;}/** * detect_pll_input_clock - Detect the PLL input clock in Hz. * @dma_base: for the port address * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock. */static long __devinit detect_pll_input_clock(unsigned long dma_base){	struct timeval start_time, end_time;	long start_count, end_count;	long pll_input, usec_elapsed;	u8 scr1;	start_count = read_counter(dma_base);	do_gettimeofday(&start_time);	/* Start the test mode */	outb(0x01, dma_base + 0x01);	scr1 = inb(dma_base + 0x03);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?