diff options
Diffstat (limited to 'sys/dev/ata/chipsets/ata-serverworks.c')
-rw-r--r-- | sys/dev/ata/chipsets/ata-serverworks.c | 99 |
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); |