^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * sata_vsc.c - Vitesse VSC7174 4 port DPA SATA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Maintained by: Jeremy Higdon @ SGI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Please ALWAYS copy linux-ide@vger.kernel.org
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * on emails.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright 2004 SGI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Bits from Jeff Garzik, Copyright RedHat, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * libata documentation is available via 'make {ps|pdf}docs',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * as Documentation/driver-api/libata.rst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Vitesse hardware documentation presumably available under NDA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Intel 31244 (same hardware interface) documentation presumably
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * available from http://developer.intel.com/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/libata.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define DRV_NAME "sata_vsc"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define DRV_VERSION "2.3"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) VSC_MMIO_BAR = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Interrupt register offsets (from chip base address) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) VSC_SATA_INT_STAT_OFFSET = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) VSC_SATA_INT_MASK_OFFSET = 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Taskfile registers offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) VSC_SATA_TF_CMD_OFFSET = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) VSC_SATA_TF_DATA_OFFSET = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) VSC_SATA_TF_ERROR_OFFSET = 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) VSC_SATA_TF_FEATURE_OFFSET = 0x06,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) VSC_SATA_TF_NSECT_OFFSET = 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) VSC_SATA_TF_LBAL_OFFSET = 0x0c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) VSC_SATA_TF_LBAM_OFFSET = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) VSC_SATA_TF_LBAH_OFFSET = 0x14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) VSC_SATA_TF_DEVICE_OFFSET = 0x18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) VSC_SATA_TF_STATUS_OFFSET = 0x1c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) VSC_SATA_TF_COMMAND_OFFSET = 0x1d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) VSC_SATA_TF_ALTSTATUS_OFFSET = 0x28,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) VSC_SATA_TF_CTL_OFFSET = 0x29,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* DMA base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) VSC_SATA_UP_DESCRIPTOR_OFFSET = 0x64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) VSC_SATA_UP_DATA_BUFFER_OFFSET = 0x6C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) VSC_SATA_DMA_CMD_OFFSET = 0x70,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* SCRs base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) VSC_SATA_SCR_STATUS_OFFSET = 0x100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) VSC_SATA_SCR_ERROR_OFFSET = 0x104,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) VSC_SATA_SCR_CONTROL_OFFSET = 0x108,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* Port stride */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) VSC_SATA_PORT_OFFSET = 0x200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* Error interrupt status bit offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) VSC_SATA_INT_ERROR_CRC = 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) VSC_SATA_INT_ERROR_T = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) VSC_SATA_INT_ERROR_P = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) VSC_SATA_INT_ERROR_R = 0x8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) VSC_SATA_INT_ERROR_E = 0x4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) VSC_SATA_INT_ERROR_M = 0x2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) VSC_SATA_INT_PHY_CHANGE = 0x1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) VSC_SATA_INT_ERROR = (VSC_SATA_INT_ERROR_CRC | VSC_SATA_INT_ERROR_T | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) VSC_SATA_INT_PHY_CHANGE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int vsc_sata_scr_read(struct ata_link *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned int sc_reg, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (sc_reg > SCR_CONTROL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) *val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int vsc_sata_scr_write(struct ata_link *link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int sc_reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (sc_reg > SCR_CONTROL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static void vsc_freeze(struct ata_port *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) void __iomem *mask_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) mask_addr = ap->host->iomap[VSC_MMIO_BAR] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) VSC_SATA_INT_MASK_OFFSET + ap->port_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) writeb(0, mask_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void vsc_thaw(struct ata_port *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) void __iomem *mask_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) mask_addr = ap->host->iomap[VSC_MMIO_BAR] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) VSC_SATA_INT_MASK_OFFSET + ap->port_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) writeb(0xff, mask_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) void __iomem *mask_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u8 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) mask_addr = ap->host->iomap[VSC_MMIO_BAR] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) VSC_SATA_INT_MASK_OFFSET + ap->port_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) mask = readb(mask_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (ctl & ATA_NIEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) mask |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) mask &= 0x7F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) writeb(mask, mask_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct ata_ioports *ioaddr = &ap->ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * The only thing the ctl register is used for is SRST.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * That is not enabled or disabled via tf_load.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * However, if ATA_NIEN is changed, then we need to change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * the interrupt register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if ((tf->ctl & ATA_NIEN) != (ap->last_ctl & ATA_NIEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ap->last_ctl = tf->ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) vsc_intr_mask_update(ap, tf->ctl & ATA_NIEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) writew(tf->feature | (((u16)tf->hob_feature) << 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ioaddr->feature_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) writew(tf->nsect | (((u16)tf->hob_nsect) << 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ioaddr->nsect_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) writew(tf->lbal | (((u16)tf->hob_lbal) << 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ioaddr->lbal_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) writew(tf->lbam | (((u16)tf->hob_lbam) << 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ioaddr->lbam_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) writew(tf->lbah | (((u16)tf->hob_lbah) << 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ioaddr->lbah_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) } else if (is_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) writew(tf->feature, ioaddr->feature_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) writew(tf->nsect, ioaddr->nsect_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) writew(tf->lbal, ioaddr->lbal_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) writew(tf->lbam, ioaddr->lbam_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) writew(tf->lbah, ioaddr->lbah_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (tf->flags & ATA_TFLAG_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) writeb(tf->device, ioaddr->device_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ata_wait_idle(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct ata_ioports *ioaddr = &ap->ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) u16 nsect, lbal, lbam, lbah, feature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) tf->command = ata_sff_check_status(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) tf->device = readw(ioaddr->device_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) feature = readw(ioaddr->error_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) nsect = readw(ioaddr->nsect_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) lbal = readw(ioaddr->lbal_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) lbam = readw(ioaddr->lbam_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) lbah = readw(ioaddr->lbah_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) tf->feature = feature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) tf->nsect = nsect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) tf->lbal = lbal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) tf->lbam = lbam;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) tf->lbah = lbah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (tf->flags & ATA_TFLAG_LBA48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) tf->hob_feature = feature >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) tf->hob_nsect = nsect >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) tf->hob_lbal = lbal >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) tf->hob_lbam = lbam >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) tf->hob_lbah = lbah >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static inline void vsc_error_intr(u8 port_status, struct ata_port *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (port_status & (VSC_SATA_INT_PHY_CHANGE | VSC_SATA_INT_ERROR_M))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ata_port_freeze(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ata_port_abort(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static void vsc_port_intr(u8 port_status, struct ata_port *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct ata_queued_cmd *qc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (unlikely(port_status & VSC_SATA_INT_ERROR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) vsc_error_intr(port_status, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) qc = ata_qc_from_tag(ap, ap->link.active_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) handled = ata_bmdma_port_intr(ap, qc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* We received an interrupt during a polled command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * or some other spurious condition. Interrupt reporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * with this hardware is fairly reliable so it is safe to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * simply clear the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (unlikely(!handled))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ap->ops->sff_check_status(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * vsc_sata_interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * Read the interrupt register and process for the devices that have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * them pending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static irqreturn_t vsc_sata_interrupt(int irq, void *dev_instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct ata_host *host = dev_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) unsigned int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) status = readl(host->iomap[VSC_MMIO_BAR] + VSC_SATA_INT_STAT_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (unlikely(status == 0xffffffff || status == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dev_err(host->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ": IRQ status == 0xffffffff, PCI fault or device removal?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) spin_lock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) for (i = 0; i < host->n_ports; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) u8 port_status = (status >> (8 * i)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (port_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) vsc_port_intr(port_status, host->ports[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) handled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) spin_unlock(&host->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return IRQ_RETVAL(handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static struct scsi_host_template vsc_sata_sht = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ATA_BMDMA_SHT(DRV_NAME),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static struct ata_port_operations vsc_sata_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .inherits = &ata_bmdma_port_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /* The IRQ handling is not quite standard SFF behaviour so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) cannot use the default lost interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .lost_interrupt = ATA_OP_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .sff_tf_load = vsc_sata_tf_load,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .sff_tf_read = vsc_sata_tf_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .freeze = vsc_freeze,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .thaw = vsc_thaw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .scr_read = vsc_sata_scr_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .scr_write = vsc_sata_scr_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static void vsc_sata_setup_port(struct ata_ioports *port, void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) port->cmd_addr = base + VSC_SATA_TF_CMD_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) port->data_addr = base + VSC_SATA_TF_DATA_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) port->error_addr = base + VSC_SATA_TF_ERROR_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) port->feature_addr = base + VSC_SATA_TF_FEATURE_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) port->nsect_addr = base + VSC_SATA_TF_NSECT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) port->lbal_addr = base + VSC_SATA_TF_LBAL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) port->lbam_addr = base + VSC_SATA_TF_LBAM_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) port->lbah_addr = base + VSC_SATA_TF_LBAH_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) port->device_addr = base + VSC_SATA_TF_DEVICE_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) port->status_addr = base + VSC_SATA_TF_STATUS_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) port->command_addr = base + VSC_SATA_TF_COMMAND_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) port->altstatus_addr = base + VSC_SATA_TF_ALTSTATUS_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) port->ctl_addr = base + VSC_SATA_TF_CTL_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) port->bmdma_addr = base + VSC_SATA_DMA_CMD_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) port->scr_addr = base + VSC_SATA_SCR_STATUS_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) writel(0, base + VSC_SATA_UP_DESCRIPTOR_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) writel(0, base + VSC_SATA_UP_DATA_BUFFER_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int vsc_sata_init_one(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static const struct ata_port_info pi = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .flags = ATA_FLAG_SATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) .pio_mask = ATA_PIO4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .mwdma_mask = ATA_MWDMA2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .udma_mask = ATA_UDMA6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .port_ops = &vsc_sata_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) const struct ata_port_info *ppi[] = { &pi, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct ata_host *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) void __iomem *mmio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) u8 cls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ata_print_version_once(&pdev->dev, DRV_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* allocate host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (!host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) rc = pcim_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* check if we have needed resource mapped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (pci_resource_len(pdev, 0) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* map IO regions and initialize host accordingly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) rc = pcim_iomap_regions(pdev, 1 << VSC_MMIO_BAR, DRV_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (rc == -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) pcim_pin_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) host->iomap = pcim_iomap_table(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) mmio_base = host->iomap[VSC_MMIO_BAR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) for (i = 0; i < host->n_ports; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct ata_port *ap = host->ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) unsigned int offset = (i + 1) * VSC_SATA_PORT_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) vsc_sata_setup_port(&ap->ioaddr, mmio_base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ata_port_pbar_desc(ap, VSC_MMIO_BAR, -1, "mmio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ata_port_pbar_desc(ap, VSC_MMIO_BAR, offset, "port");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * Use 32 bit DMA mask, because 64 bit address support is poor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * Due to a bug in the chip, the default cache line size can't be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * used (unless the default is non-zero).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (cls == 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (pci_enable_msi(pdev) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) pci_intx(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * Config offset 0x98 is "Extended Control and Status Register 0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * Default value is (1 << 28). All bits except bit 28 are reserved in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * DPA mode. If bit 28 is set, LED 0 reflects all ports' activity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * If bit 28 is clear, each port has its own LED.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) pci_write_config_dword(pdev, 0x98, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) pci_set_master(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return ata_host_activate(host, pdev->irq, vsc_sata_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) IRQF_SHARED, &vsc_sata_sht);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static const struct pci_device_id vsc_sata_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) { PCI_VENDOR_ID_VITESSE, 0x7174,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) { PCI_VENDOR_ID_INTEL, 0x3200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) { } /* terminate list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static struct pci_driver vsc_sata_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .id_table = vsc_sata_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) .probe = vsc_sata_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .remove = ata_pci_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) module_pci_driver(vsc_sata_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) MODULE_AUTHOR("Jeremy Higdon");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) MODULE_DESCRIPTION("low-level driver for Vitesse VSC7174 SATA controller");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) MODULE_DEVICE_TABLE(pci, vsc_sata_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) MODULE_VERSION(DRV_VERSION);