bk://gkernel.bkbits.net/libata-2.6
jgarzik@redhat.com|ChangeSet|20040402182304|06020 jgarzik

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/04/02 13:23:04-05:00 jgarzik@redhat.com 
#   Merge redhat.com:/spare/repo/linux-2.6
#   into redhat.com:/spare/repo/libata-2.6
# 
# include/linux/pci_ids.h
#   2004/04/02 13:23:00-05:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# drivers/scsi/sata_via.c
#   2004/04/02 13:23:00-05:00 jgarzik@redhat.com +0 -15
#   Auto merged
# 
# ChangeSet
#   2004/03/31 14:51:55-05:00 jgarzik@redhat.com 
#   [libata sata_via] Fix detection of device 1
#   
#   VIA hardware thinks port 1 (second port) is "SATA primary slave".
#   Since the hardware rarely configures SATA to present as slave devices,
#   we must pretend that the second hardware port (as the user sees it)
#   is the third port (as the VIA PCI config registers see it).
# 
# drivers/scsi/sata_via.c
#   2004/03/31 14:51:50-05:00 jgarzik@redhat.com +15 -10
#   [libata sata_via] Fix detection of device 1
#   
#   VIA hardware thinks port 1 (second port) is "SATA primary slave".
#   Since the hardware rarely configures SATA to present as slave devices,
#   we must pretend that the second hardware port (as the user sees it)
#   is the third port (as the VIA PCI config registers see it).
# 
# ChangeSet
#   2004/03/30 16:42:18-05:00 jgarzik@redhat.com 
#   [libata] fix broken delay
#   
#   Due to rounding and HZ==100, sometimes delays would not occur for
#   the desired length of time, or even at all.
#   
#   Fix call to schedule_timeout() to ensure we delay -at least- for
#   the correct amount of time.
# 
# drivers/scsi/libata-core.c
#   2004/03/30 11:42:11-05:00 jgarzik@redhat.com +1 -1
#   [libata] fix broken delay
#   
#   Due to rounding and HZ==100, sometimes delays would not occur for
#   the desired length of time, or even at all.
#   
#   Fix call to schedule_timeout() to ensure we delay -at least- for
#   the correct amount of time.
# 
# ChangeSet
#   2004/03/29 19:30:47-05:00 jgarzik@redhat.com 
#   [libata] back out duplicated upstream fix
#   
#   We already fixed this bug locally, so fix up the automerge
#   by removing the upstream change.
# 
# drivers/scsi/libata-scsi.c
#   2004/03/29 19:30:42-05:00 jgarzik@redhat.com +0 -2
#   [libata] back out duplicated upstream fix
#   
#   We already fixed this bug locally, so fix up the automerge
#   by removing the upstream change.
# 
# ChangeSet
#   2004/03/29 19:28:22-05:00 jgarzik@redhat.com 
#   Merge redhat.com:/spare/repo/linux-2.6
#   into redhat.com:/spare/repo/libata-2.6
# 
# drivers/scsi/libata-scsi.c
#   2004/03/29 19:28:20-05:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/27 00:21:34-05:00 jgarzik@redhat.com 
#   [libata] remove synchronize-cache dead code
#   
#   Just a placeholder, and now that a better way to do this is coming,
#   we don't even need the [unused] placeholder anymore.
# 
# drivers/scsi/libata-scsi.c
#   2004/03/27 00:21:29-05:00 jgarzik@redhat.com +0 -31
#   [libata] remove synchronize-cache dead code
#   
#   Just a placeholder, and now that a better way to do this is coming,
#   we don't even need the [unused] placeholder anymore.
# 
# ChangeSet
#   2004/03/26 22:14:11-05:00 jgarzik@redhat.com 
#   [libata] fix bug with READ(6) and WRITE(6) SCSI commands
#   
#   Must set the LBA bit on all transfers, not just {read,write}{10,16}
#   scsi commands.
# 
# drivers/scsi/libata-scsi.c
#   2004/03/26 22:14:06-05:00 jgarzik@redhat.com +1 -4
#   [libata] fix bug with READ(6) and WRITE(6) SCSI commands
#   
#   Must set the LBA bit on all transfers, not just {read,write}{10,16}
#   scsi commands.
# 
# ChangeSet
#   2004/03/26 20:40:58-05:00 jgarzik@redhat.com 
#   [libata sata_promise] better locking and error handling
#   
#   * Prefer spin_lock() to spin_lock_irq() in interrupt handler
#   * Reset each port, before probing the SATA phy
#   * Reset port when every time an error occurs
# 
# drivers/scsi/sata_promise.c
#   2004/03/26 20:40:53-05:00 jgarzik@redhat.com +66 -17
#   [libata sata_promise] better locking and error handling
#   
#   * Prefer spin_lock() to spin_lock_irq() in interrupt handler
#   * Reset each port, before probing the SATA phy
#   * Reset port when every time an error occurs
# 
# ChangeSet
#   2004/03/26 19:33:40-05:00 jgarzik@redhat.com 
#   Merge redhat.com:/spare/repo/linux-2.6
#   into redhat.com:/spare/repo/libata-2.6
# 
# include/linux/pci_ids.h
#   2004/03/26 19:33:38-05:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/26 18:02:34-05:00 jgarzik@redhat.com 
#   [libata] more documentation
#   
#   libata-scsi.c should now be fully documented.
# 
# drivers/scsi/libata-scsi.c
#   2004/03/26 18:02:29-05:00 jgarzik@redhat.com +125 -31
#   [libata] more documentation
#   
#   libata-scsi.c should now be fully documented.
# 
# ChangeSet
#   2004/03/26 04:04:17-05:00 jgarzik@redhat.com 
#   [libata] more cmd queue path cleanups
#   
#   Final part in tonight's series of changes to clean up the
#   command queueing path.
#   
#   The simulate-ATA-over-SCSI code is moved to a new function,
#   ata_scsi_simulate(), and ata_scsi_rw_queue() is renamed to
#   ata_scsi_translate().  With the SCSI CDB debugging dump function
#   also moved into its own function, the queue-command path is now
#   nice, compact, and readable.
# 
# drivers/scsi/libata-scsi.c
#   2004/03/26 04:04:12-05:00 jgarzik@redhat.com +50 -27
#   [libata] more cmd queue path cleanups
#   
#   Final part in tonight's series of changes to clean up the
#   command queueing path.
#   
#   The simulate-ATA-over-SCSI code is moved to a new function,
#   ata_scsi_simulate(), and ata_scsi_rw_queue() is renamed to
#   ata_scsi_translate().  With the SCSI CDB debugging dump function
#   also moved into its own function, the queue-command path is now
#   nice, compact, and readable.
# 
# ChangeSet
#   2004/03/26 03:32:10-05:00 jgarzik@redhat.com 
#   [libata] more command queue path cleanup
#   
#   A new helper ata_scsi_xlat_possible(), and the command queue path
#   gets a bit more compact.
#   
#   As side effects we kill the 'cmd_size' argument from two functions,
#   and mark ata_scsi_rw_queue() as static, as its only needed 
#   in libata-scsi.c.
# 
# drivers/scsi/libata.h
#   2004/03/26 03:32:05-05:00 jgarzik@redhat.com +0 -3
#   [libata] more command queue path cleanup
#   
#   A new helper ata_scsi_xlat_possible(), and the command queue path
#   gets a bit more compact.
#   
#   As side effects we kill the 'cmd_size' argument from two functions,
#   and mark ata_scsi_rw_queue() as static, as its only needed 
#   in libata-scsi.c.
# 
# drivers/scsi/libata-scsi.c
#   2004/03/26 03:32:05-05:00 jgarzik@redhat.com +28 -29
#   [libata] more command queue path cleanup
#   
#   A new helper ata_scsi_xlat_possible(), and the command queue path
#   gets a bit more compact.
#   
#   As side effects we kill the 'cmd_size' argument from two functions,
#   and mark ata_scsi_rw_queue() as static, as its only needed 
#   in libata-scsi.c.
# 
# ChangeSet
#   2004/03/26 03:20:47-05:00 jgarzik@redhat.com 
#   [libata] clean up command queue/submit path a bit
#   
#   This change is part of a series that compartmentalizes and consolidates
#   ATA taskfile submission.
#   
#   Here, the device-location-related checks are moved out of the ->queuecommand()
#   hook and into an inline helper function.
# 
# drivers/scsi/libata-scsi.c
#   2004/03/26 03:20:42-05:00 jgarzik@redhat.com +38 -32
#   [libata] clean up command queue/submit path a bit
#   
#   This change is part of a series that compartmentalizes and consolidates
#   ATA taskfile submission.
#   
#   Here, the device-location-related checks are moved out of the ->queuecommand()
#   hook and into an inline helper function.
# 
# ChangeSet
#   2004/03/26 01:13:20-05:00 jgarzik@redhat.com 
#   [libata sata_promise] minor initialization updates
#   
#   * remove incorrect PATA port check
#   * enable undocumented bit 13 in flash control register,
#     because the Promise driver does so.
#   * wait 10 ms after setting TBG mode, for the same reason.
# 
# drivers/scsi/sata_promise.c
#   2004/03/26 01:13:16-05:00 jgarzik@redhat.com +15 -22
#   [libata sata_promise] minor initialization updates
#   
#   * remove incorrect PATA port check
#   * enable undocumented bit 13 in flash control register,
#     because the Promise driver does so.
#   * wait 10 ms after setting TBG mode, for the same reason.
# 
# ChangeSet
#   2004/03/25 17:23:41-05:00 jgarzik@redhat.com 
#   [libata] documentation, and a couple tiny cleanups
#   
#   Add more per-function source code documentation.  Some of this stuff
#   is esoteric ATA crapola, and definitely needed to be documented.
#   
#   Also, two tiny cleanups spotted while documenting:
#   * kill unused arg from internal function ata_dev_try_classify()
#   * kill unused return value from ata_dev_id_string()
# 
# drivers/scsi/libata.h
#   2004/03/25 17:23:37-05:00 jgarzik@redhat.com +2 -2
#   [libata] documentation, and a couple tiny cleanups
#   
#   Add more per-function source code documentation.  Some of this stuff
#   is esoteric ATA crapola, and definitely needed to be documented.
#   
#   Also, two tiny cleanups spotted while documenting:
#   * kill unused arg from internal function ata_dev_try_classify()
#   * kill unused return value from ata_dev_id_string()
# 
# drivers/scsi/libata-core.c
#   2004/03/25 17:23:37-05:00 jgarzik@redhat.com +125 -50
#   [libata] documentation, and a couple tiny cleanups
#   
#   Add more per-function source code documentation.  Some of this stuff
#   is esoteric ATA crapola, and definitely needed to be documented.
#   
#   Also, two tiny cleanups spotted while documenting:
#   * kill unused arg from internal function ata_dev_try_classify()
#   * kill unused return value from ata_dev_id_string()
# 
# ChangeSet
#   2004/03/25 14:40:17-05:00 jgarzik@redhat.com 
#   [libata] use scsi host lock
#   
#   In 2.4 we release io_request_lock and take our own per-host lock,
#   in the ->queuecommand() hook.  In 2.6, the SCSI layer provides a
#   useful to simply use the lock we already have, via scsi_assign_lock().
# 
# drivers/scsi/libata-scsi.c
#   2004/03/25 14:40:12-05:00 jgarzik@redhat.com +1 -8
#   [libata] use scsi host lock
#   
#   In 2.4 we release io_request_lock and take our own per-host lock,
#   in the ->queuecommand() hook.  In 2.6, the SCSI layer provides a
#   useful to simply use the lock we already have, via scsi_assign_lock().
# 
# drivers/scsi/libata-core.c
#   2004/03/25 14:40:12-05:00 jgarzik@redhat.com +1 -0
#   [libata] use scsi host lock
#   
#   In 2.4 we release io_request_lock and take our own per-host lock,
#   in the ->queuecommand() hook.  In 2.6, the SCSI layer provides a
#   useful to simply use the lock we already have, via scsi_assign_lock().
# 
# ChangeSet
#   2004/03/25 14:36:59-05:00 jgarzik@redhat.com 
#   [libata] reduce diff with 2.4 libata backport
# 
# include/linux/libata.h
#   2004/03/25 14:36:54-05:00 jgarzik@redhat.com +1 -1
#   [libata] reduce diff with 2.4 libata backport
# 
# ChangeSet
#   2004/03/25 14:36:27-05:00 jgarzik@redhat.com 
#   [libata] pci_dma_error() was renamed to pci_dma_mapping_error()
# 
# drivers/scsi/libata-core.c
#   2004/03/25 14:36:22-05:00 jgarzik@redhat.com +1 -1
#   [libata] pci_dma_error() was renamed to pci_dma_mapping_error()
# 
# ChangeSet
#   2004/03/25 14:18:04-05:00 jgarzik@redhat.com 
#   Merge redhat.com:/spare/repo/linux-2.6
#   into redhat.com:/spare/repo/libata-2.6
# 
# drivers/scsi/Kconfig
#   2004/03/25 14:18:02-05:00 jgarzik@redhat.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/25 01:57:34-05:00 jgarzik@redhat.com 
#   [ata] move some generic stuff linux/libata.h -> linux/ata.h
#   
#   struct ata_taskfile is generic, and so far its flags (ATA_TFLAG_xxx)
#   
#   Also, move ATA_PROT_xxx definitions into their own enum.
# 
# include/linux/libata.h
#   2004/03/25 01:57:29-05:00 jgarzik@redhat.com +0 -29
#   [ata] move some generic stuff linux/libata.h -> linux/ata.h
#   
#   struct ata_taskfile is generic, and so far its flags (ATA_TFLAG_xxx)
#   
#   Also, move ATA_PROT_xxx definitions into their own enum.
# 
# include/linux/ata.h
#   2004/03/25 01:57:29-05:00 jgarzik@redhat.com +41 -8
#   [ata] move some generic stuff linux/libata.h -> linux/ata.h
#   
#   struct ata_taskfile is generic, and so far its flags (ATA_TFLAG_xxx)
#   
#   Also, move ATA_PROT_xxx definitions into their own enum.
# 
# ChangeSet
#   2004/03/25 01:44:08-05:00 jgarzik@redhat.com 
#   [libata] consolidate data transfer mode handling
#   
#   The various ways you can send data to/from your ATA device is
#   known as the ATA taskfile protocol:  PIO single sector, PIO
#   multiple sector, DMA, DMA TCQ, DMA NCQ, ...
#   
#   Prior to this change, the data direction (read/write) was encoded
#   implicitly into the ATA_PROT_xxx value itself.  This increased
#   complexity in some areas, and inhibited flexibility in others.
#   
#   This change separates data direction from taskfile protocol, and also
#   moves the data direction flag (ATA_QCFLAG_WRITE) down to a lower
#   level (ATA_TFLAG_WRITE).
# 
# include/linux/libata.h
#   2004/03/25 01:44:03-05:00 jgarzik@redhat.com +3 -4
#   [libata] consolidate data transfer mode handling
#   
#   The various ways you can send data to/from your ATA device is
#   known as the ATA taskfile protocol:  PIO single sector, PIO
#   multiple sector, DMA, DMA TCQ, DMA NCQ, ...
#   
#   Prior to this change, the data direction (read/write) was encoded
#   implicitly into the ATA_PROT_xxx value itself.  This increased
#   complexity in some areas, and inhibited flexibility in others.
#   
#   This change separates data direction from taskfile protocol, and also
#   moves the data direction flag (ATA_QCFLAG_WRITE) down to a lower
#   level (ATA_TFLAG_WRITE).
# 
# include/linux/ata.h
#   2004/03/25 01:44:03-05:00 jgarzik@redhat.com +2 -4
#   [libata] consolidate data transfer mode handling
#   
#   The various ways you can send data to/from your ATA device is
#   known as the ATA taskfile protocol:  PIO single sector, PIO
#   multiple sector, DMA, DMA TCQ, DMA NCQ, ...
#   
#   Prior to this change, the data direction (read/write) was encoded
#   implicitly into the ATA_PROT_xxx value itself.  This increased
#   complexity in some areas, and inhibited flexibility in others.
#   
#   This change separates data direction from taskfile protocol, and also
#   moves the data direction flag (ATA_QCFLAG_WRITE) down to a lower
#   level (ATA_TFLAG_WRITE).
# 
# drivers/scsi/sata_promise.c
#   2004/03/25 01:44:03-05:00 jgarzik@redhat.com +24 -29
#   [libata] consolidate data transfer mode handling
#   
#   The various ways you can send data to/from your ATA device is
#   known as the ATA taskfile protocol:  PIO single sector, PIO
#   multiple sector, DMA, DMA TCQ, DMA NCQ, ...
#   
#   Prior to this change, the data direction (read/write) was encoded
#   implicitly into the ATA_PROT_xxx value itself.  This increased
#   complexity in some areas, and inhibited flexibility in others.
#   
#   This change separates data direction from taskfile protocol, and also
#   moves the data direction flag (ATA_QCFLAG_WRITE) down to a lower
#   level (ATA_TFLAG_WRITE).
# 
# drivers/scsi/libata-scsi.c
#   2004/03/25 01:44:03-05:00 jgarzik@redhat.com +4 -6
#   [libata] consolidate data transfer mode handling
#   
#   The various ways you can send data to/from your ATA device is
#   known as the ATA taskfile protocol:  PIO single sector, PIO
#   multiple sector, DMA, DMA TCQ, DMA NCQ, ...
#   
#   Prior to this change, the data direction (read/write) was encoded
#   implicitly into the ATA_PROT_xxx value itself.  This increased
#   complexity in some areas, and inhibited flexibility in others.
#   
#   This change separates data direction from taskfile protocol, and also
#   moves the data direction flag (ATA_QCFLAG_WRITE) down to a lower
#   level (ATA_TFLAG_WRITE).
# 
# drivers/scsi/libata-core.c
#   2004/03/25 01:44:03-05:00 jgarzik@redhat.com +15 -23
#   [libata] consolidate data transfer mode handling
#   
#   The various ways you can send data to/from your ATA device is
#   known as the ATA taskfile protocol:  PIO single sector, PIO
#   multiple sector, DMA, DMA TCQ, DMA NCQ, ...
#   
#   Prior to this change, the data direction (read/write) was encoded
#   implicitly into the ATA_PROT_xxx value itself.  This increased
#   complexity in some areas, and inhibited flexibility in others.
#   
#   This change separates data direction from taskfile protocol, and also
#   moves the data direction flag (ATA_QCFLAG_WRITE) down to a lower
#   level (ATA_TFLAG_WRITE).
# 
# ChangeSet
#   2004/03/25 00:53:07-05:00 jgarzik@redhat.com 
#   [libata] set up some of the per-command data beforehand
#   
#   The data transfer mode and the set of read/write commands we generate
#   during normal operation remains constant until we change the data
#   transfer mode.
#   
#   This removes a series of branches in the read/write fast path,
#   and in general cleans up that particular spot of code.
# 
# include/linux/libata.h
#   2004/03/25 00:53:02-05:00 jgarzik@redhat.com +6 -0
#   [libata] set up some of the per-command data beforehand
#   
#   The data transfer mode and the set of read/write commands we generate
#   during normal operation remains constant until we change the data
#   transfer mode.
#   
#   This removes a series of branches in the read/write fast path,
#   and in general cleans up that particular spot of code.
# 
# drivers/scsi/libata-scsi.c
#   2004/03/25 00:53:02-05:00 jgarzik@redhat.com +4 -27
#   [libata] set up some of the per-command data beforehand
#   
#   The data transfer mode and the set of read/write commands we generate
#   during normal operation remains constant until we change the data
#   transfer mode.
#   
#   This removes a series of branches in the read/write fast path,
#   and in general cleans up that particular spot of code.
# 
# drivers/scsi/libata-core.c
#   2004/03/25 00:53:02-05:00 jgarzik@redhat.com +65 -7
#   [libata] set up some of the per-command data beforehand
#   
#   The data transfer mode and the set of read/write commands we generate
#   during normal operation remains constant until we change the data
#   transfer mode.
#   
#   This removes a series of branches in the read/write fast path,
#   and in general cleans up that particular spot of code.
# 
# ChangeSet
#   2004/03/24 23:50:34-05:00 jgarzik@redhat.com 
#   [libata sata_promise] check for PATA port on PDC20375
#   
#   We don't handle it yet, but this prints out a message in its presence,
#   permitting verification of the check and informing users why their
#   PATA device is not recognized.
# 
# drivers/scsi/sata_promise.c
#   2004/03/24 23:50:29-05:00 jgarzik@redhat.com +20 -1
#   [libata sata_promise] check for PATA port on PDC20375
#   
#   We don't handle it yet, but this prints out a message in its presence,
#   permitting verification of the check and informing users why their
#   PATA device is not recognized.
# 
# ChangeSet
#   2004/03/23 12:35:54-05:00 jgarzik@redhat.com 
#   [libata ata_piix] fix combined mode device detection
#   
#   SATA port detection should not have assumed that a single SATA port
#   mapped to a single struct ata_port.  Combined mode breaks this
#   assumption.
#   
#   Change code to simply detect if one or more devices are present
#   on the struct ata_port, which is what we really wanted to do.
# 
# drivers/scsi/ata_piix.c
#   2004/03/23 12:35:45-05:00 jgarzik@redhat.com +36 -29
#   [libata ata_piix] fix combined mode device detection
#   
#   SATA port detection should not have assumed that a single SATA port
#   mapped to a single struct ata_port.  Combined mode breaks this
#   assumption.
#   
#   Change code to simply detect if one or more devices are present
#   on the struct ata_port, which is what we really wanted to do.
# 
# ChangeSet
#   2004/03/23 11:52:00-05:00 jgarzik@redhat.com 
#   [libata ata_piix] clean up combined mode handling
# 
# drivers/scsi/ata_piix.c
#   2004/03/23 11:51:55-05:00 jgarzik@redhat.com +24 -39
#   [libata ata_piix] clean up combined mode handling
# 
# ChangeSet
#   2004/03/23 11:14:06-05:00 jgarzik@redhat.com 
#   [libata ata_piix] do not disable SATA port on module unload
#   
#   We were disabling the SATA port, but not enabling it on module load.
#   So, modprobe+rmmod+modprobe would fail.
# 
# drivers/scsi/ata_piix.c
#   2004/03/23 11:14:01-05:00 jgarzik@redhat.com +11 -52
#   [libata ata_piix] do not disable SATA port on module unload
#   
#   We were disabling the SATA port, but not enabling it on module load.
#   So, modprobe+rmmod+modprobe would fail.
# 
# ChangeSet
#   2004/03/23 09:20:14-05:00 jgarzik@redhat.com 
#   [libata] use kmap_atomic() rather than kmap()
# 
# drivers/scsi/libata-scsi.c
#   2004/03/23 09:20:09-05:00 jgarzik@redhat.com +2 -3
#   [libata] use kmap_atomic() rather than kmap()
# 
# ChangeSet
#   2004/03/22 23:40:01-05:00 jgarzik@redhat.com 
#   [libata] use new pci_dma_error() to check for pci_map_single() failure
# 
# drivers/scsi/libata-core.c
#   2004/03/22 23:38:20-05:00 jgarzik@redhat.com +7 -3
#   [libata] use new pci_dma_error() to check for pci_map_single() failure
# 
# ChangeSet
#   2004/03/21 12:15:16-05:00 jgarzik@redhat.com 
#   [libata sata_sis] minor cleanups
# 
# include/linux/pci_ids.h
#   2004/03/21 12:15:11-05:00 jgarzik@redhat.com +1 -0
#   [libata sata_sis] minor cleanups
# 
# drivers/scsi/sata_sis.c
#   2004/03/21 12:15:11-05:00 jgarzik@redhat.com +24 -33
#   [libata sata_sis] minor cleanups
# 
# ChangeSet
#   2004/03/21 11:55:35-05:00 uwe.koziolek@gmx.net 
#   [libata] Add driver for SiS 964/180 SATA.
# 
# drivers/scsi/Makefile
#   2004/03/21 11:54:11-05:00 uwe.koziolek@gmx.net +1 -0
#   [libata] Add driver for SiS 964/180 SATA.
# 
# drivers/scsi/Kconfig
#   2004/03/21 11:54:11-05:00 uwe.koziolek@gmx.net +8 -0
#   [libata] Add driver for SiS 964/180 SATA.
# 
# drivers/scsi/sata_sis.c
#   2004/03/21 11:53:36-05:00 jgarzik@redhat.com +223 -0
# 
# drivers/scsi/sata_sis.c
#   2004/03/21 11:53:36-05:00 jgarzik@redhat.com +0 -0
#   BitKeeper file /spare/repo/libata-2.6/drivers/scsi/sata_sis.c
# 
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	Thu Apr  8 14:58:15 2004
+++ b/drivers/scsi/Kconfig	Thu Apr  8 14:58:15 2004
@@ -449,6 +449,14 @@
 
 	  If unsure, say N.
 
+config SCSI_SATA_SIS
+	tristate "SiS 964/180 SATA support"
+	depends on SCSI_SATA && PCI
+	help
+	  This option enables support for SiS Serial ATA 964/180.
+
+	  If unsure, say N.
+
 config SCSI_SATA_VIA
 	tristate "VIA SATA support"
 	depends on SCSI_SATA && PCI && EXPERIMENTAL
diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile	Thu Apr  8 14:58:15 2004
+++ b/drivers/scsi/Makefile	Thu Apr  8 14:58:15 2004
@@ -123,6 +123,7 @@
 obj-$(CONFIG_SCSI_SATA_SIL)	+= libata.o sata_sil.o
 obj-$(CONFIG_SCSI_SATA_VIA)	+= libata.o sata_via.o
 obj-$(CONFIG_SCSI_SATA_VITESSE)	+= libata.o sata_vsc.o
+obj-$(CONFIG_SCSI_SATA_SIS)	+= libata.o sata_sis.o
 
 obj-$(CONFIG_ARM)		+= arm/
 
diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c	Thu Apr  8 14:58:15 2004
+++ b/drivers/scsi/ata_piix.c	Thu Apr  8 14:58:15 2004
@@ -28,17 +28,24 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"ata_piix"
-#define DRV_VERSION	"1.01"
+#define DRV_VERSION	"1.02"
 
 enum {
 	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */
+	ICH5_PMR		= 0x90, /* port mapping register */
 	ICH5_PCS		= 0x92,	/* port control and status */
 
 	PIIX_FLAG_CHECKINTR	= (1 << 29), /* make sure PCI INTx enabled */
 	PIIX_FLAG_COMBINED	= (1 << 30), /* combined mode possible */
 
-	PIIX_COMB_PRI		= (1 << 0), /* combined mode, PATA primary */
-	PIIX_COMB_SEC		= (1 << 1), /* combined mode, PATA secondary */
+	/* combined mode.  if set, PATA is channel 0.
+	 * if clear, PATA is channel 1.
+	 */
+	PIIX_COMB_PATA_P0	= (1 << 1),
+	PIIX_COMB		= (1 << 2), /* combined mode enabled? */
+
+	PIIX_PORT_PRESENT	= (1 << 0),
+	PIIX_PORT_ENABLED	= (1 << 4),
 
 	PIIX_80C_PRI		= (1 << 5) | (1 << 4),
 	PIIX_80C_SEC		= (1 << 7) | (1 << 6),
@@ -53,7 +60,6 @@
 
 static void piix_pata_phy_reset(struct ata_port *ap);
 static void piix_sata_phy_reset(struct ata_port *ap);
-static void piix_sata_port_disable(struct ata_port *ap);
 static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev,
 			      unsigned int pio);
 static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev,
@@ -137,7 +143,7 @@
 };
 
 static struct ata_port_operations piix_sata_ops = {
-	.port_disable		= piix_sata_port_disable,
+	.port_disable		= ata_port_disable,
 	.set_piomode		= piix_set_piomode,
 	.set_udmamode		= piix_set_udmamode,
 
@@ -259,54 +265,48 @@
 }
 
 /**
- *	piix_pcs_probe - Probe SATA port configuration and status register
- *	@ap: Port to probe
- *	@have_port: (output) Non-zero if SATA port is enabled
- *	@have_device: (output) Non-zero if SATA phy indicates device present
+ *	piix_sata_probe - Probe PCI device for present SATA devices
+ *	@pdev: PCI device to probe
  *
  *	Reads SATA PCI device's PCI config register Port Configuration
  *	and Status (PCS) to determine port and device availability.
  *
  *	LOCKING:
  *	None (inherited from caller).
- */
-static void piix_pcs_probe (struct ata_port *ap, unsigned int *have_port,
-			    unsigned int *have_device)
-{
-	struct pci_dev *pdev = ap->host_set->pdev;
-	u16 pcs;
-
-	pci_read_config_word(pdev, ICH5_PCS, &pcs);
-
-	/* is SATA port enabled? */
-	if (pcs & (1 << ap->port_no)) {
-		*have_port = 1;
-
-		if (pcs & (1 << (ap->port_no + 4)))
-			*have_device = 1;
-	}
-}
-
-/**
- *	piix_pcs_disable - Disable SATA port
- *	@ap: Port to disable
- *
- *	Disable SATA phy for specified port.
  *
- *	LOCKING:
- *	None (inherited from caller).
+ *	RETURNS:
+ *	Non-zero if device detected, zero otherwise.
  */
-static void piix_pcs_disable (struct ata_port *ap)
+static int piix_sata_probe (struct ata_port *ap)
 {
 	struct pci_dev *pdev = ap->host_set->pdev;
-	u16 pcs;
+	int combined = (ap->flags & ATA_FLAG_SLAVE_POSS);
+	int orig_mask, mask, i;
+	u8 pcs;
+
+	mask = (PIIX_PORT_PRESENT << ap->port_no) |
+	       (PIIX_PORT_ENABLED << ap->port_no);
+
+	pci_read_config_byte(pdev, ICH5_PCS, &pcs);
+	orig_mask = (int) pcs & 0xff;
+
+	/* TODO: this is vaguely wrong for ICH6 combined mode,
+	 * where only two of the four SATA ports are mapped
+	 * onto a single ATA channel.  It is also vaguely inaccurate
+	 * for ICH5, which has only two ports.  However, this is ok,
+	 * as further device presence detection code will handle
+	 * any false positives produced here.
+	 */
 
-	pci_read_config_word(pdev, ICH5_PCS, &pcs);
+	for (i = 0; i < 4; i++) {
+		mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i);
 
-	if (pcs & (1 << ap->port_no)) {
-		pcs &= ~(1 << ap->port_no);
-		pci_write_config_word(pdev, ICH5_PCS, pcs);
+		if ((orig_mask & mask) == mask)
+			if (combined || (i == ap->port_no))
+				return 1;
 	}
+
+	return 0;
 }
 
 /**
@@ -321,8 +321,6 @@
 
 static void piix_sata_phy_reset(struct ata_port *ap)
 {
-	unsigned int have_port = 0, have_dev = 0;
-
 	if (!pci_test_config_bits(ap->host_set->pdev,
 				  &piix_enable_bits[ap->port_no])) {
 		ata_port_disable(ap);
@@ -330,21 +328,9 @@
 		return;
 	}
 
-	piix_pcs_probe(ap, &have_port, &have_dev);
-
-	/* if port not enabled, exit */
-	if (!have_port) {
+	if (!piix_sata_probe(ap)) {
 		ata_port_disable(ap);
-		printk(KERN_INFO "ata%u: SATA port disabled. ignoring.\n",
-		       ap->id);
-		return;
-	}
-
-	/* if port enabled but no device, disable port and exit */
-	if (!have_dev) {
-		piix_sata_port_disable(ap);
-		printk(KERN_INFO "ata%u: SATA port has no device. disabling.\n",
-		       ap->id);
+		printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
 		return;
 	}
 
@@ -356,22 +342,6 @@
 }
 
 /**
- *	piix_sata_port_disable - Disable SATA port
- *	@ap: Port to disable.
- *
- *	Disable SATA port.
- *
- *	LOCKING:
- *	None (inherited from caller).
- */
-
-static void piix_sata_port_disable(struct ata_port *ap)
-{
-	ata_port_disable(ap);
-	piix_pcs_disable(ap);
-}
-
-/**
  *	piix_set_piomode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
  *	@adev: um
@@ -493,31 +463,6 @@
 	}
 }
 
-/**
- *	piix_probe_combined - Determine if PATA and SATA are combined
- *	@pdev: PCI device to examine
- *	@mask: (output) zero, %PIIX_COMB_PRI or %PIIX_COMB_SEC
- *
- *	Determine if BIOS has secretly stuffed a PATA port into our
- *	otherwise-beautiful SATA PCI device.
- *
- *	LOCKING:
- *	Inherited from PCI layer (may sleep).
- */
-static void piix_probe_combined (struct pci_dev *pdev, unsigned int *mask)
-{
-	u8 tmp;
-
-	pci_read_config_byte(pdev, 0x90, &tmp); /* combined mode reg */
-	tmp &= 0x6; 	/* interesting bits 2:1, PATA primary/secondary */
-
-	/* backwards from what one might expect */
-	if (tmp == 0x4)	/* bits 10x */
-		*mask |= PIIX_COMB_SEC;
-	if (tmp == 0x6)	/* bits 11x */
-		*mask |= PIIX_COMB_PRI;
-}
-
 /* move to PCI layer, integrate w/ MSI stuff */
 static void pci_enable_intx(struct pci_dev *pdev)
 {
@@ -550,7 +495,7 @@
 	static int printed_version;
 	struct ata_port_info *port_info[2];
 	unsigned int combined = 0, n_ports = 1;
-	unsigned int pata_comb = 0, sata_comb = 0;
+	unsigned int pata_chan = 0, sata_chan = 0;
 
 	if (!printed_version++)
 		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
@@ -561,8 +506,19 @@
 
 	port_info[0] = &piix_port_info[ent->driver_data];
 	port_info[1] = NULL;
-	if (port_info[0]->host_flags & PIIX_FLAG_COMBINED)
-		piix_probe_combined(pdev, &combined);
+
+	if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
+		u8 tmp;
+		pci_read_config_byte(pdev, ICH5_PMR, &tmp);
+
+		if (tmp & PIIX_COMB) {
+			combined = 1;
+			if (tmp & PIIX_COMB_PATA_P0)
+				sata_chan = 1;
+			else
+				pata_chan = 1;
+		}
+	}
 
 	/* On ICH5, some BIOSen disable the interrupt using the
 	 * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
@@ -573,15 +529,10 @@
 	if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR)
 		pci_enable_intx(pdev);
 
-	if (combined & PIIX_COMB_PRI)
-		sata_comb = 1;
-	else if (combined & PIIX_COMB_SEC)
-		pata_comb = 1;
-
-	if (pata_comb || sata_comb) {
-		port_info[sata_comb] = &piix_port_info[ent->driver_data];
-		port_info[sata_comb]->host_flags |= ATA_FLAG_SLAVE_POSS; /* sigh */
-		port_info[pata_comb] = &piix_port_info[ich5_pata]; /*ich5-specific*/
+	if (combined) {
+		port_info[sata_chan] = &piix_port_info[ent->driver_data];
+		port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS;
+		port_info[pata_chan] = &piix_port_info[ich5_pata];
 		n_ports++;
 
 		printk(KERN_WARNING DRV_NAME ": combined mode detected\n");
diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c	Thu Apr  8 14:58:15 2004
+++ b/drivers/scsi/libata-core.c	Thu Apr  8 14:58:15 2004
@@ -118,7 +118,7 @@
 static void msleep(unsigned long msecs)
 {
 	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(msecs));
+	schedule_timeout(msecs_to_jiffies(msecs) + 1);
 }
 
 /**
@@ -439,6 +439,81 @@
        	return readb((void *) ap->ioaddr.status_addr);
 }
 
+/**
+ *	ata_prot_to_cmd - determine which read/write opcodes to use
+ *	@protocol: ATA_PROT_xxx taskfile protocol
+ *	@lba48: true is lba48 is present
+ *
+ *	Given necessary input, determine which read/write commands
+ *	to use to transfer data.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static int ata_prot_to_cmd(int protocol, int lba48)
+{
+	int rcmd = 0, wcmd = 0;
+
+	switch (protocol) {
+	case ATA_PROT_PIO:
+		if (lba48) {
+			rcmd = ATA_CMD_PIO_READ_EXT;
+			wcmd = ATA_CMD_PIO_WRITE_EXT;
+		} else {
+			rcmd = ATA_CMD_PIO_READ;
+			wcmd = ATA_CMD_PIO_WRITE;
+		}
+		break;
+
+	case ATA_PROT_DMA:
+		if (lba48) {
+			rcmd = ATA_CMD_READ_EXT;
+			wcmd = ATA_CMD_WRITE_EXT;
+		} else {
+			rcmd = ATA_CMD_READ;
+			wcmd = ATA_CMD_WRITE;
+		}
+		break;
+
+	default:
+		return -1;
+	}
+
+	return rcmd | (wcmd << 8);
+}
+
+/**
+ *	ata_dev_set_protocol - set taskfile protocol and r/w commands
+ *	@dev: device to examine and configure
+ *
+ *	Examine the device configuration, after we have
+ *	read the identify-device page and configured the
+ *	data transfer mode.  Set internal state related to
+ *	the ATA taskfile protocol (pio, pio mult, dma, etc.)
+ *	and calculate the proper read/write commands to use.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+static void ata_dev_set_protocol(struct ata_device *dev)
+{
+	int pio = (dev->flags & ATA_DFLAG_PIO);
+	int lba48 = (dev->flags & ATA_DFLAG_LBA48);
+	int proto, cmd;
+
+	if (pio)
+		proto = dev->xfer_protocol = ATA_PROT_PIO;
+	else
+		proto = dev->xfer_protocol = ATA_PROT_DMA;
+
+	cmd = ata_prot_to_cmd(proto, lba48);
+	if (cmd < 0)
+		BUG();
+
+	dev->read_cmd = cmd & 0xff;
+	dev->write_cmd = (cmd >> 8) & 0xff;
+}
+
 static const char * udma_str[] = {
 	"UDMA/16",
 	"UDMA/25",
@@ -478,12 +553,21 @@
 }
 
 /**
- *	ata_pio_devchk -
- *	@ap:
- *	@device:
+ *	ata_pio_devchk - PATA device presence detection
+ *	@ap: ATA channel to examine
+ *	@device: Device to examine (starting at zero)
  *
- *	LOCKING:
+ *	This technique was originally described in
+ *	Hale Landis's ATADRVR (www.ata-atapi.com), and
+ *	later found its way into the ATA/ATAPI spec.
  *
+ *	Write a pattern to the ATA shadow registers,
+ *	and if a device is present, it will respond by
+ *	correctly storing and echoing back the
+ *	ATA shadow register contents.
+ *
+ *	LOCKING:
+ *	caller.
  */
 
 static unsigned int ata_pio_devchk(struct ata_port *ap,
@@ -513,12 +597,21 @@
 }
 
 /**
- *	ata_mmio_devchk -
- *	@ap:
- *	@device:
+ *	ata_mmio_devchk - PATA device presence detection
+ *	@ap: ATA channel to examine
+ *	@device: Device to examine (starting at zero)
  *
- *	LOCKING:
+ *	This technique was originally described in
+ *	Hale Landis's ATADRVR (www.ata-atapi.com), and
+ *	later found its way into the ATA/ATAPI spec.
  *
+ *	Write a pattern to the ATA shadow registers,
+ *	and if a device is present, it will respond by
+ *	correctly storing and echoing back the
+ *	ATA shadow register contents.
+ *
+ *	LOCKING:
+ *	caller.
  */
 
 static unsigned int ata_mmio_devchk(struct ata_port *ap,
@@ -548,12 +641,16 @@
 }
 
 /**
- *	ata_dev_devchk -
- *	@ap:
- *	@device:
+ *	ata_dev_devchk - PATA device presence detection
+ *	@ap: ATA channel to examine
+ *	@device: Device to examine (starting at zero)
  *
- *	LOCKING:
+ *	Dispatch ATA device presence detection, depending
+ *	on whether we are using PIO or MMIO to talk to the
+ *	ATA shadow registers.
  *
+ *	LOCKING:
+ *	caller.
  */
 
 static unsigned int ata_dev_devchk(struct ata_port *ap,
@@ -604,16 +701,24 @@
 }
 
 /**
- *	ata_dev_try_classify -
- *	@ap:
- *	@device:
+ *	ata_dev_try_classify - Parse returned ATA device signature
+ *	@ap: ATA channel to examine
+ *	@device: Device to examine (starting at zero)
  *
- *	LOCKING:
+ *	After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
+ *	an ATA/ATAPI-defined set of values is placed in the ATA
+ *	shadow registers, indicating the results of device detection
+ *	and diagnostics.
  *
+ *	Select the ATA device, and read the values from the ATA shadow
+ *	registers.  Then parse according to the Error register value,
+ *	and the spec-defined values examined by ata_dev_classify().
+ *
+ *	LOCKING:
+ *	caller.
  */
 
-static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device,
-			       unsigned int maybe_have_dev)
+static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
 {
 	struct ata_device *dev = &ap->device[device];
 	struct ata_taskfile tf;
@@ -650,44 +755,51 @@
 }
 
 /**
- *	ata_dev_id_string -
- *	@dev:
- *	@s:
- *	@ofs:
- *	@len:
+ *	ata_dev_id_string - Convert IDENTIFY DEVICE page into string
+ *	@dev: Device whose IDENTIFY DEVICE results we will examine
+ *	@s: string into which data is output
+ *	@ofs: offset into identify device page
+ *	@len: length of string to return
  *
- *	LOCKING:
- *
- *	RETURNS:
+ *	The strings in the IDENTIFY DEVICE page are broken up into
+ *	16-bit chunks.  Run through the string, and output each
+ *	8-bit chunk linearly, regardless of platform.
  *
+ *	LOCKING:
+ *	caller.
  */
 
-unsigned int ata_dev_id_string(struct ata_device *dev, unsigned char *s,
-			       unsigned int ofs, unsigned int len)
+void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
+		       unsigned int ofs, unsigned int len)
 {
-	unsigned int c, ret = 0;
+	unsigned int c;
 
 	while (len > 0) {
 		c = dev->id[ofs] >> 8;
 		*s = c;
 		s++;
 
-		ret = c = dev->id[ofs] & 0xff;
+		c = dev->id[ofs] & 0xff;
 		*s = c;
 		s++;
 
 		ofs++;
 		len -= 2;
 	}
-
-	return ret;
 }
 
 /**
- *	ata_dev_parse_strings -
- *	@dev:
+ *	ata_dev_parse_strings - Store useful IDENTIFY DEVICE page strings
+ *	@dev: Device whose IDENTIFY DEVICE page info we use
+ *
+ *	We store 'vendor' and 'product' strings read from the device,
+ *	for later use in the SCSI simulator's INQUIRY data.
+ *
+ *	Set these strings here, in the case of 'product', using
+ *	data read from the ATA IDENTIFY DEVICE page.
  *
  *	LOCKING:
+ *	caller.
  */
 
 static void ata_dev_parse_strings(struct ata_device *dev)
@@ -700,12 +812,16 @@
 }
 
 /**
- *	__ata_dev_select -
- *	@ap:
- *	@device:
+ *	__ata_dev_select - Select device 0/1 on ATA bus
+ *	@ap: ATA channel to manipulate
+ *	@device: ATA device (numbered from zero) to select
  *
- *	LOCKING:
+ *	Use the method defined in the ATA specification to
+ *	make either device 0, or device 1, active on the
+ *	ATA channel.
  *
+ *	LOCKING:
+ *	caller.
  */
 
 static void __ata_dev_select (struct ata_port *ap, unsigned int device)
@@ -726,16 +842,22 @@
 }
 
 /**
- *	ata_dev_select -
- *	@ap:
- *	@device:
- *	@wait:
- *	@can_sleep:
+ *	ata_dev_select - Select device 0/1 on ATA bus
+ *	@ap: ATA channel to manipulate
+ *	@device: ATA device (numbered from zero) to select
+ *	@wait: non-zero to wait for Status register BSY bit to clear
+ *	@can_sleep: non-zero if context allows sleeping
+ *
+ *	Use the method defined in the ATA specification to
+ *	make either device 0, or device 1, active on the
+ *	ATA channel.
+ *
+ *	This is a high-level version of __ata_dev_select(),
+ *	which additionally provides the services of inserting
+ *	the proper pauses and status polling, where needed.
  *
  *	LOCKING:
- *
- *	RETURNS:
- *
+ *	caller.
  */
 
 void ata_dev_select(struct ata_port *ap, unsigned int device,
@@ -757,10 +879,14 @@
 }
 
 /**
- *	ata_dump_id -
- *	@dev:
+ *	ata_dump_id - IDENTIFY DEVICE info debugging output
+ *	@dev: Device whose IDENTIFY DEVICE page we will dump
+ *
+ *	Dump selected 16-bit words from a detected device's
+ *	IDENTIFY PAGE page.
  *
  *	LOCKING:
+ *	caller.
  */
 
 static inline void ata_dump_id(struct ata_device *dev)
@@ -843,7 +969,7 @@
 retry:
 	ata_tf_init(ap, &tf, device);
 	tf.ctl |= ATA_NIEN;
-	tf.protocol = ATA_PROT_PIO_READ;
+	tf.protocol = ATA_PROT_PIO;
 
 	if (dev->class == ATA_DEV_ATA) {
 		tf.command = ATA_CMD_ID_ATA;
@@ -1129,7 +1255,7 @@
  */
 static void ata_set_mode(struct ata_port *ap)
 {
-	unsigned int force_pio;
+	unsigned int force_pio, i;
 
 	ata_host_set_pio(ap);
 	if (ap->flags & ATA_FLAG_PORT_DISABLED)
@@ -1148,19 +1274,21 @@
 	if (force_pio) {
 		ata_dev_set_pio(ap, 0);
 		ata_dev_set_pio(ap, 1);
-
-		if (ap->flags & ATA_FLAG_PORT_DISABLED)
-			return;
 	} else {
 		ata_dev_set_udma(ap, 0);
 		ata_dev_set_udma(ap, 1);
-
-		if (ap->flags & ATA_FLAG_PORT_DISABLED)
-			return;
 	}
 
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		return;
+
 	if (ap->ops->post_set_mode)
 		ap->ops->post_set_mode(ap);
+
+	for (i = 0; i < 2; i++) {
+		struct ata_device *dev = &ap->device[i];
+		ata_dev_set_protocol(dev);
+	}
 }
 
 /**
@@ -1386,9 +1514,9 @@
 	/*
 	 * determine by signature whether we have ATA or ATAPI devices
 	 */
-	err = ata_dev_try_classify(ap, 0, dev0);
+	err = ata_dev_try_classify(ap, 0);
 	if ((slave_possible) && (err != 0x81))
-		ata_dev_try_classify(ap, 1, dev1);
+		ata_dev_try_classify(ap, 1);
 
 	/* re-enable interrupts */
 	ata_irq_on(ap);
@@ -1725,6 +1853,7 @@
 	int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
 	struct scatterlist *sg = qc->sg;
 	unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
+	dma_addr_t dma_address;
 
 	assert(sg == &qc->sgent);
 	assert(qc->n_elem == 1);
@@ -1736,12 +1865,15 @@
 	if (!have_sg)
 		return 0;
 
-	sg_dma_address(sg) = pci_map_single(ap->host_set->pdev,
-					 cmd->request_buffer,
-					 cmd->request_bufflen, dir);
+	dma_address = pci_map_single(ap->host_set->pdev, cmd->request_buffer,
+				     cmd->request_bufflen, dir);
+	if (pci_dma_mapping_error(dma_address))
+		return -1;
+
+	sg_dma_address(sg) = dma_address;
 
 	DPRINTK("mapped buffer of %d bytes for %s\n", cmd->request_bufflen,
-		qc->flags & ATA_QCFLAG_WRITE ? "write" : "read");
+		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
 
 	return 0;
 }
@@ -1842,8 +1974,7 @@
 {
 	struct ata_port *ap = qc->ap;
 
-	assert((qc->tf.protocol == ATA_PROT_PIO_READ) ||
-	       (qc->tf.protocol == ATA_PROT_PIO_WRITE));
+	assert(qc->tf.protocol == ATA_PROT_PIO);
 
 	qc->flags |= ATA_QCFLAG_POLL;
 	qc->tf.ctl |= ATA_NIEN;	/* disable interrupts */
@@ -1963,12 +2094,12 @@
 		}
 
 	DPRINTK("data %s, drv_stat 0x%X\n",
-		qc->flags & ATA_QCFLAG_WRITE ? "write" : "read",
+		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read",
 		status);
 
 	/* do the actual data transfer */
 	/* FIXME: mmio-ize */
-	if (qc->flags & ATA_QCFLAG_WRITE)
+	if (qc->tf.flags & ATA_TFLAG_WRITE)
 		outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
 	else
 		insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
@@ -2033,8 +2164,7 @@
 	qc->scsidone = scsi_finish_command;
 
 	switch (qc->tf.protocol) {
-	case ATA_PROT_DMA_READ:
-	case ATA_PROT_DMA_WRITE:
+	case ATA_PROT_DMA:
 		if (ap->flags & ATA_FLAG_MMIO) {
 			void *mmio = (void *) ap->ioaddr.bmdma_addr;
 			host_stat = readb(mmio + ATA_DMA_STATUS);
@@ -2258,7 +2388,7 @@
 void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE);
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 host_stat, dmactl;
 	void *mmio = (void *) ap->ioaddr.bmdma_addr;
 
@@ -2307,7 +2437,7 @@
 void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE);
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 host_stat, dmactl;
 
 	/* load PRD table addr. */
@@ -2402,8 +2532,7 @@
 	unsigned int handled = 0;
 
 	switch (qc->tf.protocol) {
-	case ATA_PROT_DMA_READ:
-	case ATA_PROT_DMA_WRITE:
+	case ATA_PROT_DMA:
 		if (ap->flags & ATA_FLAG_MMIO) {
 			void *mmio = (void *) ap->ioaddr.bmdma_addr;
 			host_stat = readb(mmio + ATA_DMA_STATUS);
@@ -2810,6 +2939,7 @@
 	host->unique_id = ata_unique_id++;
 	host->max_cmd_len = 12;
 	scsi_set_device(host, &ent->pdev->dev);
+	scsi_assign_lock(host, &host_set->lock);
 
 	ap->flags = ATA_FLAG_PORT_DISABLED;
 	ap->id = host->unique_id;
diff -Nru a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
--- a/drivers/scsi/libata-scsi.c	Thu Apr  8 14:58:15 2004
+++ b/drivers/scsi/libata-scsi.c	Thu Apr  8 14:58:15 2004
@@ -32,17 +32,28 @@
 
 #include "libata.h"
 
+static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
+			      struct scsi_cmnd *cmd,
+			      void (*done)(struct scsi_cmnd *));
+
 
 /**
- *	ata_std_bios_param - generic bios head/sector/cylinder calculator
- *	    used by sd. Most BIOSes nowadays expect a XXX/255/16  (CHS) 
- *	    mapping. Some situations may arise where the disk is not 
- *	    bootable if this is not used.
+ *	ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd.
+ *	@sdev: SCSI device for which BIOS geometry is to be determined
+ *	@bdev: block device associated with @sdev
+ *	@capacity: capacity of SCSI device
+ *	@geom: location to which geometry will be output
+ *
+ *	Generic bios head/sector/cylinder calculator
+ *	used by sd. Most BIOSes nowadays expect a XXX/255/16  (CHS) 
+ *	mapping. Some situations may arise where the disk is not 
+ *	bootable if this is not used.
  *
  *	LOCKING:
+ *	Defined by the SCSI layer.  We don't really care.
  *
  *	RETURNS:
- *
+ *	Zero.
  */
 int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
 		       sector_t capacity, int geom[]) 
@@ -56,6 +67,27 @@
 }
 
 
+/**
+ *	ata_scsi_qc_new - acquire new ata_queued_cmd reference
+ *	@ap: ATA port to which the new command is attached
+ *	@dev: ATA device to which the new command is attached
+ *	@cmd: SCSI command that originated this ATA command
+ *	@done: SCSI command completion function
+ *
+ *	Obtain a reference to an unused ata_queued_cmd structure,
+ *	which is the basic libata structure representing a single
+ *	ATA command sent to the hardware.
+ *
+ *	If a command was available, fill in the SCSI-specific
+ *	portions of the structure with information on the
+ *	current command.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Command allocated, or %NULL if none available.
+ */
 struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
 				       struct ata_device *dev,
 				       struct scsi_cmnd *cmd,
@@ -84,11 +116,18 @@
 }
 
 /**
- *	ata_to_sense_error -
- *	@qc:
- *	@cmd:
+ *	ata_to_sense_error - convert ATA error to SCSI error
+ *	@qc: Command that we are erroring out
+ *
+ *	Converts an ATA error into a SCSI error.
+ *
+ *	Right now, this routine is laughably primitive.  We
+ *	don't even examine what ATA told us, we just look at
+ *	the command data direction, and return a fatal SCSI
+ *	sense error based on that.
  *
  *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
  */
 
 void ata_to_sense_error(struct ata_queued_cmd *qc)
@@ -102,7 +141,7 @@
 	cmd->sense_buffer[7] = 14 - 8;	/* addnl. sense len. FIXME: correct? */
 
 	/* additional-sense-code[-qualifier] */
-	if ((qc->flags & ATA_QCFLAG_WRITE) == 0) {
+	if (cmd->sc_data_direction == SCSI_DATA_READ) {
 		cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */
 		cmd->sense_buffer[13] = 0x04;
 	} else {
@@ -112,11 +151,15 @@
 }
 
 /**
- *	ata_scsi_slave_config -
- *	@sdev:
+ *	ata_scsi_slave_config - Set SCSI device attributes
+ *	@sdev: SCSI device to examine
  *
- *	LOCKING:
+ *	This is called before we actually start reading
+ *	and writing to the device, to configure certain
+ *	SCSI mid-layer behaviors.
  *
+ *	LOCKING:
+ *	Defined by SCSI layer.  We don't really care.
  */
 
 int ata_scsi_slave_config(struct scsi_device *sdev)
@@ -155,24 +198,29 @@
 }
 
 /**
- *	ata_scsi_rw_xlat -
- *	@qc:
- *	@scsicmd:
- *	@cmd_size:
+ *	ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Converts any of six SCSI read/write commands into the
+ *	ATA counterpart, including starting sector (LBA),
+ *	sector count, and taking into account the device's LBA48
+ *	support.
+ *
+ *	Commands %READ_6, %READ_10, %READ_16, %WRITE_6, %WRITE_10, and
+ *	%WRITE_16 are currently supported.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  *
  *	RETURNS:
- *
+ *	Zero on success, non-zero on error.
  */
 
-static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd,
-				   unsigned int cmd_size)
+static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 {
 	struct ata_taskfile *tf = &qc->tf;
 	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
-	unsigned int dma = qc->flags & ATA_QCFLAG_DMA;
 
 	qc->cursect = qc->cursg = qc->cursg_ofs = 0;
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
@@ -180,43 +228,18 @@
 	tf->hob_lbal = 0;
 	tf->hob_lbam = 0;
 	tf->hob_lbah = 0;
+	tf->protocol = qc->dev->xfer_protocol;
+	tf->device |= ATA_LBA;
 
 	if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
 	    scsicmd[0] == READ_16) {
-		if (likely(dma)) {
-			if (lba48)
-				tf->command = ATA_CMD_READ_EXT;
-			else
-				tf->command = ATA_CMD_READ;
-			tf->protocol = ATA_PROT_DMA_READ;
-		} else {
-			if (lba48)
-				tf->command = ATA_CMD_PIO_READ_EXT;
-			else
-				tf->command = ATA_CMD_PIO_READ;
-			tf->protocol = ATA_PROT_PIO_READ;
-		}
-		qc->flags &= ~ATA_QCFLAG_WRITE;
-		VPRINTK("reading\n");
+		tf->command = qc->dev->read_cmd;
 	} else {
-		if (likely(dma)) {
-			if (lba48)
-				tf->command = ATA_CMD_WRITE_EXT;
-			else
-				tf->command = ATA_CMD_WRITE;
-			tf->protocol = ATA_PROT_DMA_WRITE;
-		} else {
-			if (lba48)
-				tf->command = ATA_CMD_PIO_WRITE_EXT;
-			else
-				tf->command = ATA_CMD_PIO_WRITE;
-			tf->protocol = ATA_PROT_PIO_WRITE;
-		}
-		qc->flags |= ATA_QCFLAG_WRITE;
-		VPRINTK("writing\n");
+		tf->command = qc->dev->write_cmd;
+		tf->flags |= ATA_TFLAG_WRITE;
 	}
 
-	if (cmd_size == 10) {
+	if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
 		if (lba48) {
 			tf->hob_nsect = scsicmd[7];
 			tf->hob_lbal = scsicmd[2];
@@ -234,7 +257,6 @@
 
 			qc->nsect = scsicmd[8];
 		}
-		tf->device |= ATA_LBA;
 
 		tf->nsect = scsicmd[8];
 		tf->lbal = scsicmd[5];
@@ -245,19 +267,17 @@
 		return 0;
 	}
 
-	if (cmd_size == 6) {
+	if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
 		qc->nsect = tf->nsect = scsicmd[4];
 		tf->lbal = scsicmd[3];
 		tf->lbam = scsicmd[2];
 		tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
 
-		tf->device |= ATA_LBA;
-
 		VPRINTK("six-byte command\n");
 		return 0;
 	}
 
-	if (cmd_size == 16) {
+	if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
 		/* rule out impossible LBAs and sector counts */
 		if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11])
 			return 1;
@@ -281,7 +301,6 @@
 
 			qc->nsect = scsicmd[13];
 		}
-		tf->device |= ATA_LBA;
 
 		tf->nsect = scsicmd[13];
 		tf->lbal = scsicmd[9];
@@ -297,20 +316,26 @@
 }
 
 /**
- *	ata_scsi_rw_queue -
- *	@ap:
- *	@dev:
- *	@cmd:
- *	@done:
- *	@cmd_size:
+ *	ata_scsi_translate - Translate then issue SCSI command to ATA device
+ *	@ap: ATA port to which the command is addressed
+ *	@dev: ATA device to which the command is addressed
+ *	@cmd: SCSI command to execute
+ *	@done: SCSI command completion function
+ *
+ *	Our ->queuecommand() function has decided that the SCSI
+ *	command issued can be directly translated into an ATA
+ *	command, rather than handled internally.
+ *
+ *	This function sets up an ata_queued_cmd structure for the
+ *	SCSI command, and sends that ata_queued_cmd to the hardware.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
-		      struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
-		      unsigned int cmd_size)
+static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
+			      struct scsi_cmnd *cmd,
+			      void (*done)(struct scsi_cmnd *))
 {
 	struct ata_queued_cmd *qc;
 	u8 *scsicmd = cmd->cmnd;
@@ -329,7 +354,7 @@
 
 	qc->flags |= ATA_QCFLAG_SG;	/* data is present; dma-map it */
 
-	if (ata_scsi_rw_xlat(qc, scsicmd, cmd_size))
+	if (ata_scsi_rw_xlat(qc, scsicmd))
 		goto err_out;
 
 	/* select device, send command to hardware */
@@ -353,7 +378,6 @@
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
- *	FIXME: kmap inside spin_lock_irqsave ok?
  *
  *	RETURNS:
  *	Length of response buffer.
@@ -368,7 +392,7 @@
 		struct scatterlist *sg;
 
 		sg = (struct scatterlist *) cmd->request_buffer;
-		buf = kmap(sg->page) + sg->offset;
+		buf = kmap_atomic(sg->page, KM_USER0) + sg->offset;
 		buflen = sg->length;
 	} else {
 		buf = cmd->request_buffer;
@@ -396,7 +420,7 @@
 		struct scatterlist *sg;
 
 		sg = (struct scatterlist *) cmd->request_buffer;
-		kunmap(sg->page);
+		kunmap_atomic(sg->page, KM_USER0);
 	}
 }
 
@@ -596,30 +620,6 @@
 }
 
 /**
- *	ata_scsiop_sync_cache - Simulate SYNCHRONIZE CACHE command
- *	@args: Port / device / SCSI command of interest.
- *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *	@buflen: Response buffer length.
- *
- *	Initiates flush of device's cache.
- *
- *	TODO:
- *	Actually do this :)
- *
- *	LOCKING:
- *	spin_lock_irqsave(host_set lock)
- */
-
-unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf,
-				  unsigned int buflen)
-{
-	VPRINTK("ENTER\n");
-
-	/* FIXME */
-	return 1;
-}
-
-/**
  *	ata_msense_push - Push data onto MODE SENSE data output buffer
  *	@ptr_io: (input/output) Location to store more output data
  *	@last: End of output data buffer
@@ -649,9 +649,9 @@
 
 /**
  *	ata_msense_caching - Simulate MODE SENSE caching info page
- *	@dev:
- *	@ptr_io:
- *	@last:
+ *	@dev: Device associated with this MODE SENSE command
+ *	@ptr_io: (input/output) Location to store more output data
+ *	@last: End of output data buffer
  *
  *	Generate a caching info page, which conditionally indicates
  *	write caching to the SCSI layer, depending on device
@@ -674,9 +674,9 @@
 
 /**
  *	ata_msense_ctl_mode - Simulate MODE SENSE control mode page
- *	@dev:
- *	@ptr_io:
- *	@last:
+ *	@dev: Device associated with this MODE SENSE command
+ *	@ptr_io: (input/output) Location to store more output data
+ *	@last: End of output data buffer
  *
  *	Generate a generic MODE SENSE control mode page.
  *
@@ -834,11 +834,15 @@
 }
 
 /**
- *	ata_scsi_badcmd -
- *	@cmd:
- *	@done:
- *	@asc:
- *	@ascq:
+ *	ata_scsi_badcmd - End a SCSI request with an error
+ *	@cmd: SCSI request to be handled
+ *	@done: SCSI command completion function
+ *	@asc: SCSI-defined additional sense code
+ *	@ascq: SCSI-defined additional sense code qualifier
+ *
+ *	Helper function that completes a SCSI command with
+ *	%SAM_STAT_CHECK_CONDITION, with a sense key %ILLEGAL_REQUEST
+ *	and the specified additional sense codes.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
@@ -912,7 +916,7 @@
 
 	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
-		qc->flags |= ATA_QCFLAG_WRITE;
+		qc->tf.flags |= ATA_TFLAG_WRITE;
 		DPRINTK("direction: write\n");
 	}
 
@@ -967,6 +971,99 @@
 }
 
 /**
+ *	ata_scsi_find_dev - lookup ata_device from scsi_cmnd
+ *	@ap: ATA port to which the device is attached
+ *	@cmd: SCSI command to be sent to the device
+ *
+ *	Given various information provided in struct scsi_cmnd,
+ *	map that onto an ATA bus, and using that mapping
+ *	determine which ata_device is associated with the
+ *	SCSI command to be sent.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Associated ATA device, or %NULL if not found.
+ */
+
+static inline struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd)
+{
+	struct ata_device *dev;
+
+	/* skip commands not addressed to targets we simulate */
+	if (likely(cmd->device->id < ATA_MAX_DEVICES))
+		dev = &ap->device[cmd->device->id];
+	else
+		return NULL;
+
+	if (unlikely((cmd->device->channel != 0) ||
+		     (cmd->device->lun != 0)))
+		return NULL;
+
+	if (unlikely(!ata_dev_present(dev)))
+		return NULL;
+
+#ifndef ATA_ENABLE_ATAPI
+	if (unlikely(dev->class == ATA_DEV_ATAPI))
+		return NULL;
+#endif
+
+	return dev;
+}
+
+/**
+ *	ata_scsi_xlat_possible - check if SCSI to ATA translation is possible
+ *	@cmd: SCSI command opcode to consider
+ *
+ *	Look up the SCSI command given, and determine whether the
+ *	SCSI command is to be translated or simulated.
+ *
+ *	RETURNS:
+ *	Non-zero if possible, zero if not.
+ */
+
+static inline int ata_scsi_xlat_possible(u8 cmd)
+{
+	switch (cmd) {
+	case READ_6:
+	case READ_10:
+	case READ_16:
+
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_16:
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ *	ata_scsi_dump_cdb - dump SCSI command contents to dmesg
+ *	@ap: ATA port to which the command was being sent
+ *	@cmd: SCSI command to dump
+ *
+ *	Prints the contents of a SCSI command via printk().
+ */
+
+static inline void ata_scsi_dump_cdb(struct ata_port *ap,
+				     struct scsi_cmnd *cmd)
+{
+#ifdef ATA_DEBUG
+	u8 *scsicmd = cmd->cmnd;
+
+	DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		ap->id,
+		cmd->device->channel, cmd->device->id, cmd->device->lun,
+		scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
+		scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
+		scsicmd[8]);
+#endif
+}
+
+/**
  *	ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device
  *	@cmd: SCSI command to be sent
  *	@done: Completion function, called when command is complete
@@ -987,83 +1084,52 @@
 
 int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
-	u8 *scsicmd = cmd->cmnd;
 	struct ata_port *ap;
 	struct ata_device *dev;
-	struct ata_scsi_args args;
-	const unsigned int atapi_support =
-#ifdef ATA_ENABLE_ATAPI
-					   1;
-#else
-					   0;
-#endif
-
-	/* Note: spin_lock_irqsave is held by caller... */
-	spin_unlock(cmd->device->host->host_lock);
 
 	ap = (struct ata_port *) &cmd->device->host->hostdata[0];
 
-	DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		ap->id,
-		cmd->device->channel, cmd->device->id, cmd->device->lun,
-		scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
-		scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
-		scsicmd[8]);
+	ata_scsi_dump_cdb(ap, cmd);
 
-	/* skip commands not addressed to targets we care about */
-	if ((cmd->device->channel != 0) || (cmd->device->lun != 0) ||
-	    (cmd->device->id >= ATA_MAX_DEVICES)) {
-		cmd->result = (DID_BAD_TARGET << 16); /* FIXME: correct? */
-		done(cmd);
-		goto out;
-	}
-
-	spin_lock(&ap->host_set->lock);
-
-	dev = &ap->device[cmd->device->id];
-
-	if (!ata_dev_present(dev)) {
-		DPRINTK("no device\n");
-		cmd->result = (DID_BAD_TARGET << 16); /* FIXME: correct? */
+	dev = ata_scsi_find_dev(ap, cmd);
+	if (unlikely(!dev)) {
+		cmd->result = (DID_BAD_TARGET << 16);
 		done(cmd);
 		goto out_unlock;
 	}
 
-	if (dev->class == ATA_DEV_ATAPI) {
-		if (atapi_support)
-			atapi_scsi_queuecmd(ap, dev, cmd, done);
-		else {
-			cmd->result = (DID_BAD_TARGET << 16); /* correct? */
-			done(cmd);
-		}
-		goto out_unlock;
-	}
+	if (dev->class == ATA_DEV_ATA) {
+		if (ata_scsi_xlat_possible(cmd->cmnd[0]))
+			ata_scsi_translate(ap, dev, cmd, done);
+		else
+			ata_scsi_simulate(ap, dev, cmd, done);
+	} else
+		atapi_scsi_queuecmd(ap, dev, cmd, done);
 
-	/* fast path */
-	switch(scsicmd[0]) {
-		case READ_6:
-		case WRITE_6:
-			ata_scsi_rw_queue(ap, dev, cmd, done, 6);
-			goto out_unlock;
-
-		case READ_10:
-		case WRITE_10:
-			ata_scsi_rw_queue(ap, dev, cmd, done, 10);
-			goto out_unlock;
-
-		case READ_16:
-		case WRITE_16:
-			ata_scsi_rw_queue(ap, dev, cmd, done, 16);
-			goto out_unlock;
+out_unlock:
+	return 0;
+}
 
-		default:
-			/* do nothing */
-			break;
-	}
+/**
+ *	ata_scsi_simulate - simulate SCSI command on ATA device
+ *	@ap: Port to which ATA device is attached.
+ *	@dev: Target device for CDB.
+ *	@cmd: SCSI command being sent to device.
+ *	@done: SCSI command completion function.
+ *
+ *	Interprets and directly executes a select list of SCSI commands
+ *	that can be handled internally.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
 
-	/*
-	 * slow path
-	 */
+static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
+			      struct scsi_cmnd *cmd,
+			      void (*done)(struct scsi_cmnd *))
+{
+	struct ata_scsi_args args;
+	u8 *scsicmd = cmd->cmnd;
 
 	args.ap = ap;
 	args.dev = dev;
@@ -1102,13 +1168,6 @@
 			ata_bad_cdb(cmd, done);
 			break;
 
-		case SYNCHRONIZE_CACHE:
-			if ((dev->flags & ATA_DFLAG_WCACHE) == 0)
-				ata_bad_scsiop(cmd, done);
-			else
-				ata_scsi_rbuf_fill(&args, ata_scsiop_sync_cache);
-			break;
-
 		case READ_CAPACITY:
 			ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
 			break;
@@ -1132,11 +1191,5 @@
 			ata_bad_scsiop(cmd, done);
 			break;
 	}
-
-out_unlock:
-	spin_unlock(&ap->host_set->lock);
-out:
-	spin_lock(cmd->device->host->host_lock);
-	return 0;
 }
 
diff -Nru a/drivers/scsi/libata.h b/drivers/scsi/libata.h
--- a/drivers/scsi/libata.h	Thu Apr  8 14:58:15 2004
+++ b/drivers/scsi/libata.h	Thu Apr  8 14:58:15 2004
@@ -37,8 +37,8 @@
 
 
 /* libata-core.c */
-extern unsigned int ata_dev_id_string(struct ata_device *dev, unsigned char *s,
-                               unsigned int ofs, unsigned int len);
+extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
+			      unsigned int ofs, unsigned int len);
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
 extern int ata_qc_issue(struct ata_queued_cmd *qc);
@@ -50,9 +50,6 @@
 
 /* libata-scsi.c */
 extern void ata_to_sense_error(struct ata_queued_cmd *qc);
-extern void ata_scsi_rw_queue(struct ata_port *ap, struct ata_device *dev,
-		      struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
-		      unsigned int cmd_size);
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 			       unsigned int buflen);
diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c	Thu Apr  8 14:58:15 2004
+++ b/drivers/scsi/sata_promise.c	Thu Apr  8 14:58:15 2004
@@ -28,13 +28,14 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include "scsi.h"
 #include "hosts.h"
 #include <linux/libata.h>
 #include <asm/io.h>
 
 #define DRV_NAME	"sata_promise"
-#define DRV_VERSION	"0.91"
+#define DRV_VERSION	"0.92"
 
 
 enum {
@@ -45,10 +46,13 @@
 	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */
 	PDC_TBG_MODE		= 0x41,	/* TBG mode */
 	PDC_FLASH_CTL		= 0x44, /* Flash control register */
-	PDC_CTLSTAT		= 0x60,	/* IDE control and status register */
+	PDC_PCI_CTL		= 0x48, /* PCI control and status register */
+	PDC_GLOBAL_CTL		= 0x48, /* Global control/status (per port) */
+	PDC_CTLSTAT		= 0x60,	/* IDE control and status (per port) */
 	PDC_SATA_PLUG_CSR	= 0x6C, /* SATA Plug control/status reg */
 	PDC_SLEW_CTL		= 0x470, /* slew rate control reg */
 	PDC_HDMA_CTLSTAT	= 0x12C, /* Host DMA control / status */
+
 	PDC_20621_SEQCTL	= 0x400,
 	PDC_20621_SEQMASK	= 0x480,
 	PDC_20621_GENERAL_CTL	= 0x484,
@@ -73,12 +77,19 @@
 
 	PDC_CHIP0_OFS		= 0xC0000, /* offset of chip #0 */
 
+	PDC_20621_ERR_MASK	= (1<<19) | (1<<20) | (1<<21) | (1<<22) |
+				  (1<<23),
+	PDC_ERR_MASK		= (1<<19) | (1<<20) | (1<<21) | (1<<22) |
+				  (1<<8) | (1<<9) | (1<<10),
+
 	board_2037x		= 0,	/* FastTrak S150 TX2plus */
 	board_20319		= 1,	/* FastTrak S150 TX4 */
 	board_20621		= 2,	/* FastTrak S150 SX4 */
 
+	PDC_HAS_PATA		= (1 << 1), /* PDC20375 has PATA */
+
 	PDC_FLAG_20621		= (1 << 30), /* we have a 20621 */
-	PDC_HDMA_RESET		= (1 << 11), /* HDMA reset */
+	PDC_RESET		= (1 << 11), /* HDMA reset */
 
 	PDC_MAX_HDMA		= 32,
 	PDC_HDMA_Q_MASK		= (PDC_MAX_HDMA - 1),
@@ -154,13 +165,14 @@
 static void pdc_20621_phy_reset (struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
+static void pdc_phy_reset(struct ata_port *ap);
 static void pdc_fill_sg(struct ata_queued_cmd *qc);
 static void pdc20621_fill_sg(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc20621_host_stop(struct ata_host_set *host_set);
 static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc);
+                                     struct ata_queued_cmd *qc, int have_err);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
 static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, 
@@ -199,7 +211,7 @@
 	.tf_read		= ata_tf_read_mmio,
 	.check_status		= ata_check_status_mmio,
 	.exec_command		= pdc_exec_command_mmio,
-	.phy_reset		= sata_phy_reset,
+	.phy_reset		= pdc_phy_reset,
 	.bmdma_start            = pdc_dma_start,
 	.fill_sg		= pdc_fill_sg,
 	.eng_timeout		= pdc_eng_timeout,
@@ -351,6 +363,34 @@
         ata_bus_reset(ap);
 }
 
+static void pdc_reset_port(struct ata_port *ap)
+{
+	void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
+	unsigned int i;
+	u32 tmp;
+
+	for (i = 11; i > 0; i--) {
+		tmp = readl(mmio);
+		if (tmp & PDC_RESET)
+			break;
+
+		udelay(100);
+
+		tmp |= PDC_RESET;
+		writel(tmp, mmio);
+	}
+
+	tmp &= ~PDC_RESET;
+	writel(tmp, mmio);
+	readl(mmio);	/* flush */
+}
+
+static void pdc_phy_reset(struct ata_port *ap)
+{
+	pdc_reset_port(ap);
+	sata_phy_reset(ap);
+}
+
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
 	if (sc_reg > SCR_CONTROL)
@@ -390,12 +430,11 @@
 	 * and seq id (byte 2)
 	 */
 	switch (tf->protocol) {
-	case ATA_PROT_DMA_READ:
-		buf32[0] = cpu_to_le32(PDC_PKT_READ);
-		break;
-
-	case ATA_PROT_DMA_WRITE:
-		buf32[0] = 0;
+	case ATA_PROT_DMA:
+		if (!(tf->flags & ATA_TFLAG_WRITE))
+			buf32[0] = cpu_to_le32(PDC_PKT_READ);
+		else
+			buf32[0] = 0;
 		break;
 
 	case ATA_PROT_NODATA:
@@ -554,7 +593,7 @@
 	/*
 	 * Set up ATA packet
 	 */
-	if (tf->protocol == ATA_PROT_DMA_READ)
+	if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
 		buf[i++] = PDC_PKT_READ;
 	else if (tf->protocol == ATA_PROT_NODATA)
 		buf[i++] = PDC_PKT_NODATA;
@@ -606,7 +645,7 @@
 	/*
 	 * Set up Host DMA packet
 	 */
-	if (tf->protocol == ATA_PROT_DMA_READ)
+	if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
 		tmp = PDC_PKT_READ;
 	else
 		tmp = 0;
@@ -768,7 +807,7 @@
 	struct ata_host_set *host_set = ap->host_set;
 	unsigned int port_no = ap->port_no;
 	void *mmio = host_set->mmio_base;
-	unsigned int rw = (qc->flags & ATA_QCFLAG_WRITE);
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 seq = (u8) (port_no + 1);
 	unsigned int doing_hdma = 0, port_ofs;
 
@@ -821,13 +860,14 @@
 
 	VPRINTK("ENTER\n");
 
-	switch (qc->tf.protocol) {
-	case ATA_PROT_DMA_READ:
+	if ((qc->tf.protocol == ATA_PROT_DMA) &&	/* read */
+	    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+
 		/* step two - DMA from DIMM to host */
 		if (doing_hdma) {
 			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-			pdc_dma_complete(ap, qc);
+			pdc_dma_complete(ap, qc, 0);
 			pdc20621_pop_hdma(qc);
 		}
 
@@ -843,9 +883,9 @@
 					   port_ofs + PDC_DIMM_HOST_PKT);
 		}
 		handled = 1;
-		break;
 
-	case ATA_PROT_DMA_WRITE:
+	} else if (qc->tf.protocol == ATA_PROT_DMA) {	/* write */
+
 		/* step one - DMA from host to DIMM */
 		if (doing_hdma) {
 			u8 seq = (u8) (port_no + 1);
@@ -864,25 +904,24 @@
 		else {
 			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-			pdc_dma_complete(ap, qc);
+			pdc_dma_complete(ap, qc, 0);
 			pdc20621_pop_hdma(qc);
 		}
 		handled = 1;
-		break;
 
-	case ATA_PROT_NODATA:   /* command completion, but no data xfer */
+	/* command completion, but no data xfer */
+	} else if (qc->tf.protocol == ATA_PROT_NODATA) {
+
 		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
 		ata_qc_complete(qc, status, 0);
 		handled = 1;
-		break;
 
-        default:
-                ap->stats.idle_irq++;
-                break;
-        }
+	} else {
+		ap->stats.idle_irq++;
+	}
 
-        return handled;
+	return handled;
 }
 
 static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
@@ -918,7 +957,7 @@
 		return IRQ_NONE;
 	}
 
-        spin_lock_irq(&host_set->lock);
+        spin_lock(&host_set->lock);
 
         for (i = 1; i < 9; i++) {
 		port_no = i - 1;
@@ -940,7 +979,7 @@
 		}
 	}
 
-        spin_unlock_irq(&host_set->lock);
+        spin_unlock(&host_set->lock);
 
 	VPRINTK("mask == 0x%x\n", mask);
 
@@ -969,11 +1008,14 @@
 }
 
 static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc)
+                                     struct ata_queued_cmd *qc,
+				     int have_err)
 {
+	u8 err_bit = have_err ? ATA_ERR : 0;
+
 	/* get drive status; clear intr; complete txn */
 	ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag),
-			ata_wait_idle(ap), 0);
+			ata_wait_idle(ap) | err_bit, 0);
 }
 
 static void pdc_eng_timeout(struct ata_port *ap)
@@ -999,8 +1041,7 @@
 	qc->scsidone = scsi_finish_command;
 
 	switch (qc->tf.protocol) {
-	case ATA_PROT_DMA_READ:
-	case ATA_PROT_DMA_WRITE:
+	case ATA_PROT_DMA:
 		printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
 		ata_qc_complete(ata_qc_from_tag(ap, ap->active_tag),
 			        ata_wait_idle(ap) | ATA_ERR, 0);
@@ -1033,18 +1074,27 @@
                                           struct ata_queued_cmd *qc)
 {
 	u8 status;
-	unsigned int handled = 0;
+	unsigned int handled = 0, have_err = 0;
+	u32 tmp;
+	void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
+
+	tmp = readl(mmio);
+	if (tmp & PDC_ERR_MASK) {
+		have_err = 1;
+		pdc_reset_port(ap);
+	}
 
 	switch (qc->tf.protocol) {
-	case ATA_PROT_DMA_READ:
-	case ATA_PROT_DMA_WRITE:
-		pdc_dma_complete(ap, qc);
+	case ATA_PROT_DMA:
+		pdc_dma_complete(ap, qc, have_err);
 		handled = 1;
 		break;
 
 	case ATA_PROT_NODATA:   /* command completion, but no data xfer */
 		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+		if (have_err)
+			status |= ATA_ERR;
 		ata_qc_complete(qc, status, 0);
 		handled = 1;
 		break;
@@ -1088,7 +1138,7 @@
 		return IRQ_NONE;
 	}
 
-        spin_lock_irq(&host_set->lock);
+        spin_lock(&host_set->lock);
 
         for (i = 0; i < host_set->n_ports; i++) {
 		VPRINTK("port %u\n", i);
@@ -1103,7 +1153,7 @@
 		}
 	}
 
-        spin_unlock_irq(&host_set->lock);
+        spin_unlock(&host_set->lock);
 
 	VPRINTK("EXIT\n");
 
@@ -1130,16 +1180,14 @@
 
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if ((tf->protocol != ATA_PROT_DMA_READ) &&
-	    (tf->protocol != ATA_PROT_DMA_WRITE))
+	if (tf->protocol != ATA_PROT_DMA)
 		ata_tf_load_mmio(ap, tf);
 }
 
 
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if ((tf->protocol != ATA_PROT_DMA_READ) &&
-	    (tf->protocol != ATA_PROT_DMA_WRITE))
+	if (tf->protocol != ATA_PROT_DMA)
 		ata_exec_command_mmio(ap, tf);
 }
 
@@ -1592,14 +1640,14 @@
 	 * Reset Host DMA
 	 */
 	tmp = readl(mmio + PDC_HDMA_CTLSTAT);
-	tmp |= PDC_HDMA_RESET;
+	tmp |= PDC_RESET;
 	writel(tmp, mmio + PDC_HDMA_CTLSTAT);
 	readl(mmio + PDC_HDMA_CTLSTAT);		/* flush */
 
 	udelay(10);
 
 	tmp = readl(mmio + PDC_HDMA_CTLSTAT);
-	tmp &= ~PDC_HDMA_RESET;
+	tmp &= ~PDC_RESET;
 	writel(tmp, mmio + PDC_HDMA_CTLSTAT);
 	readl(mmio + PDC_HDMA_CTLSTAT);		/* flush */
 }
@@ -1610,14 +1658,18 @@
 	u32 tmp;
 
 	if (chip_id == board_20621)
-		return;
+		BUG();
 
-	/* change FIFO_SHD to 8 dwords. Promise driver does this...
-	 * dunno why.
+	/*
+	 * Except for the hotplug stuff, this is voodoo from the
+	 * Promise driver.  Label this entire section
+	 * "TODO: figure out why we do this"
 	 */
+
+	/* change FIFO_SHD to 8 dwords, enable BMR_BURST */
 	tmp = readl(mmio + PDC_FLASH_CTL);
-	if ((tmp & (1 << 16)) == 0)
-		writel(tmp | (1 << 16), mmio + PDC_FLASH_CTL);
+	tmp |= 0x12000;	/* bit 16 (fifo 8 dw) and 13 (bmr burst?) */
+	writel(tmp, mmio + PDC_FLASH_CTL);
 
 	/* clear plug/unplug flags for all ports */
 	tmp = readl(mmio + PDC_SATA_PLUG_CSR);
@@ -1627,13 +1679,17 @@
 	tmp = readl(mmio + PDC_SATA_PLUG_CSR);
 	writel(tmp | 0xff0000, mmio + PDC_SATA_PLUG_CSR);
 
-	/* reduce TBG clock to 133 Mhz. FIXME: why? */
+	/* reduce TBG clock to 133 Mhz. */
 	tmp = readl(mmio + PDC_TBG_MODE);
 	tmp &= ~0x30000; /* clear bit 17, 16*/
 	tmp |= 0x10000;  /* set bit 17:16 = 0:1 */
 	writel(tmp, mmio + PDC_TBG_MODE);
 
-	/* adjust slew rate control register. FIXME: why? */
+	readl(mmio + PDC_TBG_MODE);	/* flush */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(msecs_to_jiffies(10));
+
+	/* adjust slew rate control register. */
 	tmp = readl(mmio + PDC_SLEW_CTL);
 	tmp &= 0xFFFFF03F; /* clear bit 11 ~ 6 */
 	tmp  |= 0x00000900; /* set bit 11-9 = 100b , bit 8-6 = 100 */
diff -Nru a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/scsi/sata_sis.c	Thu Apr  8 14:58:15 2004
@@ -0,0 +1,214 @@
+/*
+ *  sata_sis.c - Silicon Integrated Systems SATA
+ *
+ *  Copyright 2004 Uwe Koziolek
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "scsi.h"
+#include "hosts.h"
+#include <linux/libata.h>
+
+#define DRV_NAME	"sata_sis"
+#define DRV_VERSION	"0.04"
+
+enum {
+	sis_180			= 0,
+};
+
+static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+
+static struct pci_device_id sis_pci_tbl[] = {
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
+	{ }	/* terminate list */
+};
+
+
+static struct pci_driver sis_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= sis_pci_tbl,
+	.probe			= sis_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+static Scsi_Host_Template sis_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= ATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.dma_boundary		= ATA_DMA_BOUNDARY,
+	.slave_configure	= ata_scsi_slave_config,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations sis_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load_pio,
+	.tf_read		= ata_tf_read_pio,
+	.check_status		= ata_check_status_pio,
+	.exec_command		= ata_exec_command_pio,
+	.phy_reset		= sata_phy_reset,
+	.bmdma_start            = ata_bmdma_start_pio,
+	.fill_sg		= ata_fill_sg,
+	.eng_timeout		= ata_eng_timeout,
+	.irq_handler		= ata_interrupt,
+	.scr_read		= sis_scr_read,
+	.scr_write		= sis_scr_write,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+};
+
+
+MODULE_AUTHOR("Uwe Koziolek");
+MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
+
+
+static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	if (sc_reg >= 16)
+		return 0xffffffffU;
+
+	return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+	if (sc_reg >= 16)
+		return;
+	outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+/* move to PCI layer, integrate w/ MSI stuff */
+static void pci_enable_intx(struct pci_dev *pdev)
+{
+	u16 pci_command;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+	if (pci_command & PCI_COMMAND_INTX_DISABLE) {
+		pci_command &= ~PCI_COMMAND_INTX_DISABLE;
+		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+	}
+}
+
+static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct ata_probe_ent *probe_ent = NULL;
+	int rc;
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (!probe_ent) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent->pdev = pdev;
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	probe_ent->sht = &sis_sht;
+	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
+				ATA_FLAG_NO_LEGACY;
+	probe_ent->pio_mask = 0x03;
+	probe_ent->udma_mask = 0x7f;
+	probe_ent->port_ops = &sis_ops;
+
+	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+	ata_std_ports(&probe_ent->port[0]);
+	probe_ent->port[0].ctl_addr =
+		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+	probe_ent->port[0].scr_addr = pci_resource_start(pdev, 5);
+
+	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+	ata_std_ports(&probe_ent->port[1]);
+	probe_ent->port[1].ctl_addr =
+		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+	probe_ent->port[1].scr_addr = pci_resource_start(pdev, 5) + 64;
+
+	probe_ent->n_ports = 2;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+
+	pci_set_master(pdev);
+	pci_enable_intx(pdev);
+
+	/* FIXME: check ata_device_add return value */
+	ata_device_add(probe_ent);
+	kfree(probe_ent);
+
+	return 0;
+
+err_out_regions:
+	pci_release_regions(pdev);
+
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+
+}
+
+static int __init sis_init(void)
+{
+	return pci_module_init(&sis_pci_driver);
+}
+
+static void __exit sis_exit(void)
+{
+	pci_unregister_driver(&sis_pci_driver);
+}
+
+
+module_init(sis_init);
+module_exit(sis_exit);
diff -Nru a/include/linux/ata.h b/include/linux/ata.h
--- a/include/linux/ata.h	Thu Apr  8 14:58:15 2004
+++ b/include/linux/ata.h	Thu Apr  8 14:58:15 2004
@@ -102,16 +102,6 @@
 	ATA_REG_DEVSEL		= ATA_REG_DEVICE,
 	ATA_REG_IRQ		= ATA_REG_NSECT,
 
-	/* ATA taskfile protocols */
-	ATA_PROT_UNKNOWN	= 0,
-	ATA_PROT_NODATA		= 1,
-	ATA_PROT_PIO_READ	= 2,
-	ATA_PROT_PIO_WRITE	= 3,
-	ATA_PROT_DMA_READ	= 4,
-	ATA_PROT_DMA_WRITE	= 5,
-	ATA_PROT_ATAPI		= 6,
-	ATA_PROT_ATAPI_DMA	= 7,
-
 	/* ATA device commands */
 	ATA_CMD_EDD		= 0x90,	/* execute device diagnostic */
 	ATA_CMD_ID_ATA		= 0xEC,
@@ -156,13 +146,54 @@
 	SCR_CONTROL		= 2,
 	SCR_ACTIVE		= 3,
 	SCR_NOTIFICATION	= 4,
+
+	/* struct ata_taskfile flags */
+	ATA_TFLAG_LBA48		= (1 << 0), /* enable 48-bit LBA and "HOB" */
+	ATA_TFLAG_ISADDR	= (1 << 1), /* enable r/w to nsect/lba regs */
+	ATA_TFLAG_DEVICE	= (1 << 2), /* enable r/w to device reg */
+	ATA_TFLAG_WRITE		= (1 << 3), /* data dir: host->dev==1 (write) */
+};
+
+enum ata_tf_protocols {
+	/* ATA taskfile protocols */
+	ATA_PROT_UNKNOWN,	/* unknown/invalid */
+	ATA_PROT_NODATA,	/* no data */
+	ATA_PROT_PIO,		/* PIO single sector */
+	ATA_PROT_PIO_MULT,	/* PIO multiple sector */
+	ATA_PROT_DMA,		/* DMA */
+	ATA_PROT_ATAPI,		/* packet command */
+	ATA_PROT_ATAPI_DMA,	/* packet command with special DMA sauce */
 };
 
 /* core structures */
+
 struct ata_prd {
 	u32			addr;
 	u32			flags_len;
 } __attribute__((packed));
+
+struct ata_taskfile {
+	unsigned long		flags;		/* ATA_TFLAG_xxx */
+	u8			protocol;	/* ATA_PROT_xxx */
+
+	u8			ctl;		/* control reg */
+
+	u8			hob_feature;	/* additional data */
+	u8			hob_nsect;	/* to support LBA48 */
+	u8			hob_lbal;
+	u8			hob_lbam;
+	u8			hob_lbah;
+
+	u8			feature;
+	u8			nsect;
+	u8			lbal;
+	u8			lbam;
+	u8			lbah;
+
+	u8			device;
+
+	u8			command;	/* IO operation */
+};
 
 #define ata_id_is_ata(dev)	(((dev)->id[0] & (1 << 15)) == 0)
 #define ata_id_has_lba48(dev)	((dev)->id[83] & (1 << 10))
diff -Nru a/include/linux/libata.h b/include/linux/libata.h
--- a/include/linux/libata.h	Thu Apr  8 14:58:15 2004
+++ b/include/linux/libata.h	Thu Apr  8 14:58:15 2004
@@ -107,12 +107,6 @@
 	ATA_FLAG_MMIO		= (1 << 6), /* use MMIO, not PIO */
 	ATA_FLAG_SATA_RESET	= (1 << 7), /* use COMRESET */
 
-	/* struct ata_taskfile flags */
-	ATA_TFLAG_LBA48		= (1 << 0),
-	ATA_TFLAG_ISADDR	= (1 << 1), /* enable r/w to nsect/lba regs */
-	ATA_TFLAG_DEVICE	= (1 << 2), /* enable r/w to device reg */
-
-	ATA_QCFLAG_WRITE	= (1 << 0), /* read==0, write==1 */
 	ATA_QCFLAG_ACTIVE	= (1 << 1), /* cmd not yet ack'd to scsi lyer */
 	ATA_QCFLAG_DMA		= (1 << 2), /* data delivered via DMA */
 	ATA_QCFLAG_ATAPI	= (1 << 3), /* is ATAPI packet command? */
@@ -223,29 +217,6 @@
 	struct ata_port *	ports[0];
 };
 
-struct ata_taskfile {
-	unsigned long		flags;		/* ATA_TFLAG_xxx */
-	u8			protocol;	/* ATA_PROT_xxx */
-
-	u8			ctl;		/* control reg */
-
-	u8			hob_feature;	/* additional data */
-	u8			hob_nsect;	/* to support LBA48 */
-	u8			hob_lbal;
-	u8			hob_lbam;
-	u8			hob_lbah;
-
-	u8			feature;
-	u8			nsect;
-	u8			lbal;
-	u8			lbam;
-	u8			lbah;
-
-	u8			device;
-
-	u8			command;	/* IO operation */
-};
-
 struct ata_queued_cmd {
 	struct ata_port		*ap;
 	struct ata_device	*dev;
@@ -293,6 +264,11 @@
 						 * ATAPI7 spec size, 40 ASCII
 						 * characters
 						 */
+
+	/* cache info about current transfer mode */
+	u8			xfer_protocol;	/* taskfile xfer protocol */
+	u8			read_cmd;	/* opcode to use on read */
+	u8			write_cmd;	/* opcode to use on write */
 };
 
 struct ata_engine {
@@ -408,7 +384,6 @@
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern int ata_scsi_release(struct Scsi_Host *host);
-extern int ata_scsi_slave_config(struct scsi_device *sdev);
 extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
 /*
  * Default driver ops implementations
@@ -433,6 +408,7 @@
 extern int ata_std_bios_param(struct scsi_device *sdev,
 			      struct block_device *bdev,
 			      sector_t capacity, int geom[]);
+extern int ata_scsi_slave_config(struct scsi_device *sdev);
 
 
 static inline unsigned long msecs_to_jiffies(unsigned long msecs)
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Thu Apr  8 14:58:15 2004
+++ b/include/linux/pci_ids.h	Thu Apr  8 14:58:15 2004
@@ -572,6 +572,7 @@
 #define PCI_DEVICE_ID_SI_503		0x0008
 #define PCI_DEVICE_ID_SI_ACPI		0x0009
 #define PCI_DEVICE_ID_SI_LPC		0x0018
+#define PCI_DEVICE_ID_SI_180		0x0180
 #define PCI_DEVICE_ID_SI_5597_VGA	0x0200
 #define PCI_DEVICE_ID_SI_6205		0x0205
 #define PCI_DEVICE_ID_SI_501		0x0406