📄 pdc202xx_new.c
字号:
/* * 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> * Portions Copyright (C) 1999 Promise Technology, Inc. * Author: Frank Tiernan (frankt@promise.com) * Released under terms of General Public License */#include <linux/config.h>#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>#include "ide_modes.h"#include "pdc202xx_new.h"#define PDC202_DEBUG_CABLE 0#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)#include <linux/stat.h>#include <linux/proc_fs.h>static u8 pdcnew_proc = 0;#define PDC202_MAX_DEVS 5static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS];static int n_pdc202_devs;static char * pdcnew_info(char *buf, struct pci_dev *dev){ char *p = buf; p += sprintf(p, "\n "); switch(dev->device) { case PCI_DEVICE_ID_PROMISE_20277: p += sprintf(p, "SBFastTrak 133 Lite"); break; case PCI_DEVICE_ID_PROMISE_20276: p += sprintf(p, "MBFastTrak 133 Lite"); break; case PCI_DEVICE_ID_PROMISE_20275: p += sprintf(p, "MBUltra133"); break; case PCI_DEVICE_ID_PROMISE_20271: p += sprintf(p, "FastTrak TX2000"); break; case PCI_DEVICE_ID_PROMISE_20270: p += sprintf(p, "FastTrak LP/TX2/TX4"); break; case PCI_DEVICE_ID_PROMISE_20269: p += sprintf(p, "Ultra133 TX2"); break; case PCI_DEVICE_ID_PROMISE_20268: p += sprintf(p, "Ultra100 TX2"); break; default: p += sprintf(p, "Ultra series"); break; break; } p += sprintf(p, " Chipset.\n"); return (char *)p;}static int pdcnew_get_info (char *buffer, char **addr, off_t offset, int count){ char *p = buffer; int i; for (i = 0; i < n_pdc202_devs; i++) { struct pci_dev *dev = pdc202_devs[i]; p = pdcnew_info(buffer, dev); } return p-buffer; /* => must be less than 4k! */}#endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */static u8 pdcnew_ratemask (ide_drive_t *drive){ u8 mode; switch(HWIF(drive)->pci_dev->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; } if (!eighty_ninty_three(drive)) mode = min(mode, (u8)1); return mode;}static int check_in_drive_lists (ide_drive_t *drive, const char **list){ struct hd_driveid *id = drive->id; if (pdc_quirk_drives == list) { while (*list) { if (strstr(id->model, *list++)) { return 2; } } } else { while (*list) { if (!strcmp(*list++,id->model)) { return 1; } } } return 0;}static int pdcnew_tune_chipset (ide_drive_t *drive, u8 xferspeed){ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 drive_pci = 0x60 + (drive->dn << 2); u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); u32 drive_conf; u8 AP, BP, CP, DP; u8 TA = 0, TB = 0, TC = 0; if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return -1; pci_read_config_dword(dev, drive_pci, &drive_conf); pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); pci_read_config_byte(dev, (drive_pci)|0x02, &CP); pci_read_config_byte(dev, (drive_pci)|0x03, &DP); if (speed < XFER_SW_DMA_0) { if ((AP & 0x0F) || (BP & 0x07)) { /* clear PIO modes of lower 8421 bits of A Register */ pci_write_config_byte(dev, (drive_pci), AP &~0x0F); pci_read_config_byte(dev, (drive_pci), &AP); /* clear PIO modes of lower 421 bits of B Register */ pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0x07); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); } } else { if ((BP & 0xF0) && (CP & 0x0F)) { /* clear DMA modes of upper 842 bits of B Register */ /* clear PIO forced mode upper 1 bit of B Register */ pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0xF0); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); /* clear DMA modes of lower 8421 bits of C Register */ pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F); pci_read_config_byte(dev, (drive_pci)|0x02, &CP); } } pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); pci_read_config_byte(dev, (drive_pci)|0x02, &CP); switch(speed) { case XFER_UDMA_6: speed = XFER_UDMA_5; case XFER_UDMA_5: case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; case XFER_UDMA_3: case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; case XFER_UDMA_0: case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; case XFER_MW_DMA_0: case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; case XFER_PIO_4: TA = 0x01; TB = 0x04; break; case XFER_PIO_3: TA = 0x02; TB = 0x06; break; case XFER_PIO_2: TA = 0x03; TB = 0x08; break; case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; case XFER_PIO_0: default: TA = 0x09; TB = 0x13; break; } if (speed < XFER_SW_DMA_0) { pci_write_config_byte(dev, (drive_pci), AP|TA); pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); } else { pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); }#if PDC202XX_DECODE_REGISTER_INFO pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); pci_read_config_byte(dev, (drive_pci)|0x02, &CP); pci_read_config_byte(dev, (drive_pci)|0x03, &DP); decode_registers(REG_A, AP); decode_registers(REG_B, BP); decode_registers(REG_C, CP); decode_registers(REG_D, DP);#endif /* PDC202XX_DECODE_REGISTER_INFO */#if PDC202XX_DEBUG_DRIVE_INFO printk(KERN_DEBUG "%s: %s drive%d 0x%08x ", drive->name, ide_xfer_verbose(speed), drive->dn, drive_conf); pci_read_config_dword(dev, drive_pci, &drive_conf); printk("0x%08x\n", drive_conf);#endif /* PDC202XX_DEBUG_DRIVE_INFO */ return (ide_config_drive_speed(drive, speed));}static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed){ ide_hwif_t *hwif = HWIF(drive); unsigned long indexreg = hwif->dma_vendor1; unsigned long datareg = hwif->dma_vendor3; u8 thold = 0x10; u8 adj = (drive->dn%2) ? 0x08 : 0x00; u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); if (speed == XFER_UDMA_2) { hwif->OUTB((thold + adj), indexreg); hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg); } switch (speed) { case XFER_UDMA_7: speed = XFER_UDMA_6; case XFER_UDMA_6: set_ultra(0x1a, 0x01, 0xcb); break; case XFER_UDMA_5: set_ultra(0x1a, 0x02, 0xcb); break; case XFER_UDMA_4: set_ultra(0x1a, 0x03, 0xcd); break; case XFER_UDMA_3: set_ultra(0x1a, 0x05, 0xcd); break; case XFER_UDMA_2: set_ultra(0x2a, 0x07, 0xcd); break; case XFER_UDMA_1: set_ultra(0x3a, 0x0a, 0xd0); break; case XFER_UDMA_0: set_ultra(0x4a, 0x0f, 0xd5); break; case XFER_MW_DMA_2: set_ata2(0x69, 0x25); break; case XFER_MW_DMA_1: set_ata2(0x6b, 0x27); break; case XFER_MW_DMA_0: set_ata2(0xdf, 0x5f); break; case XFER_PIO_4: set_pio(0x23, 0x09, 0x25); break; case XFER_PIO_3: set_pio(0x27, 0x0d, 0x35); break; case XFER_PIO_2: set_pio(0x23, 0x26, 0x64); break; case XFER_PIO_1: set_pio(0x46, 0x29, 0xa4); break; case XFER_PIO_0: set_pio(0xfb, 0x2b, 0xac); break; default: ; } return (ide_config_drive_speed(drive, speed));}/* 0 1 2 3 4 5 6 7 8 * 960, 480, 390, 300, 240, 180, 120, 90, 60 * 180, 150, 120, 90, 60 * DMA_Speed * 180, 120, 90, 90, 90, 60, 30 * 11, 5, 4, 3, 2, 1, 0 */static int config_chipset_for_pio (ide_drive_t *drive, u8 pio){ u8 speed = 0; if (pio == 5) pio = 4; speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); return ((int) pdcnew_tune_chipset(drive, speed));}static void pdcnew_tune_drive (ide_drive_t *drive, u8 pio){ (void) config_chipset_for_pio(drive, pio);}static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif){ hwif->OUTB(0x0b, hwif->dma_vendor1); return ((u8)((hwif->INB(hwif->dma_vendor3) & 0x04)));}static int config_chipset_for_dma (ide_drive_t *drive){ struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 speed = -1; u8 cable = 0; u8 ultra_66 = ((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008)) ? 1 : 0; switch(dev->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: case PCI_DEVICE_ID_PROMISE_20270: case PCI_DEVICE_ID_PROMISE_20268: cable = pdcnew_new_cable_detect(hwif);#if PDC202_DEBUG_CABLE printk(KERN_DEBUG "%s: %s-pin cable, %s-pin cable, %d\n", hwif->name, hwif->udma_four ? "80" : "40", cable ? "40" : "80", cable);#endif /* PDC202_DEBUG_CABLE */ break; default: /* If its not one we know we should never arrive here.. */ BUG(); } /* * Set the control register to use the 66Mhz system * clock for UDMA 3/4 mode operation. If one drive on * a channel is U66 capable but the other isn't we * fall back to U33 mode. The BIOS INT 13 hooks turn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -