11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Portions Copyright (C) 2003		Red Hat Inc
5fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz * Portions Copyright (C) 2007		Bartlomiej Zolnierkiewicz
659c8d04f5ee97ea46da854e9adbbaa45d988c39dSergei Shtylyov * Portions Copyright (C) 2005-2009	MontaVista Software, Inc.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thanks to HighPoint Technologies for their assistance, and hardware.
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * donation of an ABit BP6 mainboard, processor, and memory acellerated
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * development and support.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
13b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox *
14836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov * HighPoint has its own drivers (open source except for the RAID part)
15631dd1a885b6d7e9f6f51b4e5b311c2bb04c323cJustin P. Mattock * available from http://www.highpoint-tech.com/USA_new/service_support.htm
16836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov * This may be useful to anyone wanting to work on this driver, however  do not
17836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov * trust  them too much since the code tends to become less and less meaningful
18836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov * as the time passes... :-/
19b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox *
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that final HPT370 support was done by force extraction of GPL.
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - add function for getting/setting power status of drive
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - the HPT370's state machine can get confused. reset it before each dma
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   xfer to prevent that from happening.
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - reset state engine whenever we get an error.
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - check for busmaster state at end of dma.
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - use new highpoint timings.
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - detect bus speed using highpoint register.
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - use pll if we don't have a clock table. added a 66MHz table that's
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   just 2x the 33MHz table.
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - removed turnaround. NOTE: we never want to switch between pll and
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   pci clocks as the chip can glitch in those cases. the highpoint
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   approved workaround slows everything down too much to be useful. in
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   addition, we would have to serialize access to each chip.
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	Adrian Sun <a.sun@sun.com>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * add drive timings for 66MHz PCI bus,
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fix ATA Cable signal detection, fix incorrect /proc info
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * add /proc display for per-drive PIO/DMA/UDMA mode and
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * per-channel ATA-33/66 Cable detect.
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	Duncan Laurie <void@sun.com>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fixup /proc output for multiple controllers
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Tim Hockin <thockin@sun.com>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * On hpt366:
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reset the hpt366 on error, reset on dma
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fix disabling Fast Interrupt hpt366.
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 	Mike Waychison <crlf@sun.com>
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Added support for 372N clocking and clock switching. The 372N needs
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * different clocks on read/write. This requires overloading rw_disk and
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other deeply crazy things. Thanks to <http://www.hoerstreich.de> for
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * keeping me sane.
55ccd32e221c3e3797ac56305c554ad8b07c13c815Alan Cox *		Alan Cox <alan@lxorguk.ukuu.org.uk>
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
57836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov * - fix the clock turnaround code: it was writing to the wrong ports when
58836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *   called for the secondary channel, caching the current clock mode per-
59836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *   channel caused the cached register value to get out of sync with the
60836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *   actual one, the channels weren't serialized, the turnaround shouldn't
61836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *   be done on 66 MHz PCI bus
627b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - disable UltraATA/100 for HPT370 by default as the 33 MHz clock being used
637b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   does not allow for this speed anyway
647b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - avoid touching disabled channels (e.g. HPT371/N are single channel chips,
657b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   their primary channel is kind of virtual, it isn't tied to any pins)
66471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * - fix/remove bad/unused timing tables and use one set of tables for the whole
67471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov *   HPT37x chip family; save space by introducing the separate transfer mode
68471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov *   table in which the mode lookup is done
6926c068daf089aa21844236c97d05049b9497cc0aSergei Shtylyov * - use f_CNT value saved by  the HighPoint BIOS as reading it directly gives
707293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov *   the wrong PCI frequency since DPLL has already been calibrated by BIOS;
717293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov *   read it only from the function 0 of HPT374 chips
7233b18a602525198ab8892789dab6839f325407f8Sergei Shtylyov * - fix the hotswap code:  it caused RESET- to glitch when tristating the bus,
7333b18a602525198ab8892789dab6839f325407f8Sergei Shtylyov *   and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
7473d1dd93c462b52512685fe118159eafc7eb9f7eSergei Shtylyov * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
7573d1dd93c462b52512685fe118159eafc7eb9f7eSergei Shtylyov *   they tamper with its fields
767b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - pass  to the init_setup handlers a copy of the ide_pci_device_t structure
777b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   since they may tamper with its fields
7890778574c9257ea2d11c433626e1b12ac4135e0aSergei Shtylyov * - prefix the driver startup messages with the real chip name
7990778574c9257ea2d11c433626e1b12ac4135e0aSergei Shtylyov * - claim the extra 240 bytes of I/O space for all chips
802648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov * - optimize the UltraDMA filtering and the drive list lookup code
81b4586715d7944dfbcb2b6b76a0098413cf3222e4Sergei Shtylyov * - use pci_get_slot() to get to the function 1 of HPT36x/374
827b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - cache offset of the channel's misc. control registers (MCRs) being used
837b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   throughout the driver
847b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - only touch the relevant MCR when detecting the cable type on HPT374's
857b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   function 1
86abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov * - rename all the register related variables consistently
877b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - move all the interrupt twiddling code from the speedproc handlers into
887b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   init_hwif_hpt366(), also grouping all the DMA related code together there
89866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
907b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
917b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   when setting an UltraDMA mode
927b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
937b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   the best possible one
944bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov * - clean up DMA timeout handling for HPT370
957b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - switch to using the enumeration type to differ between the numerous chip
967b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   variants, matching PCI device/revision ID with the chip type early, at the
977b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   init_setup stage
987b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - extend the hpt_info structure to hold the DPLL and PCI clock frequencies,
997b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   stop duplicating it for each channel by storing the pointer in the pci_dev
1007b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   structure: first, at the init_setup stage, point it to a static "template"
1017b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   with only the chip type and its specific base DPLL frequency, the highest
1022648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov *   UltraDMA mode, and the chip settings table pointer filled,  then, at the
1032648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov *   init_chipset stage, allocate per-chip instance  and fill it with the rest
1042648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov *   of the necessary information
1057b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - get rid of the constant thresholds in the HPT37x PCI clock detection code,
1067b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   switch  to calculating  PCI clock frequency based on the chip's base DPLL
1077b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   frequency
1087b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov * - switch to using the  DPLL clock and enable UltraATA/133 mode by default on
109278978e953a35a2ddf27f197003b29da54e31908Sergei Shtylyov *   anything  newer than HPT370/A (except HPT374 that is not capable of this
110278978e953a35a2ddf27f197003b29da54e31908Sergei Shtylyov *   mode according to the manual)
1116273d26a5b280cb96b804424de323560b301ca51Sergei Shtylyov * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(),
1126273d26a5b280cb96b804424de323560b301ca51Sergei Shtylyov *   also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
1137b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   unify HPT36x/37x timing setup code and the speedproc handlers by joining
1147b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *   the register setting lists into the table indexed by the clock selected
1152648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov * - set the correct hwif->ultra_mask for each individual chip
116b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov * - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards
117c018f1ee5cf81e58b93d9e93a2ee39cad13dc1acSergei Shtylyov * - stop resetting HPT370's state machine before each DMA transfer as that has
118c018f1ee5cf81e58b93d9e93a2ee39cad13dc1acSergei Shtylyov *   caused more harm than good
1197b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *	Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h>
1315a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
136ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz#define DRV_NAME "hpt366"
137ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* various tuning parameters */
139c018f1ee5cf81e58b93d9e93a2ee39cad13dc1acSergei Shtylyov#undef	HPT_RESET_STATE_ENGINE
140836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov#undef	HPT_DELAY_INTERRUPT
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *bad_ata100_5[] = {
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307075",
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307060",
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307045",
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307030",
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307020",
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307015",
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-305040",
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-305030",
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-305020",
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L010AVER07-0",
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L020AVER07-0",
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L030AVER07-0",
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L040AVER07-0",
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L060AVER07-0",
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"WDC AC310200R",
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *bad_ata66_4[] = {
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307075",
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307060",
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307045",
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307030",
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307020",
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-307015",
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-305040",
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-305030",
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IBM-DTLA-305020",
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L010AVER07-0",
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L020AVER07-0",
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L030AVER07-0",
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L040AVER07-0",
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IC35L060AVER07-0",
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"WDC AC310200R",
177783353b1d3d1ed3ae4a0bd4ea4557bd4d77aa04eSergei Shtylyov	"MAXTOR STM3320620A",
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *bad_ata66_3[] = {
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"WDC AC310200R",
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *bad_ata33[] = {
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maxtor 90510D4",
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
197471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyovstatic u8 xfer_speeds[] = {
198471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_UDMA_6,
199471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_UDMA_5,
200471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_UDMA_4,
201471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_UDMA_3,
202471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_UDMA_2,
203471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_UDMA_1,
204471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_UDMA_0,
205471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov
206471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_MW_DMA_2,
207471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_MW_DMA_1,
208471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_MW_DMA_0,
209471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov
210471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_PIO_4,
211471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_PIO_3,
212471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_PIO_2,
213471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_PIO_1,
214471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	XFER_PIO_0
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
217471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov/* Key for bus clock timings
218471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 36x   37x
219471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * bits  bits
220471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 0:3	 0:3	data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
221471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov *		cycles = value + 1
222471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 4:7	 4:8	data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
223471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov *		cycles = value + 1
224471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 8:11  9:12	cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
225471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov *		register access.
226471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 12:15 13:17	cmd_low_time. Active time of DIOW_/DIOR_ during task file
227471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov *		register access.
228471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 16:18 18:20	udma_cycle_time. Clock cycles for UDMA xfer.
229471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * -	 21	CLK frequency: 0=ATA clock, 1=dual ATA clock.
230471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 19:21 22:24	pre_high_time. Time to initialize the 1st cycle for PIO and
231471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov *		MW DMA xfer.
232471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 22:24 25:27	cmd_pre_high_time. Time to initialize the 1st PIO cycle for
233471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov *		task file register access.
234471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 28	 28	UDMA enable.
235471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 29	 29	DMA  enable.
236471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 30	 30	PIO MST enable. If set, the chip is in bus master mode during
237471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov *		PIO xfer.
238471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov * 31	 31	FIFO enable.
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyovstatic u32 forty_base_hpt36x[] = {
242471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_6 */	0x900fd943,
243471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_5 */	0x900fd943,
244471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_4 */	0x900fd943,
245471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_3 */	0x900ad943,
246471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_2 */	0x900bd943,
247471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_1 */	0x9008d943,
248471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_0 */	0x9008d943,
249471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov
250471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_MW_DMA_2 */	0xa008d943,
251471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_MW_DMA_1 */	0xa010d955,
252471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_MW_DMA_0 */	0xa010d9fc,
253471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov
254471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_4 */	0xc008d963,
255471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_3 */	0xc010d974,
256471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_2 */	0xc010d997,
257471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_1 */	0xc010d9c7,
258471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_0 */	0xc018d9d9
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyovstatic u32 thirty_three_base_hpt36x[] = {
262471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_6 */	0x90c9a731,
263471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_5 */	0x90c9a731,
264471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_4 */	0x90c9a731,
265471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_3 */	0x90cfa731,
266471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_2 */	0x90caa731,
267471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_1 */	0x90cba731,
268471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_0 */	0x90c8a731,
269471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov
270471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_MW_DMA_2 */	0xa0c8a731,
271471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_MW_DMA_1 */	0xa0c8a732,	/* 0xa0c8a733 */
272471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_MW_DMA_0 */	0xa0c8a797,
273471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov
274471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_4 */	0xc0c8a731,
275471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_3 */	0xc0c8a742,
276471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_2 */	0xc0d0a753,
277471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_1 */	0xc0d0a7a3,	/* 0xc0d0a793 */
278471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_0 */	0xc0d0a7aa	/* 0xc0d0a7a7 */
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyovstatic u32 twenty_five_base_hpt36x[] = {
282471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_6 */	0x90c98521,
283471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_5 */	0x90c98521,
284471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_4 */	0x90c98521,
285471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_3 */	0x90cf8521,
286471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_2 */	0x90cf8521,
287471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_1 */	0x90cb8521,
288471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_UDMA_0 */	0x90cb8521,
289471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov
290471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_MW_DMA_2 */	0xa0ca8521,
291471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_MW_DMA_1 */	0xa0ca8532,
292471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_MW_DMA_0 */	0xa0ca8575,
293471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov
294471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_4 */	0xc0ca8521,
295471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_3 */	0xc0ca8532,
296471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_2 */	0xc0ca8542,
297471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_1 */	0xc0d08572,
298471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/* XFER_PIO_0 */	0xc0d08585
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov/*
302809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov * The following are the new timing tables with PIO mode data/taskfile transfer
303809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov * overclocking fixed...
304809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov */
305809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov
306809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov/* This table is taken from the HPT370 data manual rev. 1.02 */
307809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyovstatic u32 thirty_three_base_hpt37x[] = {
308809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_6 */	0x16455031,	/* 0x16655031 ?? */
309809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_5 */	0x16455031,
310809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_4 */	0x16455031,
311809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_3 */	0x166d5031,
312809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_2 */	0x16495031,
313809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_1 */	0x164d5033,
314809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_0 */	0x16515097,
315809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov
316809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_MW_DMA_2 */	0x26515031,
317809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_MW_DMA_1 */	0x26515033,
318809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_MW_DMA_0 */	0x26515097,
319809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov
320809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_4 */	0x06515021,
321809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_3 */	0x06515022,
322809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_2 */	0x06515033,
323809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_1 */	0x06915065,
324809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_0 */	0x06d1508a
325809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov};
326809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov
327809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyovstatic u32 fifty_base_hpt37x[] = {
328809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_6 */	0x1a861842,
329809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_5 */	0x1a861842,
330809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_4 */	0x1aae1842,
331809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_3 */	0x1a8e1842,
332809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_2 */	0x1a0e1842,
333809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_1 */	0x1a161854,
334809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_0 */	0x1a1a18ea,
335809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov
336809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_MW_DMA_2 */	0x2a821842,
337809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_MW_DMA_1 */	0x2a821854,
338809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_MW_DMA_0 */	0x2a8218ea,
339809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov
340809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_4 */	0x0a821842,
341809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_3 */	0x0a821843,
342809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_2 */	0x0a821855,
343809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_1 */	0x0ac218a8,
344809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_0 */	0x0b02190c
345809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov};
346809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov
347809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyovstatic u32 sixty_six_base_hpt37x[] = {
348809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_6 */	0x1c86fe62,
349809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_5 */	0x1caefe62,	/* 0x1c8afe62 */
350809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_4 */	0x1c8afe62,
351809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_3 */	0x1c8efe62,
352809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_2 */	0x1c92fe62,
353809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_1 */	0x1c9afe62,
354809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_UDMA_0 */	0x1c82fe62,
355809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov
356809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_MW_DMA_2 */	0x2c82fe62,
357809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_MW_DMA_1 */	0x2c82fe66,
358809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_MW_DMA_0 */	0x2c82ff2e,
359809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov
360809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_4 */	0x0c82fe62,
361809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_3 */	0x0c82fe84,
362809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_2 */	0x0c82fea6,
363809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_1 */	0x0d02ff26,
364809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov	/* XFER_PIO_0 */	0x0d42ff7f
365809b53c4ef7188dc284498ef6e4ec2d4d587a275Sergei Shtylyov};
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3677b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov#define HPT371_ALLOW_ATA133_6		1
3687b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov#define HPT302_ALLOW_ATA133_6		1
3697b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov#define HPT372_ALLOW_ATA133_6		1
370e139b0b02fd35a68c4353db34d3380c8a7c9a90dSergei Shtylyov#define HPT370_ALLOW_ATA100_5		0
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HPT366_ALLOW_ATA66_4		1
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HPT366_ALLOW_ATA66_3		1
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3747b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov/* Supported ATA clock frequencies */
3757b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyovenum ata_clock {
3767b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	ATA_CLOCK_25MHZ,
3777b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	ATA_CLOCK_33MHZ,
3787b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	ATA_CLOCK_40MHZ,
3797b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	ATA_CLOCK_50MHZ,
3807b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	ATA_CLOCK_66MHZ,
3817b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	NUM_ATA_CLOCKS
3827b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
384866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyovstruct hpt_timings {
385866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	u32 pio_mask;
386866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	u32 dma_mask;
387866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	u32 ultra_mask;
388866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	u32 *clock_table[NUM_ATA_CLOCKS];
389866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov};
390866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov
391b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox/*
3927b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *	Hold all the HighPoint chip information in one place.
393b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox */
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3957b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyovstruct hpt_info {
396fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	char *chip_name;	/* Chip name */
3977b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	u8 chip_type;		/* Chip type */
398fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	u8 udma_mask;		/* Allowed UltraDMA modes mask. */
3997b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	u8 dpll_clk;		/* DPLL clock in MHz */
4007b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	u8 pci_clk;		/* PCI  clock in MHz */
401866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	struct hpt_timings *timings; /* Chipset timing data */
402866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	u8 clock;		/* ATA clock selected */
403b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox};
404b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox
4057b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov/* Supported HighPoint chips */
4067b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyovenum {
4077b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT36x,
4087b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT370,
4097b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT370A,
4107b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT374,
4117b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT372,
4127b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT372A,
4137b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT302,
4147b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT371,
4157b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT372N,
4167b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT302N,
4177b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	HPT371N
4187b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
419b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox
420866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyovstatic struct hpt_timings hpt36x_timings = {
421866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.pio_mask	= 0xc1f8ffff,
422866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.dma_mask	= 0x303800ff,
423866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.ultra_mask	= 0x30070000,
424866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.clock_table	= {
425866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x,
426866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x,
427866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_40MHZ] = forty_base_hpt36x,
428866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_50MHZ] = NULL,
429866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_66MHZ] = NULL
430866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	}
4317b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
432e139b0b02fd35a68c4353db34d3380c8a7c9a90dSergei Shtylyov
433866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyovstatic struct hpt_timings hpt37x_timings = {
434866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.pio_mask	= 0xcfc3ffff,
435866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.dma_mask	= 0x31c001ff,
436866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.ultra_mask	= 0x303c0000,
437866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.clock_table	= {
438866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_25MHZ] = NULL,
439866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x,
440866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_40MHZ] = NULL,
441866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_50MHZ] = fifty_base_hpt37x,
442866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		[ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x
443866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	}
4447b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
446282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt36x __devinitdata = {
447fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT36x",
4487b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT36x,
449fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
4507b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 0,	/* no DPLL */
451866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt36x_timings
4527b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
4537b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
454282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt370 __devinitdata = {
455fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT370",
4567b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT370,
457fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
4587b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 48,
459866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
4607b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
4617b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
462282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt370a __devinitdata = {
463fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT370A",
4647b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT370A,
465fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
4667b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 48,
467866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
4687b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
4697b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
470282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt374 __devinitdata = {
471fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT374",
4727b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT374,
473fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= ATA_UDMA5,
4747b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 48,
475866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
4767b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
4777b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
478282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt372 __devinitdata = {
479fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT372",
4807b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT372,
481fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
4827b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 55,
483866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
4847b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
4857b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
486282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt372a __devinitdata = {
487fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT372A",
4887b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT372A,
489fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
4907b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 66,
491866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
4927b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
4937b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
494282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt302 __devinitdata = {
495fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT302",
4967b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT302,
497fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
4987b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 66,
499866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
5007b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
5017b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
502282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt371 __devinitdata = {
503fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT371",
5047b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT371,
505fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
5067b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 66,
507866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
5087b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
5097b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
510282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt372n __devinitdata = {
511fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT372N",
5127b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT372N,
513fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
5147b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 77,
515866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
5167b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
5177b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
518282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt302n __devinitdata = {
519fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT302N",
5207b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT302N,
521fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
5227b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 77,
523866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
5247b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
5257b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
526282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewiczstatic const struct hpt_info hpt371n __devinitdata = {
527fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.chip_name	= "HPT371N",
5287b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.chip_type	= HPT371N,
529fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
5307b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	.dpll_clk	= 77,
531866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	.timings	= &hpt37x_timings
5327b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov};
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
534e139b0b02fd35a68c4353db34d3380c8a7c9a90dSergei Shtylyovstatic int check_in_drive_list(ide_drive_t *drive, const char **list)
535e139b0b02fd35a68c4353db34d3380c8a7c9a90dSergei Shtylyov{
5364dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz	char *m = (char *)&drive->id[ATA_ID_PROD];
537e139b0b02fd35a68c4353db34d3380c8a7c9a90dSergei Shtylyov
538e139b0b02fd35a68c4353db34d3380c8a7c9a90dSergei Shtylyov	while (*list)
5394dde4492d850a4c9bcaa92e5bd7f4eebe3e2f5abBartlomiej Zolnierkiewicz		if (!strcmp(*list++, m))
540e139b0b02fd35a68c4353db34d3380c8a7c9a90dSergei Shtylyov			return 1;
541e139b0b02fd35a68c4353db34d3380c8a7c9a90dSergei Shtylyov	return 0;
542e139b0b02fd35a68c4353db34d3380c8a7c9a90dSergei Shtylyov}
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54462ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbianistatic struct hpt_info *hpt3xx_get_info(struct device *dev)
54562ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani{
54662ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	struct ide_host *host	= dev_get_drvdata(dev);
54762ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	struct hpt_info *info	= (struct hpt_info *)host->host_priv;
54862ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani
54962ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	return dev == host->dev[1] ? info + 1 : info;
55062ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani}
55162ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5532808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov * The Marvell bridge chips used on the HighPoint SATA cards do not seem
5542808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5562d5eaa6dd744a641e75503232a01f52d0768884cBartlomiej Zolnierkiewicz
5572d5eaa6dd744a641e75503232a01f52d0768884cBartlomiej Zolnierkiewiczstatic u8 hpt3xx_udma_filter(ide_drive_t *drive)
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
559898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif	= drive->hwif;
56062ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
5612808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov	u8 mask 		= hwif->ultra_mask;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5632648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov	switch (info->chip_type) {
5642648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov	case HPT36x:
5652648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov		if (!HPT366_ALLOW_ATA66_4 ||
5662648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov		    check_in_drive_list(drive, bad_ata66_4))
5672808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov			mask = ATA_UDMA3;
5687b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
5692648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov		if (!HPT366_ALLOW_ATA66_3 ||
5702648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov		    check_in_drive_list(drive, bad_ata66_3))
5712808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov			mask = ATA_UDMA2;
5722648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov		break;
5732808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov	case HPT370:
5742808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov		if (!HPT370_ALLOW_ATA100_5 ||
5752808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov		    check_in_drive_list(drive, bad_ata100_5))
5762808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov			mask = ATA_UDMA4;
5772808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov		break;
5782808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov	case HPT370A:
5792808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov		if (!HPT370_ALLOW_ATA100_5 ||
5802808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov		    check_in_drive_list(drive, bad_ata100_5))
5812808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov			return ATA_UDMA4;
5822808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov	case HPT372 :
5832808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov	case HPT372A:
5842808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov	case HPT372N:
5852808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov	case HPT374 :
586367d7e78dd48cf6ad35182a99d97abb5486e040eBartlomiej Zolnierkiewicz		if (ata_id_is_sata(drive->id))
5872808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov			mask &= ~0x0e;
5882808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov		/* Fall thru */
5892648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov	default:
5902808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov		return mask;
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5922648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov
5932648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov	return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
596b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyovstatic u8 hpt3xx_mdma_filter(ide_drive_t *drive)
597b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov{
598898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif	= drive->hwif;
59962ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
600b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov
601b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov	switch (info->chip_type) {
602b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov	case HPT372 :
603b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov	case HPT372A:
604b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov	case HPT372N:
605b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov	case HPT374 :
606367d7e78dd48cf6ad35182a99d97abb5486e040eBartlomiej Zolnierkiewicz		if (ata_id_is_sata(drive->id))
607b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov			return 0x00;
608b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov		/* Fall thru */
609b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov	default:
610b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov		return 0x07;
611b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov	}
612b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov}
613b4e44369a380c1836d0983c2a5011099b7b26eb1Sergei Shtylyov
6147b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyovstatic u32 get_speed_setting(u8 speed, struct hpt_info *info)
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
616471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	int i;
617471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov
618471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	/*
619471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	 * Lookup the transfer mode table to get the index into
620471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	 * the timing table.
621471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	 *
622471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	 * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
623471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	 */
624471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov	for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
625471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov		if (xfer_speeds[i] == speed)
626471a0bda5a2de5b0fd3b58255791eb831517a52cSergei Shtylyov			break;
627866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov
628866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	return info->timings->clock_table[info->clock][i];
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6318776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewiczstatic void hpt3xx_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
63374811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	struct pci_dev *dev	= to_pci_dev(hwif->dev);
63462ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
635866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	struct hpt_timings *t	= info->timings;
636866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	u8  itr_addr		= 0x40 + (drive->dn * 4);
63726ccb802ee3f9a1f1fd5bc6abf38f124bfbd9cb2Sergei Shtylyov	u32 old_itr		= 0;
6388776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz	const u8 speed		= drive->dma_mode;
639ceb1b2c583a9503e3ae68c4e7c652637971e3768Sergei Shtylyov	u32 new_itr		= get_speed_setting(speed, info);
640866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	u32 itr_mask		= speed < XFER_MW_DMA_0 ? t->pio_mask :
641866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov				 (speed < XFER_UDMA_0   ? t->dma_mask :
642866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov							  t->ultra_mask);
643b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox
644ceb1b2c583a9503e3ae68c4e7c652637971e3768Sergei Shtylyov	pci_read_config_dword(dev, itr_addr, &old_itr);
645ceb1b2c583a9503e3ae68c4e7c652637971e3768Sergei Shtylyov	new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask);
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
647abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	 * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
648abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	 * to avoid problems handling I/O errors later
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
650abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	new_itr &= ~0xc0000000;
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
652abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	pci_write_config_dword(dev, itr_addr, new_itr);
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
655e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewiczstatic void hpt3xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6578776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz	drive->dma_mode = drive->pio_mode;
6588776168ca2151850164af1de5565d01f7b8b2c53Bartlomiej Zolnierkiewicz	hpt3xx_set_mode(hwif, drive);
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
66126ccb802ee3f9a1f1fd5bc6abf38f124bfbd9cb2Sergei Shtylyovstatic void hpt3xx_maskproc(ide_drive_t *drive, int mask)
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
663898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif	= drive->hwif;
66436501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
66562ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
667734affdcae20af4fec95e46a64fb29f063a15c19Bartlomiej Zolnierkiewicz	if ((drive->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0)
668ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov		return;
669ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov
670ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov	if (info->chip_type >= HPT370) {
671ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov		u8 scr1 = 0;
672ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov
673ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov		pci_read_config_byte(dev, 0x5a, &scr1);
674ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov		if (((scr1 & 0x10) >> 4) != mask) {
675abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov			if (mask)
676ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov				scr1 |=  0x10;
677abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov			else
678ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov				scr1 &= ~0x10;
679ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov			pci_write_config_byte(dev, 0x5a, scr1);
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
681ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov	} else if (mask)
682ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov		disable_irq(hwif->irq);
683ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov	else
684ea2ac5a3b7d33ff9f41ddcee2a92c95b5a32f4e2Sergei Shtylyov		enable_irq(hwif->irq);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
688abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov * This is specific to the HPT366 UDMA chipset
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by HighPoint|Triones Technologies, Inc.
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
691841d2a9bf16471716ba3a5172d24aa40a2ea9398Sergei Shtylyovstatic void hpt366_dma_lost_irq(ide_drive_t *drive)
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
69336501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
694abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
695abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov
696abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	pci_read_config_byte(dev, 0x50, &mcr1);
697abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	pci_read_config_byte(dev, 0x52, &mcr3);
698abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	pci_read_config_byte(dev, 0x5a, &scr1);
699abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	printk("%s: (%s)  mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n",
700eb63963a55f039f049d0dd1121f91f332af6ecc9Harvey Harrison		drive->name, __func__, mcr1, mcr3, scr1);
701abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	if (scr1 & 0x10)
702abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov		pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
703841d2a9bf16471716ba3a5172d24aa40a2ea9398Sergei Shtylyov	ide_dma_lost_irq(drive);
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7064bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyovstatic void hpt370_clear_engine(ide_drive_t *drive)
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
708898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif = drive->hwif;
70936501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(hwif->dev);
710abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov
71136501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	pci_write_config_byte(dev, hwif->select_data, 0x37);
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(10);
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7154bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyovstatic void hpt370_irq_timeout(ide_drive_t *drive)
7164bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov{
717898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif	= drive->hwif;
71836501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev	= to_pci_dev(hwif->dev);
7194bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov	u16 bfifo		= 0;
7204bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov	u8  dma_cmd;
7214bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov
72236501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
7234bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov	printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
7244bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov
7254bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov	/* get DMA command mode */
726cab7f8eda40d3e3e16b137c67cdddc2cf893c5d7Bartlomiej Zolnierkiewicz	dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
7274bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov	/* stop DMA */
72859c8d04f5ee97ea46da854e9adbbaa45d988c39dSergei Shtylyov	outb(dma_cmd & ~ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
7294bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov	hpt370_clear_engine(drive);
7304bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov}
7314bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov
7325e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewiczstatic void hpt370_dma_start(ide_drive_t *drive)
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef HPT_RESET_STATE_ENGINE
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hpt370_clear_engine(drive);
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ide_dma_start(drive);
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7405e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewiczstatic int hpt370_dma_end(ide_drive_t *drive)
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
742898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif	= drive->hwif;
743cab7f8eda40d3e3e16b137c67cdddc2cf893c5d7Bartlomiej Zolnierkiewicz	u8  dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
74559c8d04f5ee97ea46da854e9adbbaa45d988c39dSergei Shtylyov	if (dma_stat & ATA_DMA_ACTIVE) {
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* wait a little */
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(20);
748cab7f8eda40d3e3e16b137c67cdddc2cf893c5d7Bartlomiej Zolnierkiewicz		dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
74959c8d04f5ee97ea46da854e9adbbaa45d988c39dSergei Shtylyov		if (dma_stat & ATA_DMA_ACTIVE)
7504bf63de27e9fd9c0926ba3bb773de076b324a955Sergei Shtylyov			hpt370_irq_timeout(drive);
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
752653bcf5292a9ac4ffc07315198f0ef995e0646a8Bartlomiej Zolnierkiewicz	return ide_dma_end(drive);
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* returns 1 if DMA IRQ issued, 0 otherwise */
7565e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewiczstatic int hpt374_dma_test_irq(ide_drive_t *drive)
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
758898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif	= drive->hwif;
75936501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev	= to_pci_dev(hwif->dev);
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 bfifo		= 0;
761abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	u8  dma_stat;
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
76336501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bfifo & 0x1FF) {
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//		printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
769cab7f8eda40d3e3e16b137c67cdddc2cf893c5d7Bartlomiej Zolnierkiewicz	dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* return 1 if INTR asserted */
77159c8d04f5ee97ea46da854e9adbbaa45d988c39dSergei Shtylyov	if (dma_stat & ATA_DMA_INTR)
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7775e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewiczstatic int hpt374_dma_end(ide_drive_t *drive)
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
779898ec223fea2a2df88035e58dbf50f493577e225Bartlomiej Zolnierkiewicz	ide_hwif_t *hwif	= drive->hwif;
78036501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev	= to_pci_dev(hwif->dev);
781abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	u8 mcr	= 0, mcr_addr	= hwif->select_data;
782abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	u8 bwsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
783abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov
784abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	pci_read_config_byte(dev, 0x6a, &bwsr);
785abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	pci_read_config_byte(dev, mcr_addr, &mcr);
786abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	if (bwsr & mask)
787abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov		pci_write_config_byte(dev, mcr_addr, mcr | 0x30);
788653bcf5292a9ac4ffc07315198f0ef995e0646a8Bartlomiej Zolnierkiewicz	return ide_dma_end(drive);
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
792836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *	hpt3xxn_set_clock	-	perform clock switching dance
793836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *	@hwif: hwif to switch
794836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *	@mode: clocking mode (0x21 for write, 0x23 otherwise)
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
796836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *	Switch the DPLL clock on the HPT3xxN devices. This is a	right mess.
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
798836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
799836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyovstatic void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8011c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	unsigned long base = hwif->extra_base;
8021c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	u8 scr2 = inb(base + 0x6b);
803836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
804836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	if ((scr2 & 0x7f) == mode)
805836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov		return;
806836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Tristate the bus */
8081c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	outb(0x80, base + 0x63);
8091c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	outb(0x80, base + 0x67);
810836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Switch clock and reset channels */
8121c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	outb(mode, base + 0x6b);
8131c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	outb(0xc0, base + 0x69);
814836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
8157b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	/*
8167b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * Reset the state machines.
8177b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * NOTE: avoid accidentally enabling the disabled channels.
8187b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 */
8191c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	outb(inb(base + 0x60) | 0x32, base + 0x60);
8201c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	outb(inb(base + 0x64) | 0x32, base + 0x64);
821836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Complete reset */
8231c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	outb(0x00, base + 0x69);
824836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Reconnect channels to bus */
8261c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	outb(0x00, base + 0x63);
8271c029fd658baa2442e8e51dc9c819301cad95777Bartlomiej Zolnierkiewicz	outb(0x00, base + 0x67);
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
831836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *	hpt3xxn_rw_disk		-	prepare for I/O
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@drive: drive for command
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@rq: block request structure
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
835836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov *	This is called when a disk I/O is issued to HPT3xxN.
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	We need it because of the clock switching.
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
839836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyovstatic void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
841bbe54d78cc59a39f1ef3ffbe70423376ad9aab4cSergei Shtylyov	hpt3xxn_set_clock(drive->hwif, rq_data_dir(rq) ? 0x21 : 0x23);
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8447b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov/**
8457b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *	hpt37x_calibrate_dpll	-	calibrate the DPLL
8467b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *	@dev: PCI device
8477b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *
8487b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *	Perform a calibration cycle on the DPLL.
8497b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov *	Returns 1 if this succeeds
8507b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov */
851feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewiczstatic int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high)
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8537b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	u32 dpll = (f_high << 16) | f_low | 0x100;
8547b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	u8  scr2;
8557b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	int i;
856b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox
8577b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	pci_write_config_dword(dev, 0x5c, dpll);
858b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox
8597b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	/* Wait for oscillator ready */
8607b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	for(i = 0; i < 0x5000; ++i) {
8617b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		udelay(50);
8627b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_read_config_byte(dev, 0x5b, &scr2);
8637b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		if (scr2 & 0x80)
864b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox			break;
865b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox	}
8667b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	/* See if it stays ready (we'll just bail out if it's not yet) */
8677b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	for(i = 0; i < 0x1000; ++i) {
8687b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_read_config_byte(dev, 0x5b, &scr2);
8697b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/* DPLL destabilized? */
8707b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		if(!(scr2 & 0x80))
8717b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			return 0;
8727b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	}
8737b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	/* Turn off tuning, we have the DPLL set */
8747b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	pci_read_config_dword (dev, 0x5c, &dpll);
8757b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	pci_write_config_dword(dev, 0x5c, (dpll & ~0x100));
8767b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	return 1;
877b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox}
878b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox
879feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewiczstatic void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr)
8801785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz{
8811785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	struct ide_host *host	= pci_get_drvdata(dev);
8821785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	struct hpt_info *info	= host->host_priv + (&dev->dev == host->dev[1]);
8831785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	u8  chip_type		= info->chip_type;
8841785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	u8  new_mcr, old_mcr	= 0;
8851785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz
8861785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	/*
8871785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	 * Disable the "fast interrupt" prediction.  Don't hold off
8881785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	 * on interrupts. (== 0x01 despite what the docs say)
8891785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	 */
8901785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	pci_read_config_byte(dev, mcr_addr + 1, &old_mcr);
8911785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz
8921785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	if (chip_type >= HPT374)
8931785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz		new_mcr = old_mcr & ~0x07;
8941785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	else if (chip_type >= HPT370) {
8951785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz		new_mcr = old_mcr;
8961785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz		new_mcr &= ~0x02;
8971785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz#ifdef HPT_DELAY_INTERRUPT
8981785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz		new_mcr &= ~0x01;
8991785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz#else
9001785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz		new_mcr |=  0x01;
9011785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz#endif
9021785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	} else					/* HPT366 and HPT368  */
9031785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz		new_mcr = old_mcr & ~0x80;
9041785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz
9051785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	if (new_mcr != old_mcr)
9061785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz		pci_write_config_byte(dev, mcr_addr + 1, new_mcr);
9071785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz}
9081785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz
9092ed0ef543ae3f3ea4f8bd0433fb1fed22625a309Bartlomiej Zolnierkiewiczstatic int init_chipset_hpt366(struct pci_dev *dev)
910b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox{
9117b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	unsigned long io_base	= pci_resource_start(dev, 4);
91262ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	struct hpt_info *info	= hpt3xx_get_info(&dev->dev);
913a326b02b0c576001353dbc489154959b0889c6bfBartlomiej Zolnierkiewicz	const char *name	= DRV_NAME;
9147b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	u8 pci_clk,  dpll_clk	= 0;	/* PCI and DPLL clock in MHz */
9157293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov	u8 chip_type;
9167b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	enum ata_clock	clock;
9177b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
9187293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov	chip_type = info->chip_type;
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9207b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
9217b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
9227b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
9237b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
92426c068daf089aa21844236c97d05049b9497cc0aSergei Shtylyov
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9267b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * First, try to estimate the PCI clock frequency...
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
9287293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov	if (chip_type >= HPT370) {
9297b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		u8  scr1  = 0;
9307b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		u16 f_cnt = 0;
9317b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		u32 temp  = 0;
9327b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
9337b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/* Interrupt force enable. */
9347b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_read_config_byte(dev, 0x5a, &scr1);
9357b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		if (scr1 & 0x10)
9367b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
9377b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
9387b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/*
9397b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * HighPoint does this for HPT372A.
9407b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * NOTE: This register is only writeable via I/O space.
9417b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 */
9427293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		if (chip_type == HPT372A)
9437b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			outb(0x0e, io_base + 0x9c);
9447b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
9457b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/*
9467b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * Default to PCI clock. Make sure MA15/16 are set to output
9477b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * to prevent drives having problems with 40-pin cables.
9487b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 */
9497b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_write_config_byte(dev, 0x5b, 0x23);
950836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
9517b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/*
9527b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * We'll have to read f_CNT value in order to determine
9537b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * the PCI clock frequency according to the following ratio:
9547b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 *
9557b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * f_CNT = Fpci * 192 / Fdpll
9567b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 *
9577b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * First try reading the register in which the HighPoint BIOS
9587b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * saves f_CNT value before  reprogramming the DPLL from its
9597b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * default setting (which differs for the various chips).
9607b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 *
9617293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		 * NOTE: This register is only accessible via I/O space;
9627293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		 * HPT374 BIOS only saves it for the function 0, so we have to
9637293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		 * always read it from there -- no need to check the result of
9647293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		 * pci_get_slot() for the function 0 as the whole device has
9657293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		 * been already "pinned" (via function 1) in init_setup_hpt374()
9667293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		 */
9677293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
9687293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov			struct pci_dev	*dev1 = pci_get_slot(dev->bus,
9697293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov							     dev->devfn - 1);
9707293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov			unsigned long io_base = pci_resource_start(dev1, 4);
9717293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov
9727293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov			temp =	inl(io_base + 0x90);
9737293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov			pci_dev_put(dev1);
9747293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		} else
9757293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov			temp =	inl(io_base + 0x90);
9767293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov
9777293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		/*
9787293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		 * In case the signature check fails, we'll have to
9797293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		 * resort to reading the f_CNT register itself in hopes
9807293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov		 * that nobody has touched the DPLL yet...
9817b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 */
9827b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		if ((temp & 0xFFFFF000) != 0xABCDE000) {
9837b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			int i;
9847b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
98528cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			printk(KERN_WARNING "%s %s: no clock data saved by "
98628cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz				"BIOS\n", name, pci_name(dev));
9877b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
9887b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			/* Calculate the average value of f_CNT. */
9897b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			for (temp = i = 0; i < 128; i++) {
9907b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov				pci_read_config_word(dev, 0x78, &f_cnt);
9917b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov				temp += f_cnt & 0x1ff;
9927b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov				mdelay(1);
9937b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			}
9947b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			f_cnt = temp / 128;
9957b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		} else
9967b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			f_cnt = temp & 0x1ff;
9977b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
9987b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		dpll_clk = info->dpll_clk;
9997b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_clk  = (f_cnt * dpll_clk) / 192;
10007b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
10017b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/* Clamp PCI clock to bands. */
10027b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		if (pci_clk < 40)
10037b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			pci_clk = 33;
10047b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		else if(pci_clk < 45)
10057b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			pci_clk = 40;
10067b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		else if(pci_clk < 55)
10077b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			pci_clk = 50;
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
10097b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			pci_clk = 66;
1010836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
101128cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz		printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, "
101228cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			"assuming %d MHz PCI\n", name, pci_name(dev),
101328cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			dpll_clk, f_cnt, pci_clk);
101490778574c9257ea2d11c433626e1b12ac4135e0aSergei Shtylyov	} else {
10157b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		u32 itr1 = 0;
10167b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
10177b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_read_config_dword(dev, 0x40, &itr1);
10187b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
10197b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/* Detect PCI clock by looking at cmd_high_time. */
10207b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		switch((itr1 >> 8) & 0x07) {
10217b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			case 0x09:
10227b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov				pci_clk = 40;
10236273d26a5b280cb96b804424de323560b301ca51Sergei Shtylyov				break;
10247b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			case 0x05:
10257b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov				pci_clk = 25;
10266273d26a5b280cb96b804424de323560b301ca51Sergei Shtylyov				break;
10277b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			case 0x07:
10287b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			default:
10297b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov				pci_clk = 33;
10306273d26a5b280cb96b804424de323560b301ca51Sergei Shtylyov				break;
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1033836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
10347b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	/* Let's assume we'll use PCI clock for the ATA clock... */
10357b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	switch (pci_clk) {
10367b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		case 25:
10377b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			clock = ATA_CLOCK_25MHZ;
10387b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			break;
10397b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		case 33:
10407b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		default:
10417b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			clock = ATA_CLOCK_33MHZ;
10427b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			break;
10437b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		case 40:
10447b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			clock = ATA_CLOCK_40MHZ;
10457b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			break;
10467b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		case 50:
10477b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			clock = ATA_CLOCK_50MHZ;
10487b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			break;
10497b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		case 66:
10507b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			clock = ATA_CLOCK_66MHZ;
10517b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			break;
10527b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	}
1053836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10557b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * Only try the DPLL if we don't have a table for the PCI clock that
10567b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * we are running at for HPT370/A, always use it  for anything newer...
1057b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox	 *
10587b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI.
10597b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * We also  don't like using  the DPLL because this causes glitches
10607b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * on PRST-/SRST- when the state engine gets reset...
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1062866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
10637b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		u16 f_low, delta = pci_clk < 50 ? 2 : 4;
10647b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		int adjust;
10657b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
10667b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 /*
10677b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		  * Select 66 MHz DPLL clock only if UltraATA/133 mode is
10687b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		  * supported/enabled, use 50 MHz DPLL clock otherwise...
10697b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		  */
1070fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		if (info->udma_mask == ATA_UDMA6) {
10717b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			dpll_clk = 66;
10727b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			clock = ATA_CLOCK_66MHZ;
10737b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		} else if (dpll_clk) {	/* HPT36x chips don't have DPLL */
10747b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			dpll_clk = 50;
10757b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			clock = ATA_CLOCK_50MHZ;
10767b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		}
1077b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox
1078866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov		if (info->timings->clock_table[clock] == NULL) {
107928cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			printk(KERN_ERR "%s %s: unknown bus timing!\n",
108028cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz				name, pci_name(dev));
10817b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			return -EIO;
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10847b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/* Select the DPLL clock. */
10857b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_write_config_byte(dev, 0x5b, 0x21);
10867b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
10877b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/*
10887b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * Adjust the DPLL based upon PCI clock, enable it,
10897b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * and wait for stabilization...
10907b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 */
10917b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		f_low = (pci_clk * 48) / dpll_clk;
10927b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
10937b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		for (adjust = 0; adjust < 8; adjust++) {
10947b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta))
10957b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov				break;
10967b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
10977b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			/*
10987b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			 * See if it'll settle at a fractionally different clock
10997b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			 */
11007b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			if (adjust & 1)
11017b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov				f_low -= adjust >> 1;
11027b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			else
11037b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov				f_low += adjust >> 1;
11047b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		}
11057b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		if (adjust == 8) {
110628cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			printk(KERN_ERR "%s %s: DPLL did not stabilize!\n",
110728cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz				name, pci_name(dev));
11087b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov			return -EIO;
11097b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		}
11107b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
111128cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz		printk(KERN_INFO "%s %s: using %d MHz DPLL clock\n",
111228cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			name, pci_name(dev), dpll_clk);
11137b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	} else {
11147b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/* Mark the fact that we're not using the DPLL. */
11157b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		dpll_clk = 0;
11167b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
111728cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz		printk(KERN_INFO "%s %s: using %d MHz PCI clock\n",
111828cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			name, pci_name(dev), pci_clk);
11197b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	}
1120b39b01ffb75e14ed76510e4229ffb575007df0fbAlan Cox
11217b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	/* Store the clock frequencies. */
11227b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	info->dpll_clk	= dpll_clk;
11237b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	info->pci_clk	= pci_clk;
1124866664d79f6a920af07e6503f64366f4c5b2d41fSergei Shtylyov	info->clock	= clock;
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11267293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov	if (chip_type >= HPT370) {
11277b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		u8  mcr1, mcr4;
11287b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
11297b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		/*
11307b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * Reset the state engines.
11317b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 * NOTE: Avoid accidentally enabling the disabled channels.
11327b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		 */
11337b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_read_config_byte (dev, 0x50, &mcr1);
11347b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_read_config_byte (dev, 0x54, &mcr4);
11357b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_write_config_byte(dev, 0x50, (mcr1 | 0x32));
11367b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		pci_write_config_byte(dev, 0x54, (mcr4 | 0x32));
11377b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		udelay(100);
113826ccb802ee3f9a1f1fd5bc6abf38f124bfbd9cb2Sergei Shtylyov	}
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11407b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	/*
11417b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * On  HPT371N, if ATA clock is 66 MHz we must set bit 2 in
11427b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * the MISC. register to stretch the UltraDMA Tss timing.
11437b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 * NOTE: This register is only writeable via I/O space.
11447b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	 */
11457293136810936bbde403bcb67ac1b4dbae4dd790Sergei Shtylyov	if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ)
11467b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c);
11477b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
11481785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	hpt3xx_disable_fast_irq(dev, 0x50);
11491785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz	hpt3xx_disable_fast_irq(dev, 0x54);
11501785192b5310ee25165768f5bb80f13146788e3eBartlomiej Zolnierkiewicz
11512ed0ef543ae3f3ea4f8bd0433fb1fed22625a309Bartlomiej Zolnierkiewicz	return 0;
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1154f454cbe8cd38b6d447e74ddaf012017fea42717eBartlomiej Zolnierkiewiczstatic u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
1155bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz{
1156bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
115762ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
1158bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	u8 chip_type		= info->chip_type;
1159bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	u8 scr1 = 0, ata66	= hwif->channel ? 0x01 : 0x02;
1160bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz
1161bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	/*
1162bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
1163bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	 * address lines to access an external EEPROM.  To read valid
1164bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	 * cable detect state the pins must be enabled as inputs.
1165bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	 */
1166bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
1167bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		/*
1168bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		 * HPT374 PCI function 1
1169bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		 * - set bit 15 of reg 0x52 to enable TCBLID as input
1170bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		 * - set bit 15 of reg 0x56 to enable FCBLID as input
1171bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		 */
1172bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		u8  mcr_addr = hwif->select_data + 2;
1173bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		u16 mcr;
1174bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz
1175bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		pci_read_config_word(dev, mcr_addr, &mcr);
11765d3f1a493e19f34ba427936b76f0b5624a2fc62aSergei Shtylyov		pci_write_config_word(dev, mcr_addr, mcr | 0x8000);
11775d3f1a493e19f34ba427936b76f0b5624a2fc62aSergei Shtylyov		/* Debounce, then read cable ID register */
11785d3f1a493e19f34ba427936b76f0b5624a2fc62aSergei Shtylyov		udelay(10);
1179bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		pci_read_config_byte(dev, 0x5a, &scr1);
1180bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		pci_write_config_word(dev, mcr_addr, mcr);
1181bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	} else if (chip_type >= HPT370) {
1182bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		/*
1183bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		 * HPT370/372 and 374 pcifn 0
1184bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		 * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
1185bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		 */
1186bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		u8 scr2 = 0;
1187bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz
1188bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		pci_read_config_byte(dev, 0x5b, &scr2);
11895d3f1a493e19f34ba427936b76f0b5624a2fc62aSergei Shtylyov		pci_write_config_byte(dev, 0x5b, scr2 & ~1);
11905d3f1a493e19f34ba427936b76f0b5624a2fc62aSergei Shtylyov		/* Debounce, then read cable ID register */
11915d3f1a493e19f34ba427936b76f0b5624a2fc62aSergei Shtylyov		udelay(10);
1192bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		pci_read_config_byte(dev, 0x5a, &scr1);
11935d3f1a493e19f34ba427936b76f0b5624a2fc62aSergei Shtylyov		pci_write_config_byte(dev, 0x5b, scr2);
1194bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	} else
1195bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz		pci_read_config_byte(dev, 0x5a, &scr1);
1196bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz
1197bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
1198bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz}
1199bfa14b42a3bd671f0287b3db42e703e86ef27b48Bartlomiej Zolnierkiewicz
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
120262ff2ecf7a4e69f7271b7f7a57aaee76ffe610f2Masoud Sharbiani	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
12032808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov	u8  chip_type		= info->chip_type;
1204abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov
1205abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	/* Cache the channel's MISC. control registers' offset */
12062808b0a96a05ac8e826b5380eb2d30a10586707aSergei Shtylyov	hwif->select_data	= hwif->channel ? 0x54 : 0x50;
1207abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov
1208836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	/*
1209836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 * HPT3xxN chips have some complications:
1210836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 *
1211836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 * - on 33 MHz PCI we must clock switch
1212836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 * - on 66 MHz PCI we must NOT use the PCI clock
1213836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 */
12147b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov	if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) {
1215836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov		/*
1216836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov		 * Clock is shared between the channels,
1217836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov		 * so we'll have to serialize them... :-(
1218836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov		 */
1219702c026be87ef8374ae58122969a4b0b081ce6f2Bartlomiej Zolnierkiewicz		hwif->host->host_flags |= IDE_HFLAG_SERIALIZE;
1220836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov		hwif->rw_disk = &hpt3xxn_rw_disk;
1221836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	}
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1224b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewiczstatic int __devinit init_dma_hpt366(ide_hwif_t *hwif,
1225b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz				     const struct ide_port_info *d)
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
122736501650ec45b1db308c3b51886044863be2d762Bartlomiej Zolnierkiewicz	struct pci_dev *dev = to_pci_dev(hwif->dev);
1228b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz	unsigned long flags, base = ide_pci_dma_base(hwif, d);
1229b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz	u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231ebb00fb55d0566bb3e81518122a57b4b3bedf1e4Bartlomiej Zolnierkiewicz	if (base == 0)
1232ebb00fb55d0566bb3e81518122a57b4b3bedf1e4Bartlomiej Zolnierkiewicz		return -1;
1233ebb00fb55d0566bb3e81518122a57b4b3bedf1e4Bartlomiej Zolnierkiewicz
1234ebb00fb55d0566bb3e81518122a57b4b3bedf1e4Bartlomiej Zolnierkiewicz	hwif->dma_base = base;
1235ebb00fb55d0566bb3e81518122a57b4b3bedf1e4Bartlomiej Zolnierkiewicz
1236ebb00fb55d0566bb3e81518122a57b4b3bedf1e4Bartlomiej Zolnierkiewicz	if (ide_pci_check_simplex(hwif, d) < 0)
1237ebb00fb55d0566bb3e81518122a57b4b3bedf1e4Bartlomiej Zolnierkiewicz		return -1;
1238ebb00fb55d0566bb3e81518122a57b4b3bedf1e4Bartlomiej Zolnierkiewicz
1239ebb00fb55d0566bb3e81518122a57b4b3bedf1e4Bartlomiej Zolnierkiewicz	if (ide_pci_set_master(dev, d->name) < 0)
1240b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz		return -1;
1241b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz
1242b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz	dma_old = inb(base + 2);
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_save(flags);
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dma_new = dma_old;
1247abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma);
1248abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47,  &slavedma);
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (masterdma & 0x30)	dma_new |= 0x20;
1251abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfeSergei Shtylyov	if ( slavedma & 0x30)	dma_new |= 0x40;
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dma_new != dma_old)
1253b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz		outb(dma_new, base + 2);
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_restore(flags);
1256b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz
1257b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
1258b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz			 hwif->name, base, base + 7);
1259b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz
1260b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz	hwif->extra_base = base + (hwif->channel ? 8 : 16);
1261b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz
1262b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz	if (ide_allocate_dma_engine(hwif))
1263b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz		return -1;
1264b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz
1265b123f56e04c7c112f754f948198d1ea5a80e649dBartlomiej Zolnierkiewicz	return 0;
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1268fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewiczstatic void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1270fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	if (dev2->irq != dev->irq) {
1271fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		/* FIXME: we need a core pci_set_interrupt() */
1272fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		dev2->irq = dev->irq;
1273ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz		printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt "
127428cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			"fixed\n", pci_name(dev2));
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1278fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewiczstatic void __devinit hpt371_init(struct pci_dev *dev)
1279836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov{
128044c10138fd4bbc4b6d6bff0873c24902f2a9da65Auke Kok	u8 mcr1 = 0;
128190778574c9257ea2d11c433626e1b12ac4135e0aSergei Shtylyov
1282836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	/*
1283836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 * HPT371 chips physically have only one channel, the secondary one,
1284836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 * but the primary channel registers do exist!  Go figure...
1285836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 * So,  we manually disable the non-existing channel here
1286836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 * (if the BIOS hasn't done this already).
1287836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	 */
1288836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	pci_read_config_byte(dev, 0x50, &mcr1);
1289836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov	if (mcr1 & 0x04)
129090778574c9257ea2d11c433626e1b12ac4135e0aSergei Shtylyov		pci_write_config_byte(dev, 0x50, mcr1 & ~0x04);
129190778574c9257ea2d11c433626e1b12ac4135e0aSergei Shtylyov}
129290778574c9257ea2d11c433626e1b12ac4135e0aSergei Shtylyov
1293fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewiczstatic int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
129490778574c9257ea2d11c433626e1b12ac4135e0aSergei Shtylyov{
1295fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	u8 mcr1 = 0, pin1 = 0, pin2 = 0;
12967b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov
1297fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	/*
1298fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	 * Now we'll have to force both channels enabled if
1299fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	 * at least one of them has been enabled by BIOS...
1300fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	 */
1301fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	pci_read_config_byte(dev, 0x50, &mcr1);
1302fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	if (mcr1 & 0x30)
1303fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		pci_write_config_byte(dev, 0x50, mcr1 | 0x30);
1304836c0063c74cc088ffe370d007e1c6cac95e7caaSergei Shtylyov
1305fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	pci_read_config_byte(dev,  PCI_INTERRUPT_PIN, &pin1);
1306fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1308fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	if (pin1 != pin2 && dev->irq == dev2->irq) {
1309ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz		printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, "
131028cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			"pin1=%d pin2=%d\n", pci_name(dev), pin1, pin2);
1311fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		return 1;
13122648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov	}
13132648e5d9a80d8a020feb343c52a8704e978e60c6Sergei Shtylyov
1314fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	return 0;
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13174db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz#define IDE_HFLAGS_HPT3XX \
13184db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz	(IDE_HFLAG_NO_ATAPI_DMA | \
13194db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz	 IDE_HFLAG_OFF_BOARD)
13204db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz
1321ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops hpt3xx_port_ops = {
1322ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.set_pio_mode		= hpt3xx_set_pio_mode,
1323ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.set_dma_mode		= hpt3xx_set_mode,
1324ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.maskproc		= hpt3xx_maskproc,
1325ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.mdma_filter		= hpt3xx_mdma_filter,
1326ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.udma_filter		= hpt3xx_udma_filter,
1327ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.cable_detect		= hpt3xx_cable_detect,
1328ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz};
1329ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz
1330f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewiczstatic const struct ide_dma_ops hpt37x_dma_ops = {
1331f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_host_set		= ide_dma_host_set,
1332f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_setup		= ide_dma_setup,
1333f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_start		= ide_dma_start,
13345e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_end		= hpt374_dma_end,
13355e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_test_irq		= hpt374_dma_test_irq,
1336f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_lost_irq		= ide_dma_lost_irq,
133722117d6eaac50d366d9013c88318a869ea4d8739Bartlomiej Zolnierkiewicz	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
1338592b5315219881c6c0af4785f96456ad2043193aSergei Shtylyov	.dma_sff_read_status	= ide_dma_sff_read_status,
13395e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz};
13405e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz
1341f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewiczstatic const struct ide_dma_ops hpt370_dma_ops = {
1342f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_host_set		= ide_dma_host_set,
1343f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_setup		= ide_dma_setup,
13445e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_start		= hpt370_dma_start,
13455e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_end		= hpt370_dma_end,
1346f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_test_irq		= ide_dma_test_irq,
1347f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_lost_irq		= ide_dma_lost_irq,
134822117d6eaac50d366d9013c88318a869ea4d8739Bartlomiej Zolnierkiewicz	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
134935c9b4daf4c94b30e5cede597d98016ebf31b5adBartlomiej Zolnierkiewicz	.dma_clear		= hpt370_irq_timeout,
1350592b5315219881c6c0af4785f96456ad2043193aSergei Shtylyov	.dma_sff_read_status	= ide_dma_sff_read_status,
13515e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz};
13525e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz
1353f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewiczstatic const struct ide_dma_ops hpt36x_dma_ops = {
1354f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_host_set		= ide_dma_host_set,
1355f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_setup		= ide_dma_setup,
1356f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_start		= ide_dma_start,
1357653bcf5292a9ac4ffc07315198f0ef995e0646a8Bartlomiej Zolnierkiewicz	.dma_end		= ide_dma_end,
1358f37afdaca711838b50ecd89b9c15fc745270d77cBartlomiej Zolnierkiewicz	.dma_test_irq		= ide_dma_test_irq,
13595e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	.dma_lost_irq		= hpt366_dma_lost_irq,
136022117d6eaac50d366d9013c88318a869ea4d8739Bartlomiej Zolnierkiewicz	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
1361592b5315219881c6c0af4785f96456ad2043193aSergei Shtylyov	.dma_sff_read_status	= ide_dma_sff_read_status,
13625e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz};
13635e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz
13648562043606430185cad26d085d46adcc7ad67fd1Bartlomiej Zolnierkiewiczstatic const struct ide_port_info hpt366_chipsets[] __devinitdata = {
1365ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz	{	/* 0: HPT36x */
1366ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz		.name		= DRV_NAME,
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.init_chipset	= init_chipset_hpt366,
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.init_hwif	= init_hwif_hpt366,
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.init_dma	= init_dma_hpt366,
1370fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		/*
1371fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		 * HPT36x chips have one channel per function and have
1372fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		 * both channel enable bits located differently and visible
1373fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		 * to both functions -- really stupid design decision... :-(
1374fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		 * Bit 4 is for the primary channel, bit 5 for the secondary.
1375fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		 */
1376fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		.enablebits	= {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
1377ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz		.port_ops	= &hpt3xx_port_ops,
13785e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz		.dma_ops	= &hpt36x_dma_ops,
13794db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz		.host_flags	= IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
13804099d14322149c7a467e4997b87be4ba8eb78697Bartlomiej Zolnierkiewicz		.pio_mask	= ATA_PIO4,
13815f8b6c34854a966fe5eb7241fde0419d47d5d408Bartlomiej Zolnierkiewicz		.mwdma_mask	= ATA_MWDMA2,
1382ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz	},
1383ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz	{	/* 1: HPT3xx */
1384ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz		.name		= DRV_NAME,
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.init_chipset	= init_chipset_hpt366,
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.init_hwif	= init_hwif_hpt366,
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.init_dma	= init_dma_hpt366,
13887b73ee05d0acb926923d43d78b61add776ea4bb1Sergei Shtylyov		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
1389ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz		.port_ops	= &hpt3xx_port_ops,
13905e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz		.dma_ops	= &hpt37x_dma_ops,
13914db90a145292327b95b03f6dcd3352327235cc36Bartlomiej Zolnierkiewicz		.host_flags	= IDE_HFLAGS_HPT3XX,
13924099d14322149c7a467e4997b87be4ba8eb78697Bartlomiej Zolnierkiewicz		.pio_mask	= ATA_PIO4,
13935f8b6c34854a966fe5eb7241fde0419d47d5d408Bartlomiej Zolnierkiewicz		.mwdma_mask	= ATA_MWDMA2,
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	hpt366_init_one	-	called when an HPT366 is found
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@dev: the hpt366 device
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	@id: the matching pci id
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Called when the PCI registration layer (or the IDE initialization)
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	finds a device matching our IDE device tables.
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1407282037f17f1db66f555b40eedef1215a5f4b36afBartlomiej Zolnierkiewicz	const struct hpt_info *info = NULL;
140874811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	struct hpt_info *dyn_info;
1409fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	struct pci_dev *dev2 = NULL;
1410039788e1532368eeca1071a873c14e03920cdf38Bartlomiej Zolnierkiewicz	struct ide_port_info d;
1411fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	u8 idx = id->driver_data;
1412fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	u8 rev = dev->revision;
141374811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	int ret;
1414fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz
1415fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1))
1416fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		return -ENODEV;
1417fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz
1418fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	switch (idx) {
1419fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	case 0:
1420fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		if (rev < 3)
1421fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz			info = &hpt36x;
1422fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		else {
1423b66cae7672996c1ed0c4c4a4df04ce7b275c61f6Sam Ravnborg			switch (min_t(u8, rev, 6)) {
1424b66cae7672996c1ed0c4c4a4df04ce7b275c61f6Sam Ravnborg			case 3: info = &hpt370;  break;
1425b66cae7672996c1ed0c4c4a4df04ce7b275c61f6Sam Ravnborg			case 4: info = &hpt370a; break;
1426b66cae7672996c1ed0c4c4a4df04ce7b275c61f6Sam Ravnborg			case 5: info = &hpt372;  break;
1427b66cae7672996c1ed0c4c4a4df04ce7b275c61f6Sam Ravnborg			case 6: info = &hpt372n; break;
1428b66cae7672996c1ed0c4c4a4df04ce7b275c61f6Sam Ravnborg			}
1429fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz			idx++;
1430fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		}
1431fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		break;
1432fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	case 1:
1433fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		info = (rev > 1) ? &hpt372n : &hpt372a;
1434fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		break;
1435fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	case 2:
1436fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		info = (rev > 1) ? &hpt302n : &hpt302;
1437fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		break;
1438fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	case 3:
1439fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		hpt371_init(dev);
1440fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		info = (rev > 1) ? &hpt371n : &hpt371;
1441fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		break;
1442fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	case 4:
1443fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		info = &hpt374;
1444fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		break;
1445fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	case 5:
1446fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		info = &hpt372n;
1447fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		break;
1448fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	}
1449fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz
1450ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz	printk(KERN_INFO DRV_NAME ": %s chipset detected\n", info->chip_name);
1451ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz
1452ced3ec8aa7d0fa3300187ee47c144a22ccfc974eBartlomiej Zolnierkiewicz	d = hpt366_chipsets[min_t(u8, idx, 1)];
1453fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz
1454fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	d.udma_mask = info->udma_mask;
1455fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz
14565e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	/* fixup ->dma_ops for HPT370/HPT370A */
14575e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz	if (info == &hpt370 || info == &hpt370a)
14585e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz		d.dma_ops = &hpt370_dma_ops;
14595e37bdc081a980dd0d669e6387bcf15ca9666f81Bartlomiej Zolnierkiewicz
1460fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	if (info == &hpt36x || info == &hpt374)
1461fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
1462fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz
146374811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL);
146474811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	if (dyn_info == NULL) {
146528cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz		printk(KERN_ERR "%s %s: out of memory!\n",
146628cfd8af52a9ed4e5bd1751ea6bc0b8c870f68ecBartlomiej Zolnierkiewicz			d.name, pci_name(dev));
146774811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz		pci_dev_put(dev2);
146874811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz		return -ENOMEM;
146974811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	}
147074811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz
147174811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	/*
147274811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	 * Copy everything from a static "template" structure
147374811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	 * to just allocated per-chip hpt_info structure.
147474811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	 */
147574811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	memcpy(dyn_info, info, sizeof(*dyn_info));
1476fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz
147774811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	if (dev2) {
147874811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz		memcpy(dyn_info + 1, info, sizeof(*dyn_info));
1479fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz
1480fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		if (info == &hpt374)
1481fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz			hpt374_init(dev, dev2);
1482fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		else {
1483fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz			if (hpt36x_init(dev, dev2))
14845e71d9c5a50b92b33d35061d42ac39166db9578eBartlomiej Zolnierkiewicz				d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE;
1485fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		}
1486fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz
148774811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz		ret = ide_pci_init_two(dev, dev2, &d, dyn_info);
148874811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz		if (ret < 0) {
1489fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz			pci_dev_put(dev2);
149074811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz			kfree(dyn_info);
149174811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz		}
1492fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz		return ret;
1493fbf47840fe679bf370d07267df6f851b4f53e78dBartlomiej Zolnierkiewicz	}
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
149574811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	ret = ide_pci_init_one(dev, &d, dyn_info);
149674811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	if (ret < 0)
149774811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz		kfree(dyn_info);
149874811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz
149974811f355f4f69a187fa74892dcf2a684b84ce99Bartlomiej Zolnierkiewicz	return ret;
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1502a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewiczstatic void __devexit hpt366_remove(struct pci_dev *dev)
1503a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz{
1504a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz	struct ide_host *host = pci_get_drvdata(dev);
1505a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz	struct ide_info *info = host->host_priv;
1506a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz	struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL;
1507a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz
1508a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz	ide_pci_remove(dev);
1509a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz	pci_dev_put(dev2);
1510a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz	kfree(info);
1511a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz}
1512a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz
1513b66cae7672996c1ed0c4c4a4df04ce7b275c61f6Sam Ravnborgstatic const struct pci_device_id hpt366_pci_tbl[] __devinitconst = {
15149cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366),  0 },
15159cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372),  1 },
15169cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302),  2 },
15179cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371),  3 },
15189cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374),  4 },
15199cbcc5e3c5d2d0355fed22d00762fd764c81a383Bartlomiej Zolnierkiewicz	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), 5 },
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, },
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1524a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewiczstatic struct pci_driver hpt366_pci_driver = {
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "HPT366_IDE",
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= hpt366_pci_tbl,
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= hpt366_init_one,
1528a69999e286b5da33232694a2ad99c29419b91a44Adrian Bunk	.remove		= __devexit_p(hpt366_remove),
1529feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewicz	.suspend	= ide_pci_suspend,
1530feb22b7f8e62b1b987a3a1dbad95af767a1df832Bartlomiej Zolnierkiewicz	.resume		= ide_pci_resume,
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
153382ab1eeceba6705cd5a8815c48eb03af1dada744Bartlomiej Zolnierkiewiczstatic int __init hpt366_ide_init(void)
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1535a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz	return ide_pci_register_driver(&hpt366_pci_driver);
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1538a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewiczstatic void __exit hpt366_ide_exit(void)
1539a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz{
1540a9ab09e26055a76295548ca36ec00de2f4367d32Bartlomiej Zolnierkiewicz	pci_unregister_driver(&hpt366_pci_driver);
1541a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz}
1542a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewicz
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(hpt366_ide_init);
1544a6c43a2be9721d00ef9d6ef5b7b0e8113444577bBartlomiej Zolnierkiewiczmodule_exit(hpt366_ide_exit);
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Andre Hedrick");
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1549