#include "libata.h"
-static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev);
-static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev);
+static unsigned int ata_dev_init_params(struct ata_port *ap,
+ struct ata_device *dev);
static void ata_set_mode(struct ata_port *ap);
static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift);
module_param(atapi_enabled, int, 0444);
MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
+int libata_fua = 0;
+module_param_named(fua, libata_fua, int, 0444);
+MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
+
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE("GPL");
} else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
/* Unable to use DMA due to host limitation */
tf->protocol = ATA_PROT_PIO;
- index = dev->multi_count ? 0 : 4;
+ index = dev->multi_count ? 0 : 8;
} else {
tf->protocol = ATA_PROT_DMA;
index = 16;
}
/**
- * ata_dev_id_string - Convert IDENTIFY DEVICE page into string
+ * ata_id_string - Convert IDENTIFY DEVICE page into string
* @id: IDENTIFY DEVICE results we will examine
* @s: string into which data is output
* @ofs: offset into identify device page
* caller.
*/
-void ata_dev_id_string(const u16 *id, unsigned char *s,
- unsigned int ofs, unsigned int len)
+void ata_id_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len)
{
unsigned int c;
}
}
+/**
+ * ata_id_c_string - Convert IDENTIFY DEVICE page into C string
+ * @id: 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. must be an odd number.
+ *
+ * This function is identical to ata_id_string except that it
+ * trims trailing spaces and terminates the resulting string with
+ * null. @len must be actual maximum length (even number) + 1.
+ *
+ * LOCKING:
+ * caller.
+ */
+void ata_id_c_string(const u16 *id, unsigned char *s,
+ unsigned int ofs, unsigned int len)
+{
+ unsigned char *p;
+
+ WARN_ON(!(len & 1));
+
+ ata_id_string(id, s, ofs, len - 1);
+
+ p = s + strnlen(s, len - 1);
+ while (p > s && p[-1] == ' ')
+ p--;
+ *p = '\0';
+}
+
+static u64 ata_id_n_sectors(const u16 *id)
+{
+ if (ata_id_has_lba(id)) {
+ if (ata_id_has_lba48(id))
+ return ata_id_u64(id, 100);
+ else
+ return ata_id_u32(id, 60);
+ } else {
+ if (ata_id_current_chs_valid(id))
+ return ata_id_u32(id, 57);
+ else
+ return id[1] * id[3] * id[6];
+ }
+}
/**
* ata_noop_dev_select - Select device 0/1 on ATA bus
/**
* ata_dump_id - IDENTIFY DEVICE info debugging output
- * @dev: Device whose IDENTIFY DEVICE page we will dump
+ * @id: IDENTIFY DEVICE page to dump
*
- * Dump selected 16-bit words from a detected device's
- * IDENTIFY PAGE page.
+ * Dump selected 16-bit words from the given IDENTIFY DEVICE
+ * page.
*
* LOCKING:
* caller.
*/
-static inline void ata_dump_id(const struct ata_device *dev)
+static inline void ata_dump_id(const u16 *id)
{
DPRINTK("49==0x%04x "
"53==0x%04x "
"63==0x%04x "
"64==0x%04x "
"75==0x%04x \n",
- dev->id[49],
- dev->id[53],
- dev->id[63],
- dev->id[64],
- dev->id[75]);
+ id[49],
+ id[53],
+ id[63],
+ id[64],
+ id[75]);
DPRINTK("80==0x%04x "
"81==0x%04x "
"82==0x%04x "
"83==0x%04x "
"84==0x%04x \n",
- dev->id[80],
- dev->id[81],
- dev->id[82],
- dev->id[83],
- dev->id[84]);
+ id[80],
+ id[81],
+ id[82],
+ id[83],
+ id[84]);
DPRINTK("88==0x%04x "
"93==0x%04x\n",
- dev->id[88],
- dev->id[93]);
+ id[88],
+ id[93]);
}
/*
}
/**
- * ata_dev_identify - obtain IDENTIFY x DEVICE page
- * @ap: port on which device we wish to probe resides
- * @device: device bus address, starting at zero
- *
- * Following bus reset, we issue the IDENTIFY [PACKET] DEVICE
- * command, and read back the 512-byte device information page.
- * The device information page is fed to us via the standard
- * PIO-IN protocol, but we hand-code it here. (TODO: investigate
- * using standard PIO-IN paths)
- *
- * After reading the device information page, we use several
- * bits of information from it to initialize data structures
- * that will be used during the lifetime of the ata_device.
- * Other data from the info page is used to disqualify certain
- * older ATA devices we do not wish to support.
+ * ata_dev_read_id - Read ID data from the specified device
+ * @ap: port on which target device resides
+ * @dev: target device
+ * @p_class: pointer to class of the target device (may be changed)
+ * @post_reset: is this read ID post-reset?
+ * @p_id: read IDENTIFY page (newly allocated)
+ *
+ * Read ID data from the specified device. ATA_CMD_ID_ATA is
+ * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
+ * devices. This function also takes care of EDD signature
+ * misreporting (to be removed once EDD support is gone) and
+ * issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives.
*
* LOCKING:
- * Inherited from caller. Some functions called by this function
- * obtain the host_set lock.
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
*/
-
-static void ata_dev_identify(struct ata_port *ap, unsigned int device)
+static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
+ unsigned int *p_class, int post_reset, u16 **p_id)
{
- struct ata_device *dev = &ap->device[device];
- unsigned int major_version;
- u16 tmp;
- unsigned long xfer_modes;
+ unsigned int class = *p_class;
unsigned int using_edd;
struct ata_taskfile tf;
- unsigned int err_mask;
+ unsigned int err_mask = 0;
+ u16 *id;
+ const char *reason;
int rc;
- if (!ata_dev_present(dev)) {
- DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
- ap->id, device);
- return;
- }
+ DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
- if (ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
+ if (ap->ops->probe_reset ||
+ ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
using_edd = 0;
else
using_edd = 1;
- DPRINTK("ENTER, host %u, dev %u\n", ap->id, device);
+ ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
- assert (dev->class == ATA_DEV_ATA || dev->class == ATA_DEV_ATAPI ||
- dev->class == ATA_DEV_NONE);
-
- ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
+ id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL);
+ if (id == NULL) {
+ rc = -ENOMEM;
+ reason = "out of memory";
+ goto err_out;
+ }
-retry:
- ata_tf_init(ap, &tf, device);
+ retry:
+ ata_tf_init(ap, &tf, dev->devno);
- if (dev->class == ATA_DEV_ATA) {
+ switch (class) {
+ case ATA_DEV_ATA:
tf.command = ATA_CMD_ID_ATA;
- DPRINTK("do ATA identify\n");
- } else {
+ break;
+ case ATA_DEV_ATAPI:
tf.command = ATA_CMD_ID_ATAPI;
- DPRINTK("do ATAPI identify\n");
+ break;
+ default:
+ rc = -ENODEV;
+ reason = "unsupported class";
+ goto err_out;
}
tf.protocol = ATA_PROT_PIO;
err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
- dev->id, sizeof(dev->id));
+ id, sizeof(id[0]) * ATA_ID_WORDS);
if (err_mask) {
+ rc = -EIO;
+ reason = "I/O error";
+
if (err_mask & ~AC_ERR_DEV)
goto err_out;
* ATA software reset (SRST, the default) does not appear
* to have this problem.
*/
- if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
+ if ((using_edd) && (class == ATA_DEV_ATA)) {
u8 err = tf.feature;
if (err & ATA_ABORTED) {
- dev->class = ATA_DEV_ATAPI;
+ class = ATA_DEV_ATAPI;
goto retry;
}
}
goto err_out;
}
- swap_buf_le16(dev->id, ATA_ID_WORDS);
+ swap_buf_le16(id, ATA_ID_WORDS);
/* print device capabilities */
printk(KERN_DEBUG "ata%u: dev %u cfg "
"49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
- ap->id, device, dev->id[49],
- dev->id[82], dev->id[83], dev->id[84],
- dev->id[85], dev->id[86], dev->id[87],
- dev->id[88]);
+ ap->id, dev->devno,
+ id[49], id[82], id[83], id[84], id[85], id[86], id[87], id[88]);
+
+ /* sanity check */
+ if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) {
+ rc = -EINVAL;
+ reason = "device reports illegal type";
+ goto err_out;
+ }
+
+ if (post_reset && class == ATA_DEV_ATA) {
+ /*
+ * The exact sequence expected by certain pre-ATA4 drives is:
+ * SRST RESET
+ * IDENTIFY
+ * INITIALIZE DEVICE PARAMETERS
+ * anything else..
+ * Some drives were very specific about that exact sequence.
+ */
+ if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
+ err_mask = ata_dev_init_params(ap, dev);
+ if (err_mask) {
+ rc = -EIO;
+ reason = "INIT_DEV_PARAMS failed";
+ goto err_out;
+ }
+
+ /* current CHS translation info (id[53-58]) might be
+ * changed. reread the identify device info.
+ */
+ post_reset = 0;
+ goto retry;
+ }
+ }
+
+ *p_class = class;
+ *p_id = id;
+ return 0;
+
+ err_out:
+ printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n",
+ ap->id, dev->devno, reason);
+ kfree(id);
+ return rc;
+}
+
+static inline u8 ata_dev_knobble(const struct ata_port *ap,
+ struct ata_device *dev)
+{
+ return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+}
+
+/**
+ * ata_dev_configure - Configure the specified ATA/ATAPI device
+ * @ap: Port on which target device resides
+ * @dev: Target device to configure
+ *
+ * Configure @dev according to @dev->id. Generic and low-level
+ * driver specific fixups are also applied.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise
+ */
+static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev)
+{
+ unsigned long xfer_modes;
+ int i, rc;
+
+ if (!ata_dev_present(dev)) {
+ DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
+ ap->id, dev->devno);
+ return 0;
+ }
+
+ DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
+
+ /* initialize to-be-configured parameters */
+ dev->flags = 0;
+ dev->max_sectors = 0;
+ dev->cdb_len = 0;
+ dev->n_sectors = 0;
+ dev->cylinders = 0;
+ dev->heads = 0;
+ dev->sectors = 0;
/*
* common ATA, ATAPI feature tests
/* we require DMA support (bits 8 of word 49) */
if (!ata_id_has_dma(dev->id)) {
printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
+ rc = -EINVAL;
goto err_out_nosup;
}
if (!xfer_modes)
xfer_modes = ata_pio_modes(dev);
- ata_dump_id(dev);
+ ata_dump_id(dev->id);
/* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) {
- if (!ata_id_is_ata(dev->id)) /* sanity check */
- goto err_out_nosup;
-
- /* get major version */
- tmp = dev->id[ATA_ID_MAJOR_VER];
- for (major_version = 14; major_version >= 1; major_version--)
- if (tmp & (1 << major_version))
- break;
-
- /*
- * The exact sequence expected by certain pre-ATA4 drives is:
- * SRST RESET
- * IDENTIFY
- * INITIALIZE DEVICE PARAMETERS
- * anything else..
- * Some drives were very specific about that exact sequence.
- */
- if (major_version < 4 || (!ata_id_has_lba(dev->id))) {
- ata_dev_init_params(ap, dev);
-
- /* current CHS translation info (id[53-58]) might be
- * changed. reread the identify device info.
- */
- ata_dev_reread_id(ap, dev);
- }
+ dev->n_sectors = ata_id_n_sectors(dev->id);
if (ata_id_has_lba(dev->id)) {
dev->flags |= ATA_DFLAG_LBA;
- if (ata_id_has_lba48(dev->id)) {
+ if (ata_id_has_lba48(dev->id))
dev->flags |= ATA_DFLAG_LBA48;
- dev->n_sectors = ata_id_u64(dev->id, 100);
- } else {
- dev->n_sectors = ata_id_u32(dev->id, 60);
- }
/* print device info to dmesg */
printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
- ap->id, device,
- major_version,
+ ap->id, dev->devno,
+ ata_id_major_version(dev->id),
ata_mode_string(xfer_modes),
(unsigned long long)dev->n_sectors,
dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
- } else {
+ } else {
/* CHS */
/* Default translation */
dev->cylinders = dev->id[1];
dev->heads = dev->id[3];
dev->sectors = dev->id[6];
- dev->n_sectors = dev->cylinders * dev->heads * dev->sectors;
if (ata_id_current_chs_valid(dev->id)) {
/* Current CHS translation is valid. */
dev->cylinders = dev->id[54];
dev->heads = dev->id[55];
dev->sectors = dev->id[56];
-
- dev->n_sectors = ata_id_u32(dev->id, 57);
}
/* print device info to dmesg */
printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
- ap->id, device,
- major_version,
+ ap->id, dev->devno,
+ ata_id_major_version(dev->id),
ata_mode_string(xfer_modes),
(unsigned long long)dev->n_sectors,
(int)dev->cylinders, (int)dev->heads, (int)dev->sectors);
}
- ap->host->max_cmd_len = 16;
+ dev->cdb_len = 16;
}
/* ATAPI-specific feature tests */
else if (dev->class == ATA_DEV_ATAPI) {
- if (ata_id_is_ata(dev->id)) /* sanity check */
- goto err_out_nosup;
-
rc = atapi_cdb_len(dev->id);
if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);
+ rc = -EINVAL;
goto err_out_nosup;
}
- ap->cdb_len = (unsigned int) rc;
- ap->host->max_cmd_len = (unsigned char) ap->cdb_len;
+ dev->cdb_len = (unsigned int) rc;
/* print device info to dmesg */
printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
- ap->id, device,
+ ap->id, dev->devno,
ata_mode_string(xfer_modes));
}
- DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
- return;
-
-err_out_nosup:
- printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
- ap->id, device);
-err_out:
- dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */
- DPRINTK("EXIT, err\n");
-}
-
-
-static inline u8 ata_dev_knobble(const struct ata_port *ap)
-{
- return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id)));
-}
-
-/**
- * ata_dev_config - Run device specific handlers & check for SATA->PATA bridges
- * @ap: Bus
- * @i: Device
- *
- * LOCKING:
- */
+ ap->host->max_cmd_len = 0;
+ for (i = 0; i < ATA_MAX_DEVICES; i++)
+ ap->host->max_cmd_len = max_t(unsigned int,
+ ap->host->max_cmd_len,
+ ap->device[i].cdb_len);
-void ata_dev_config(struct ata_port *ap, unsigned int i)
-{
/* limit bridge transfers to udma5, 200 sectors */
- if (ata_dev_knobble(ap)) {
+ if (ata_dev_knobble(ap, dev)) {
printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
- ap->id, ap->device->devno);
+ ap->id, dev->devno);
ap->udma_mask &= ATA_UDMA5;
- ap->host->max_sectors = ATA_MAX_SECTORS;
- ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
- ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS;
+ dev->max_sectors = ATA_MAX_SECTORS;
}
if (ap->ops->dev_config)
- ap->ops->dev_config(ap, &ap->device[i]);
+ ap->ops->dev_config(ap, dev);
+
+ DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
+ return 0;
+
+err_out_nosup:
+ printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
+ ap->id, dev->devno);
+ DPRINTK("EXIT, err\n");
+ return rc;
}
/**
static int ata_bus_probe(struct ata_port *ap)
{
- unsigned int i, found = 0;
+ unsigned int classes[ATA_MAX_DEVICES];
+ unsigned int i, rc, found = 0;
- if (ap->ops->probe_reset) {
- unsigned int classes[ATA_MAX_DEVICES];
- int rc;
-
- ata_port_probe(ap);
+ ata_port_probe(ap);
+ /* reset */
+ if (ap->ops->probe_reset) {
rc = ap->ops->probe_reset(ap, classes);
- if (rc == 0) {
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- ap->device[i].class = classes[i];
- } else {
- printk(KERN_ERR "ata%u: probe reset failed, "
- "disabling port\n", ap->id);
- ata_port_disable(ap);
+ if (rc) {
+ printk("ata%u: reset failed (errno=%d)\n", ap->id, rc);
+ return rc;
}
- } else
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++)
+ if (classes[i] == ATA_DEV_UNKNOWN)
+ classes[i] = ATA_DEV_NONE;
+ } else {
ap->ops->phy_reset(ap);
- if (ap->flags & ATA_FLAG_PORT_DISABLED)
- goto err_out;
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
+ classes[i] = ap->device[i].class;
+ else
+ ap->device[i].class = ATA_DEV_UNKNOWN;
+ }
+ ata_port_probe(ap);
+ }
+ /* read IDENTIFY page and configure devices */
for (i = 0; i < ATA_MAX_DEVICES; i++) {
- ata_dev_identify(ap, i);
- if (ata_dev_present(&ap->device[i])) {
- found = 1;
- ata_dev_config(ap,i);
+ struct ata_device *dev = &ap->device[i];
+
+ dev->class = classes[i];
+
+ if (!ata_dev_present(dev))
+ continue;
+
+ WARN_ON(dev->id != NULL);
+ if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) {
+ dev->class = ATA_DEV_NONE;
+ continue;
}
+
+ if (ata_dev_configure(ap, dev)) {
+ dev->class++; /* disable device */
+ continue;
+ }
+
+ found = 1;
}
- if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+ if (!found)
goto err_out_disable;
ata_set_mode(ap);
err_out_disable:
ap->ops->port_disable(ap);
-err_out:
return -1;
}
*
* @ap is about to be probed. Initialize it. This function is
* to be used as standard callback for ata_drive_probe_reset().
+ *
+ * NOTE!!! Do not use this function as probeinit if a low level
+ * driver implements only hardreset. Just pass NULL as probeinit
+ * in that case. Using this function is probably okay but doing
+ * so makes reset sequence different from the original
+ * ->phy_reset implementation and Jeff nervous. :-P
*/
extern void ata_std_probeinit(struct ata_port *ap)
{
- if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read)
+ if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) {
sata_phy_resume(ap);
+ if (sata_dev_present(ap))
+ ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+ }
}
/**
DPRINTK("ENTER\n");
+ if (ap->ops->scr_read && !sata_dev_present(ap)) {
+ classes[0] = ATA_DEV_NONE;
+ goto out;
+ }
+
/* determine if device 0/1 are present */
if (ata_devchk(ap, 0))
devmask |= (1 << 0);
if (slave_possible && ata_devchk(ap, 1))
devmask |= (1 << 1);
- /* devchk reports device presence without actual device on
- * most SATA controllers. Check SStatus and turn devmask off
- * if link is offline. Note that we should continue resetting
- * even when it seems like there's no device.
- */
- if (ap->ops->scr_read && !sata_dev_present(ap))
- devmask = 0;
-
/* select device 0 again */
ap->ops->dev_select(ap, 0);
if (slave_possible && err != 0x81)
classes[1] = ata_dev_try_classify(ap, 1, &err);
+ out:
DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
return 0;
}
*/
int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
{
- u32 serror;
-
DPRINTK("ENTER\n");
/* Issue phy wake/reset */
/* Bring phy back */
sata_phy_resume(ap);
- /* Clear SError */
- serror = scr_read(ap, SCR_ERROR);
- scr_write(ap, SCR_ERROR, serror);
-
/* TODO: phy layer with polling, timeouts, etc. */
if (!sata_dev_present(ap)) {
*class = ATA_DEV_NONE;
return -EIO;
}
+ ap->ops->dev_select(ap, 0); /* probably unnecessary */
+
*class = ata_dev_try_classify(ap, 0, NULL);
DPRINTK("EXIT, class=%u\n", *class);
* This function is invoked after a successful reset. Note that
* the device might have been reset more than once using
* different reset methods before postreset is invoked.
- * postreset is also reponsible for setting cable type.
*
* This function is to be used as standard callback for
* ata_drive_*_reset().
{
DPRINTK("ENTER\n");
- /* set cable type */
+ /* set cable type if it isn't already set */
if (ap->cbl == ATA_CBL_NONE && ap->flags & ATA_FLAG_SATA)
ap->cbl = ATA_CBL_SATA;
if (ap->cbl == ATA_CBL_SATA)
sata_print_link_status(ap);
- /* bail out if no device is present */
- if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
- DPRINTK("EXIT, no device\n");
- return;
- }
+ /* re-enable interrupts */
+ if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
+ ata_irq_on(ap);
/* is double-select really necessary? */
if (classes[0] != ATA_DEV_NONE)
if (classes[1] != ATA_DEV_NONE)
ap->ops->dev_select(ap, 0);
- /* re-enable interrupts & set up device control */
- if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
- ata_irq_on(ap);
+ /* bail out if no device is present */
+ if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+ DPRINTK("EXIT, no device\n");
+ return;
+ }
+
+ /* set up device control */
+ if (ap->ioaddr.ctl_addr) {
+ if (ap->flags & ATA_FLAG_MMIO)
+ writeb(ap->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
+ else
+ outb(ap->ctl, ap->ioaddr.ctl_addr);
+ }
DPRINTK("EXIT\n");
}
static int ata_dma_blacklisted(const struct ata_device *dev)
{
- unsigned char model_num[40];
- char *s;
- unsigned int len;
+ unsigned char model_num[41];
int i;
- ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
- sizeof(model_num));
- s = &model_num[0];
- len = strnlen(s, sizeof(model_num));
-
- /* ATAPI specifies that empty space is blank-filled; remove blanks */
- while ((len > 0) && (s[len - 1] == ' ')) {
- len--;
- s[len] = 0;
- }
+ ata_id_c_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num));
for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++)
- if (!strncmp(ata_dma_blacklist[i], s, len))
+ if (!strcmp(ata_dma_blacklist[i], model_num))
return 1;
return 0;
master = &ap->device[0];
slave = &ap->device[1];
- assert (ata_dev_present(master) || ata_dev_present(slave));
+ WARN_ON(!ata_dev_present(master) && !ata_dev_present(slave));
if (shift == ATA_SHIFT_UDMA) {
mask = ap->udma_mask;
DPRINTK("EXIT\n");
}
-/**
- * ata_dev_reread_id - Reread the device identify device info
- * @ap: port where the device is
- * @dev: device to reread the identify device info
- *
- * LOCKING:
- */
-
-static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
-{
- struct ata_taskfile tf;
-
- ata_tf_init(ap, &tf, dev->devno);
-
- if (dev->class == ATA_DEV_ATA) {
- tf.command = ATA_CMD_ID_ATA;
- DPRINTK("do ATA identify\n");
- } else {
- tf.command = ATA_CMD_ID_ATAPI;
- DPRINTK("do ATAPI identify\n");
- }
-
- tf.flags |= ATA_TFLAG_DEVICE;
- tf.protocol = ATA_PROT_PIO;
-
- if (ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
- dev->id, sizeof(dev->id)))
- goto err_out;
-
- swap_buf_le16(dev->id, ATA_ID_WORDS);
-
- ata_dump_id(dev);
-
- DPRINTK("EXIT\n");
-
- return;
-err_out:
- printk(KERN_ERR "ata%u: failed to reread ID, disabled\n", ap->id);
- ata_port_disable(ap);
-}
-
/**
* ata_dev_init_params - Issue INIT DEV PARAMS command
* @ap: Port associated with device @dev
* @dev: Device to which command will be sent
*
* LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * 0 on success, AC_ERR_* mask otherwise.
*/
-static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
+static unsigned int ata_dev_init_params(struct ata_port *ap,
+ struct ata_device *dev)
{
struct ata_taskfile tf;
+ unsigned int err_mask;
u16 sectors = dev->id[6];
u16 heads = dev->id[3];
/* Number of sectors per track 1-255. Number of heads 1-16 */
if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
- return;
+ return 0;
/* set up init dev params taskfile */
DPRINTK("init dev params \n");
tf.nsect = sectors;
tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
- if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
- printk(KERN_ERR "ata%u: failed to init parameters, disabled\n",
- ap->id);
- ata_port_disable(ap);
- }
+ err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
- DPRINTK("EXIT\n");
+ DPRINTK("EXIT, err_mask=%x\n", err_mask);
+ return err_mask;
}
/**
int dir = qc->dma_dir;
void *pad_buf = NULL;
- assert(qc->flags & ATA_QCFLAG_DMAMAP);
- assert(sg != NULL);
+ WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+ WARN_ON(sg == NULL);
if (qc->flags & ATA_QCFLAG_SINGLE)
- assert(qc->n_elem == 1);
+ WARN_ON(qc->n_elem > 1);
VPRINTK("unmapping %u sg elements\n", qc->n_elem);
kunmap_atomic(addr, KM_IRQ0);
}
} else {
- if (sg_dma_len(&sg[0]) > 0)
+ if (qc->n_elem)
dma_unmap_single(ap->host_set->dev,
sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
dir);
struct scatterlist *sg;
unsigned int idx;
- assert(qc->__sg != NULL);
- assert(qc->n_elem > 0);
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
idx = 0;
ata_for_each_sg(sg, qc) {
int dir = qc->dma_dir;
struct scatterlist *sg = qc->__sg;
dma_addr_t dma_address;
+ int trim_sg = 0;
/* we must lengthen transfers to end on a 32-bit boundary */
qc->pad_len = sg->length & 3;
void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
struct scatterlist *psg = &qc->pad_sgent;
- assert(qc->dev->class == ATA_DEV_ATAPI);
+ WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
memset(pad_buf, 0, ATA_DMA_PAD_SZ);
sg_dma_len(psg) = ATA_DMA_PAD_SZ;
/* trim sg */
sg->length -= qc->pad_len;
+ if (sg->length == 0)
+ trim_sg = 1;
DPRINTK("padding done, sg->length=%u pad_len=%u\n",
sg->length, qc->pad_len);
}
- if (!sg->length) {
- sg_dma_address(sg) = 0;
+ if (trim_sg) {
+ qc->n_elem--;
goto skip_map;
}
}
sg_dma_address(sg) = dma_address;
-skip_map:
sg_dma_len(sg) = sg->length;
+skip_map:
DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
int n_elem, pre_n_elem, dir, trim_sg = 0;
VPRINTK("ENTER, ata%u\n", ap->id);
- assert(qc->flags & ATA_QCFLAG_SG);
+ WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
/* we must lengthen transfers to end on a 32-bit boundary */
qc->pad_len = lsg->length & 3;
struct scatterlist *psg = &qc->pad_sgent;
unsigned int offset;
- assert(qc->dev->class == ATA_DEV_ATAPI);
+ WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
memset(pad_buf, 0, ATA_DMA_PAD_SZ);
unsigned int reg_state = HSM_ST_UNKNOWN;
qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
+ WARN_ON(qc == NULL);
switch (ap->hsm_task_state) {
case HSM_ST:
}
qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
+ WARN_ON(qc == NULL);
drv_stat = ata_wait_idle(ap);
if (!ata_ok(drv_stat)) {
ap->hsm_task_state = HSM_ST_IDLE;
- assert(qc->err_mask == 0);
+ WARN_ON(qc->err_mask);
ata_poll_qc_complete(qc);
/* another command may start at this point */
}
qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
+ WARN_ON(qc == NULL);
/* check error */
if (status & (ATA_ERR | ATA_DF)) {
{
struct ata_queued_cmd *qc;
- printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
-
qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
+ WARN_ON(qc == NULL);
+
+ if (qc->tf.command != ATA_CMD_PACKET)
+ printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
/* make sure qc->err_mask is available to
* know what's wrong and recover
*/
- assert(qc->err_mask);
+ WARN_ON(qc->err_mask == 0);
ap->hsm_task_state = HSM_ST_IDLE;
void ata_eng_timeout(struct ata_port *ap)
{
- struct ata_queued_cmd *qc;
-
DPRINTK("ENTER\n");
- qc = ata_qc_from_tag(ap, ap->active_tag);
- if (qc)
- ata_qc_timeout(qc);
- else {
- printk(KERN_ERR "ata%u: BUG: timeout without command\n",
- ap->id);
- goto out;
- }
+ ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
-out:
DPRINTK("EXIT\n");
}
struct ata_port *ap = qc->ap;
unsigned int tag;
- assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
+ WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
qc->flags = 0;
tag = qc->tag;
}
}
-inline void __ata_qc_complete(struct ata_queued_cmd *qc)
+void __ata_qc_complete(struct ata_queued_cmd *qc)
{
- assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
- assert(qc->flags & ATA_QCFLAG_ACTIVE);
+ WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
+ WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
ata_sg_clean(qc);
qc->complete_fn(qc);
}
-/**
- * ata_qc_complete - Complete an active ATA command
- * @qc: Command to complete
- * @err_mask: ATA Status register contents
- *
- * Indicate to the mid and upper layers that an ATA
- * command has completed, with either an ok or not-ok status.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-void ata_qc_complete(struct ata_queued_cmd *qc)
-{
- if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
- return;
-
- __ata_qc_complete(qc);
-}
-
static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
u8 status;
qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
- assert(qc->flags & ATA_QCFLAG_ACTIVE);
+ WARN_ON(qc == NULL);
+ WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
/* sleep-wait for BSY to clear */
DPRINTK("busy wait\n");
/* send SCSI cdb */
DPRINTK("send cdb\n");
- assert(ap->cdb_len >= 12);
+ WARN_ON(qc->dev->cdb_len < 12);
if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
*/
spin_lock_irqsave(&ap->host_set->lock, flags);
ap->flags &= ~ATA_FLAG_NOINTR;
- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
+ ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
ap->ops->bmdma_start(qc); /* initiate bmdma */
spin_unlock_irqrestore(&ap->host_set->lock, flags);
} else {
- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
+ ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
/* PIO commands are handled by polling */
ap->hsm_task_state = HSM_ST;
int ata_scsi_release(struct Scsi_Host *host)
{
struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
+ int i;
DPRINTK("ENTER\n");
ap->ops->port_disable(ap);
ata_host_remove(ap, 0);
+ for (i = 0; i < ATA_MAX_DEVICES; i++)
+ kfree(ap->device[i].id);
DPRINTK("EXIT\n");
return 1;
EXPORT_SYMBOL_GPL(ata_host_set_remove);
EXPORT_SYMBOL_GPL(ata_sg_init);
EXPORT_SYMBOL_GPL(ata_sg_init_one);
-EXPORT_SYMBOL_GPL(ata_qc_complete);
+EXPORT_SYMBOL_GPL(__ata_qc_complete);
EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
EXPORT_SYMBOL_GPL(ata_eng_timeout);
EXPORT_SYMBOL_GPL(ata_tf_load);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
+EXPORT_SYMBOL_GPL(ata_scsi_timed_out);
EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_release);
EXPORT_SYMBOL_GPL(ata_host_intr);
EXPORT_SYMBOL_GPL(ata_dev_classify);
-EXPORT_SYMBOL_GPL(ata_dev_id_string);
-EXPORT_SYMBOL_GPL(ata_dev_config);
+EXPORT_SYMBOL_GPL(ata_id_string);
+EXPORT_SYMBOL_GPL(ata_id_c_string);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
EXPORT_SYMBOL_GPL(ata_eh_qc_retry);