summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/chipsets/ata-serverworks.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ata/chipsets/ata-serverworks.c')
-rw-r--r--sys/dev/ata/chipsets/ata-serverworks.c99
1 files changed, 52 insertions, 47 deletions
diff --git a/sys/dev/ata/chipsets/ata-serverworks.c b/sys/dev/ata/chipsets/ata-serverworks.c
index 886282e..b5a3fc2 100644
--- a/sys/dev/ata/chipsets/ata-serverworks.c
+++ b/sys/dev/ata/chipsets/ata-serverworks.c
@@ -60,7 +60,7 @@ static int ata_serverworks_ch_attach(device_t dev);
static int ata_serverworks_ch_detach(device_t dev);
static void ata_serverworks_tf_read(struct ata_request *request);
static void ata_serverworks_tf_write(struct ata_request *request);
-static void ata_serverworks_setmode(device_t dev, int mode);
+static int ata_serverworks_setmode(device_t dev, int target, int mode);
#ifdef __powerpc__
static int ata_serverworks_status(device_t dev);
#endif
@@ -147,6 +147,7 @@ ata_serverworks_chipinit(device_t dev)
ctlr->ch_attach = ata_serverworks_ch_attach;
ctlr->ch_detach = ata_serverworks_ch_detach;
ctlr->setmode = ata_sata_setmode;
+ ctlr->getrev = ata_sata_getrev;
return 0;
}
else if (ctlr->chip->cfg1 == SWKS_33) {
@@ -213,6 +214,7 @@ ata_serverworks_ch_attach(device_t dev)
ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x48;
ch->flags |= ATA_NO_SLAVE;
+ ch->flags |= ATA_SATA;
ata_pci_hw(dev);
ch->hw.tf_read = ata_serverworks_tf_read;
ch->hw.tf_write = ata_serverworks_tf_write;
@@ -287,7 +289,9 @@ static void
ata_serverworks_tf_write(struct ata_request *request)
{
struct ata_channel *ch = device_get_softc(request->parent);
+#ifndef ATA_CAM
struct ata_device *atadev = device_get_softc(request->dev);
+#endif
if (request->flags & ATA_R_48BIT) {
ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
@@ -303,6 +307,7 @@ ata_serverworks_tf_write(struct ata_request *request)
else {
ATA_IDX_OUTW(ch, ATA_FEATURE, request->u.ata.feature);
ATA_IDX_OUTW(ch, ATA_COUNT, request->u.ata.count);
+#ifndef ATA_CAM
if (atadev->flags & ATA_D_USE_CHS) {
int heads, sectors;
@@ -324,74 +329,74 @@ ata_serverworks_tf_write(struct ata_request *request)
sectors) & 0xf));
}
else {
+#endif
ATA_IDX_OUTW(ch, ATA_SECTOR, request->u.ata.lba);
ATA_IDX_OUTW(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
ATA_IDX_OUTW(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
ATA_IDX_OUTW(ch, ATA_DRIVE,
ATA_D_IBM | ATA_D_LBA | ATA_DEV(request->unit) |
((request->u.ata.lba >> 24) & 0x0f));
+#ifndef ATA_CAM
}
+#endif
}
}
-static void
-ata_serverworks_setmode(device_t dev, int mode)
+static int
+ata_serverworks_setmode(device_t dev, int target, int mode)
{
- device_t gparent = GRANDPARENT(dev);
- struct ata_pci_controller *ctlr = device_get_softc(gparent);
- struct ata_channel *ch = device_get_softc(device_get_parent(dev));
- struct ata_device *atadev = device_get_softc(dev);
- int devno = (ch->unit << 1) + atadev->unit;
- int offset = (devno ^ 0x01) << 3;
- int error;
- u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
- u_int8_t dmatimings[] = { 0x77, 0x21, 0x20 };
-
- mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);
-
- mode = ata_check_80pin(dev, mode);
-
- error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
-
- if (bootverbose)
- device_printf(dev, "%ssetting %s on %s chip\n",
- (error) ? "FAILURE " : "",
- ata_mode2str(mode), ctlr->chip->text);
- if (!error) {
+ device_t parent = device_get_parent(dev);
+ struct ata_pci_controller *ctlr = device_get_softc(parent);
+ struct ata_channel *ch = device_get_softc(dev);
+ int devno = (ch->unit << 1) + target;
+ int offset = (devno ^ 0x01) << 3;
+ int piomode;
+ u_int8_t piotimings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
+ u_int8_t dmatimings[] = { 0x77, 0x21, 0x20 };
+
+ mode = min(mode, ctlr->chip->max_dma);
if (mode >= ATA_UDMA0) {
- pci_write_config(gparent, 0x56,
- (pci_read_config(gparent, 0x56, 2) &
+ /* Set UDMA mode, enable UDMA, set WDMA2/PIO4 */
+ pci_write_config(parent, 0x56,
+ (pci_read_config(parent, 0x56, 2) &
~(0xf << (devno << 2))) |
((mode & ATA_MODE_MASK) << (devno << 2)), 2);
- pci_write_config(gparent, 0x54,
- pci_read_config(gparent, 0x54, 1) |
+ pci_write_config(parent, 0x54,
+ pci_read_config(parent, 0x54, 1) |
(0x01 << devno), 1);
- pci_write_config(gparent, 0x44,
- (pci_read_config(gparent, 0x44, 4) &
+ pci_write_config(parent, 0x44,
+ (pci_read_config(parent, 0x44, 4) &
~(0xff << offset)) |
(dmatimings[2] << offset), 4);
- }
- else if (mode >= ATA_WDMA0) {
- pci_write_config(gparent, 0x54,
- pci_read_config(gparent, 0x54, 1) &
+ piomode = ATA_PIO4;
+ } else if (mode >= ATA_WDMA0) {
+ /* Disable UDMA, set WDMA mode and timings, calculate PIO. */
+ pci_write_config(parent, 0x54,
+ pci_read_config(parent, 0x54, 1) &
~(0x01 << devno), 1);
- pci_write_config(gparent, 0x44,
- (pci_read_config(gparent, 0x44, 4) &
+ pci_write_config(parent, 0x44,
+ (pci_read_config(parent, 0x44, 4) &
~(0xff << offset)) |
(dmatimings[mode & ATA_MODE_MASK] << offset), 4);
- }
- else
- pci_write_config(gparent, 0x54,
- pci_read_config(gparent, 0x54, 1) &
+ piomode = (mode == ATA_WDMA0) ? ATA_PIO0 :
+ (mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4;
+ } else {
+ /* Disable UDMA, set requested PIO. */
+ pci_write_config(parent, 0x54,
+ pci_read_config(parent, 0x54, 1) &
~(0x01 << devno), 1);
-
- pci_write_config(gparent, 0x40,
- (pci_read_config(gparent, 0x40, 4) &
+ piomode = mode;
+ }
+ /* Set PIO mode and timings, calculated above. */
+ pci_write_config(parent, 0x4a,
+ (pci_read_config(parent, 0x4a, 2) &
+ ~(0xf << (devno << 2))) |
+ ((piomode - ATA_PIO0) << (devno<<2)),2);
+ pci_write_config(parent, 0x40,
+ (pci_read_config(parent, 0x40, 4) &
~(0xff << offset)) |
- (piotimings[ata_mode2idx(mode)] << offset), 4);
- atadev->mode = mode;
- }
+ (piotimings[ata_mode2idx(piomode)] << offset), 4);
+ return (mode);
}
ATA_DECLARE_DRIVER(ata_serverworks);
OpenPOWER on IntegriCloud