/* Per the spec, only slot type and drawer type ODD can be supported */ static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev) { char buf[16]; unsigned int ret; struct rm_feature_desc *desc = (void *)(buf + 8); struct ata_taskfile tf = {}; char cdb[] = { GPCMD_GET_CONFIGURATION, 2, /* only 1 feature descriptor requested */ 0, 3, /* 3, removable medium feature */ 0, 0, 0,/* reserved */ 0, sizeof(buf), 0, 0, 0, }; tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.command = ATA_CMD_PACKET; tf.protocol = ATAPI_PROT_PIO; tf.lbam = sizeof(buf); ret = ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE, buf, sizeof(buf), 0); if (ret) return ODD_MECH_TYPE_UNSUPPORTED; if (be16_to_cpu(desc->feature_code) != 3) return ODD_MECH_TYPE_UNSUPPORTED; if (desc->mech_type == 0 && desc->load == 0 && desc->eject == 1) return ODD_MECH_TYPE_SLOT; else if (desc->mech_type == 1 && desc->load == 0 && desc->eject == 1) return ODD_MECH_TYPE_DRAWER; else return ODD_MECH_TYPE_UNSUPPORTED; }
/* Per the spec, only slot type and drawer type ODD can be supported */ static enum odd_mech_type zpodd_get_mech_type(struct ata_device *dev) { char *buf; unsigned int ret; struct rm_feature_desc *desc; struct ata_taskfile tf; static const char cdb[] = { GPCMD_GET_CONFIGURATION, 2, /* only 1 feature descriptor requested */ 0, 3, /* 3, removable medium feature */ 0, 0, 0,/* reserved */ 0, 16, 0, 0, 0, }; buf = kzalloc(16, GFP_KERNEL); if (!buf) return ODD_MECH_TYPE_UNSUPPORTED; desc = (void *)(buf + 8); ata_tf_init(dev, &tf); tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.command = ATA_CMD_PACKET; tf.protocol = ATAPI_PROT_PIO; tf.lbam = 16; ret = ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE, buf, 16, 0); if (ret) { kfree(buf); return ODD_MECH_TYPE_UNSUPPORTED; } if (be16_to_cpu(desc->feature_code) != 3) { kfree(buf); return ODD_MECH_TYPE_UNSUPPORTED; } if (desc->mech_type == 0 && desc->load == 0 && desc->eject == 1) { kfree(buf); return ODD_MECH_TYPE_SLOT; } else if (desc->mech_type == 1 && desc->load == 0 && desc->eject == 1) { kfree(buf); return ODD_MECH_TYPE_DRAWER; } else { kfree(buf); return ODD_MECH_TYPE_UNSUPPORTED; } }
static int eject_tray(struct ata_device *dev) { struct ata_taskfile tf = {}; const char cdb[] = { GPCMD_START_STOP_UNIT, 0, 0, 0, 0x02, /* LoEj */ 0, 0, 0, 0, 0, 0, 0, }; tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.command = ATA_CMD_PACKET; tf.protocol = ATAPI_PROT_NODATA; return ata_exec_internal(dev, &tf, cdb, DMA_NONE, NULL, 0, 0); }
/** * sata_pmp_write - write PMP register * @link: link to write PMP register for * @reg: register to write * @r_val: value to write * * Write PMP register. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, AC_ERR_* mask on failure. */ static unsigned int sata_pmp_write(struct ata_link *link, int reg, u32 val) { struct ata_port *ap = link->ap; struct ata_device *pmp_dev = ap->link.device; struct ata_taskfile tf; ata_tf_init(pmp_dev, &tf); tf.command = ATA_CMD_PMP_WRITE; tf.protocol = ATA_PROT_NODATA; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.feature = reg; tf.device = link->pmp; tf.nsect = val & 0xff; tf.lbal = (val >> 8) & 0xff; tf.lbam = (val >> 16) & 0xff; tf.lbah = (val >> 24) & 0xff; return ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0, SATA_PMP_SCR_TIMEOUT); }
/** * sata_pmp_read - read PMP register * @link: link to read PMP register for * @reg: register to read * @r_val: resulting value * * Read PMP register. * * LOCKING: * Kernel thread context (may sleep). * * RETURNS: * 0 on success, AC_ERR_* mask on failure. */ static unsigned int sata_pmp_read(struct ata_link *link, int reg, u32 *r_val) { struct ata_port *ap = link->ap; struct ata_device *pmp_dev = ap->link.device; struct ata_taskfile tf; unsigned int err_mask; ata_tf_init(pmp_dev, &tf); tf.command = ATA_CMD_PMP_READ; tf.protocol = ATA_PROT_NODATA; tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.feature = reg; tf.device = link->pmp; err_mask = ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0, SATA_PMP_SCR_TIMEOUT); if (err_mask) return err_mask; *r_val = tf.nsect | tf.lbal << 8 | tf.lbam << 16 | tf.lbah << 24; return 0; }