From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
To: Andrew Morton <akpm@osdl.org>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>,
linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org,
Alan Cox <alan@lxorguk.ukuu.org.uk>
Subject: [PATCH][RFT] Fix HPT3xx hotswap support
Date: Wed, 03 May 2006 02:14:42 +0400 [thread overview]
Message-ID: <4457D9D2.30206@ru.mvista.com> (raw)
In-Reply-To: <444B3BDE.1030106@ru.mvista.com>
[-- Attachment #1: Type: text/plain, Size: 591 bytes --]
Hello.
Fix the broken hotswap code: on HPT37x it caused RESET- to glitch when
tristating the bus (the MISC control 3/6 and soft control 2 need to be
written to in the certain order), and for HPT36x the obsolete
HDIO_TRISTATE_HWIF ioctl() handler was called instead which treated the state
argument wrong. Also, get rid of the soft control reg. 1 wtite to enable IDE
interrupt -- this is done in init_hpt37x() already...
Have been tested on HPT370 and 371N. Should apply on top of the HPT37x
timing table fix.
MBR, Sergei
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
[-- Attachment #2: HPT3xx-fix-hotswap.patch --]
[-- Type: text/plain, Size: 5394 bytes --]
Index: linus/drivers/ide/pci/hpt366.c
===================================================================
--- linus.orig/drivers/ide/pci/hpt366.c
+++ linus/drivers/ide/pci/hpt366.c
@@ -71,6 +71,8 @@
* needed and had many modes over- and underclocked, HPT372 33 MHz table was
* for 66 MHz and 50 MHz table missed UltraDMA mode 6, HPT374 33 MHz table was
* really for 50 MHz; switch to using HPT372 tables for HPT374...
+ * - fix the hotswap code: it caused RESET- to glitch when tristating the bus,
+ * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
* <source@mvista.com>
*
*/
@@ -954,101 +956,68 @@ static void hpt3xxn_rw_disk(ide_drive_t
hpt3xxn_set_clock(hwif, wantclock);
}
-/*
- * Since SUN Cobalt is attempting to do this operation, I should disclose
- * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
- * HOTSWAP ATA Infrastructure.
- */
-
-static void hpt3xx_reset (ide_drive_t *drive)
-{
-}
-
-static int hpt3xx_tristate (ide_drive_t * drive, int state)
-{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
- u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40;
- u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;
-
- pci_read_config_byte(dev, 0x59, ®59h);
- pci_read_config_byte(dev, state_reg, ®XXh);
-
- if (state) {
- (void) ide_do_reset(drive);
- pci_write_config_byte(dev, state_reg, regXXh|0x80);
- pci_write_config_byte(dev, 0x59, reg59h|reset);
- } else {
- pci_write_config_byte(dev, 0x59, reg59h & ~(reset));
- pci_write_config_byte(dev, state_reg, regXXh & ~(0x80));
- (void) ide_do_reset(drive);
- }
- return 0;
-}
-
/*
- * set/get power state for a drive.
- * turning the power off does the following things:
- * 1) soft-reset the drive
- * 2) tri-states the ide bus
+ * Set/get power state for a drive.
*
- * when we turn things back on, we need to re-initialize things.
+ * When we turn the power back on, we need to re-initialize things.
*/
#define TRISTATE_BIT 0x8000
-static int hpt370_busproc(ide_drive_t * drive, int state)
+
+static int hpt3xx_busproc(ide_drive_t *drive, int state)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = hwif->pci_dev;
- u8 tristate = 0, resetmask = 0, bus_reg = 0;
- u16 tri_reg;
+ u8 tristate, resetmask, bus_reg = 0;
+ u16 tri_reg = 0;
hwif->bus_state = state;
if (hwif->channel) {
/* secondary channel */
- tristate = 0x56;
- resetmask = 0x80;
+ tristate = 0x56;
+ resetmask = 0x80;
} else {
/* primary channel */
- tristate = 0x52;
+ tristate = 0x52;
resetmask = 0x40;
}
- /* grab status */
+ /* Grab the status. */
pci_read_config_word(dev, tristate, &tri_reg);
pci_read_config_byte(dev, 0x59, &bus_reg);
- /* set the state. we don't set it if we don't need to do so.
- * make sure that the drive knows that it has failed if it's off */
+ /*
+ * Set the state. We don't set it if we don't need to do so.
+ * Make sure that the drive knows that it has failed if it's off.
+ */
switch (state) {
case BUSSTATE_ON:
- hwif->drives[0].failures = 0;
- hwif->drives[1].failures = 0;
- if ((bus_reg & resetmask) == 0)
+ if (!(bus_reg & resetmask))
return 0;
- tri_reg &= ~TRISTATE_BIT;
- bus_reg &= ~resetmask;
- break;
+ hwif->drives[0].failures = hwif->drives[1].failures = 0;
+
+ pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask);
+ pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT);
+ return 0;
case BUSSTATE_OFF:
- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
- if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask))
+ if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT))
return 0;
tri_reg &= ~TRISTATE_BIT;
- bus_reg |= resetmask;
break;
case BUSSTATE_TRISTATE:
- hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
- hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
- if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask))
+ if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT))
return 0;
tri_reg |= TRISTATE_BIT;
- bus_reg |= resetmask;
break;
+ default:
+ return -EINVAL;
}
- pci_write_config_byte(dev, 0x59, bus_reg);
- pci_write_config_word(dev, tristate, tri_reg);
+ hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+ hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+
+ pci_write_config_word(dev, tristate, tri_reg);
+ pci_write_config_byte(dev, 0x59, bus_reg | resetmask);
return 0;
}
@@ -1363,23 +1332,11 @@ static void __devinit init_hwif_hpt366(i
if (serialize && hwif->mate)
hwif->serialized = hwif->mate->serialized = 1;
- if (info->revision >= 3) {
- u8 reg5ah = 0;
- pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
- /*
- * set up ioctl for power status.
- * note: power affects both
- * drives on each channel
- */
- hwif->resetproc = &hpt3xx_reset;
- hwif->busproc = &hpt370_busproc;
- } else if (info->revision >= 2) {
- hwif->resetproc = &hpt3xx_reset;
- hwif->busproc = &hpt3xx_tristate;
- } else {
- hwif->resetproc = &hpt3xx_reset;
- hwif->busproc = &hpt3xx_tristate;
- }
+ /*
+ * Set up ioctl for power status.
+ * NOTE: power affects both drives on each channel.
+ */
+ hwif->busproc = &hpt3xx_busproc;
if (!hwif->dma_base) {
hwif->drives[0].autotune = 1;
next prev parent reply other threads:[~2006-05-02 22:15 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-04-23 8:33 [PATCH][RFT] HPT3xxN clocking fixes Sergei Shtylyov
2006-04-24 22:09 ` [PATCH][RFT] HPT3xxN clocking fixes (take 2) Sergei Shtylyov
2006-05-02 21:55 ` [PATCH][RFT] Fix HPT37x timing tables Sergei Shtylyov
2006-05-06 20:08 ` [PATCH] Optimize " Sergei Shtylyov
2006-05-02 22:14 ` Sergei Shtylyov [this message]
2006-05-02 22:26 ` [PATCH] Fix the case of multiple HPT3xx chips present Sergei Shtylyov
2006-05-04 19:46 ` [PATCH] HPT3xx: fix PCI clock detection Sergei Shtylyov
2006-05-16 22:44 ` [PATCH] HPT3xx: rework rate filtering Sergei Shtylyov
2006-05-20 8:51 ` [PATCH] HPT3xx: print the real chip name at startup Sergei Shtylyov
2006-05-27 22:05 ` [PATCH] HPT3xx: switch to using pci_find_slot() Sergei Shtylyov
2006-05-27 22:54 ` Jiri Slaby
2006-05-27 23:01 ` Sergei Shtylyov
2006-05-27 23:30 ` [PATCH] HPT3xx: switch to using pci_get_slot() Sergei Shtylyov
2006-05-28 2:55 ` [PATCH] HPT3xx: cache channel's MCR address Sergei Shtylyov
2006-06-04 22:24 ` [PATCH] HPT3x7: merge speedproc handlers Sergei Shtylyov
2006-06-11 21:18 ` [PATCH] HPT370: clean up DMA timeout handling Sergei Shtylyov
2006-06-27 21:41 ` [PATCH][RFT] HPT3xx: init code rewrite Sergei Shtylyov
2006-05-28 13:51 ` [PATCH] HPT3xx: switch to using pci_get_slot() Jiri Slaby
2006-05-29 14:26 ` Sergei Shtylyov
2006-05-20 8:41 ` [PATCH] HPT37x: read f_CNT saved by BIOS from port Sergei Shtylyov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4457D9D2.30206@ru.mvista.com \
--to=sshtylyov@ru.mvista.com \
--cc=akpm@osdl.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=bzolnier@gmail.com \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).