@@ -184,6 +184,7 @@ obj-y += wdt_ib700.o wdt_i6300esb.o
# Hardware support
obj-i386-y = ide.o pckbd.o vga.o $(sound-obj-y) dma.o isa-bus.o
+obj-i386-y += atapi-pt.o atapi-data.o
obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
@@ -191,6 +192,7 @@ obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o
# shared objects
obj-ppc-y = ppc.o ide.o vga.o $(sound-obj-y) dma.o isa-bus.o openpic.o
+obj-ppc-y += atapi-pt.o atapi-data.o
# PREP target
obj-ppc-y += pckbd.o serial.o i8259.o i8254.o fdc.o mc146818rtc.o
obj-ppc-y += prep_pci.o ppc_prep.o
@@ -212,6 +214,7 @@ obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
obj-mips-y += mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o
obj-mips-y += g364fb.o jazz_led.o dp8393x.o
obj-mips-y += ide.o gt64xxx.o pckbd.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
+obj-mips-y += atapi-pt.o atapi-data.o
obj-mips-y += piix_pci.o parallel.o cirrus_vga.o isa-bus.o pcspk.o $(sound-obj-y)
obj-mips-y += mipsnet.o
obj-mips-y += pflash_cfi01.o
@@ -242,7 +245,7 @@ obj-cris-y += etraxfs_ser.o
obj-cris-y += pflash_cfi02.o
ifeq ($(TARGET_ARCH), sparc64)
-obj-sparc-y = sun4u.o ide.o isa-bus.o pckbd.o vga.o apb_pci.o
+obj-sparc-y = sun4u.o ide.o atapi-pt.o atapi-data.o isa-bus.o pckbd.o vga.o apb_pci.o
obj-sparc-y += fdc.o mc146818rtc.o serial.o
obj-sparc-y += cirrus_vga.o parallel.o
else
@@ -261,7 +264,7 @@ obj-arm-y += arm-semi.o
obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
obj-arm-y += pflash_cfi01.o gumstix.o
-obj-arm-y += zaurus.o ide.o serial.o spitz.o tosa.o tc6393xb.o
+obj-arm-y += zaurus.o ide.o atapi-pt.o atapi-data.o serial.o spitz.o tosa.o tc6393xb.o
obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
obj-arm-y += omap2.o omap_dss.o soc_dma.o
obj-arm-y += omap_sx1.o palm.o tsc210x.o
@@ -275,7 +278,7 @@ obj-arm-y += syborg_virtio.o
obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o serial.o
-obj-sh4-y += ide.o
+obj-sh4-y += ide.o atapi-pt.o atapi-data.o
obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
obj-m68k-y += m68k-semi.o dummy_m68k.o
@@ -22,21 +22,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "hw.h"
-#include "pc.h"
-#include "pci.h"
-#include "scsi-disk.h"
-#include "pcmcia.h"
-#include "block.h"
-#include "block_int.h"
-#include "qemu-timer.h"
-#include "sysemu.h"
-#include "ppc_mac.h"
-#include "mac_dbdma.h"
-#include "sh.h"
-#include "dma.h"
#include "ide.h"
-#include "atapi-defines.h"
+#include "atapi-pt.h"
/* debug IDE devices */
//#define DEBUG_IDE
@@ -44,6 +31,7 @@
//#define DEBUG_AIO
#define USE_DMA_CDROM
+
/* XXX: DVDs that could fit on a CD will be reported as a CD */
static inline int media_present(IDEState *s)
{
@@ -62,7 +50,6 @@ static inline int media_is_cd(IDEState *s)
static void ide_dma_restart(IDEState *s);
static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
-static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc);
static void padstr(char *str, const char *src, int len)
{
@@ -1978,7 +1965,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
/* ATAPI commands */
case WIN_PIDENTIFY:
if (s->is_cdrom) {
- ide_atapi_identify(s);
+ s->atapi_identify(s);
s->status = READY_STAT | SEEK_STAT;
ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
} else {
@@ -2016,7 +2003,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
s->atapi_dma = s->feature & 1;
s->nsector = 1;
ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
- ide_atapi_cmd);
+ s->atapi_cmd);
break;
/* CF-ATA commands */
case CFA_REQ_EXT_ERROR_CODE:
@@ -2355,6 +2342,16 @@ static void ide_init2(IDEState *ide_state,
if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
s->is_cdrom = 1;
+ if (!bdrv_is_sg(s->bs)) {
+ s->atapi_cmd = ide_atapi_cmd;
+ s->atapi_identify = ide_atapi_identify;
+ }
+#if CONFIG_ATAPI_PT
+ else {
+ s->atapi_cmd = ide_atapi_pt_cmd;
+ s->atapi_identify = ide_atapi_pt_identify;
+ }
+#endif /* CONFIG_ATAPI_PT */
bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
}
}
@@ -40,7 +40,20 @@
#include "dma.h"
#include "atapi-defines.h"
+
#include <stdint.h>
+#include <limits.h>
+#include <asm/byteorder.h>
+#include <assert.h>
+
+#ifdef __linux__
+# include <linux/hdreg.h>
+# define CONFIG_ATAPI_PT 1
+#else
+# define CONFIG_ATAPI_PT 0
+#endif /* __linux__ */
+
+#include <scsi/sg.h>
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
@@ -419,6 +432,50 @@ struct IDEState;
typedef void EndTransferFunc(struct IDEState *);
+typedef struct request_sense {
+#if defined(__BIG_ENDIAN_BITFIELD)
+ uint8_t valid : 1;
+ uint8_t error_code : 7;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ uint8_t error_code : 7;
+ uint8_t valid : 1;
+#endif
+ uint8_t segment_number;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ uint8_t reserved1 : 2;
+ uint8_t ili : 1;
+ uint8_t reserved2 : 1;
+ uint8_t sense_key : 4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ uint8_t sense_key : 4;
+ uint8_t reserved2 : 1;
+ uint8_t ili : 1;
+ uint8_t reserved1 : 2;
+#endif
+ uint8_t information[4];
+ uint8_t add_sense_len;
+ uint8_t command_info[4];
+ uint8_t asc;
+ uint8_t ascq;
+ uint8_t fruc;
+ uint8_t sks[3];
+ uint8_t asb[46];
+} request_sense;
+
+#if CONFIG_ATAPI_PT
+typedef struct ATAPIPassThroughState
+{
+ uint8_t request[ATAPI_PACKET_SIZE];
+ struct sg_io_hdr cmd;
+ struct request_sense sense;
+ void (*cmd_sent)(struct IDEState *);
+
+ uint32_t reply_size_init; // initial value
+ uint32_t reply_size_offset; // offset in s->io_buffer
+ uint32_t reply_size_len; // length in byte (0, 1, 2, 3 or 4)
+} ATAPIPassThroughState;
+#endif /* CONFIG_ATAPI_PT */
+
/* NOTE: IDEState represents in fact one drive */
typedef struct IDEState {
/* ide config */
@@ -468,6 +525,11 @@ typedef struct IDEState {
int lba;
int cd_sector_size;
int atapi_dma; /* true if dma is requested for the packet cmd */
+#if CONFIG_ATAPI_PT
+ ATAPIPassThroughState atapi_pt;
+#endif /* CONFIG_ATAPI_PT */
+ void (*atapi_identify)(struct IDEState *); // the ATAPI identify
+ void (*atapi_cmd)(struct IDEState *); // the ATAPI cmd handler
/* ATA DMA state */
int io_buffer_size;
QEMUSGList sg;
@@ -489,27 +551,27 @@ typedef struct IDEState {
int is_read;
} IDEState;
-#define BM_STATUS_DMAING 0x01
-#define BM_STATUS_ERROR 0x02
-#define BM_STATUS_INT 0x04
-#define BM_STATUS_DMA_RETRY 0x08
-#define BM_STATUS_PIO_RETRY 0x10
+#define BM_STATUS_DMAING 0x01
+#define BM_STATUS_ERROR 0x02
+#define BM_STATUS_INT 0x04
+#define BM_STATUS_DMA_RETRY 0x08
+#define BM_STATUS_PIO_RETRY 0x10
-#define BM_CMD_START 0x01
-#define BM_CMD_READ 0x08
+#define BM_CMD_START 0x01
+#define BM_CMD_READ 0x08
-#define IDE_TYPE_PIIX3 0
-#define IDE_TYPE_CMD646 1
-#define IDE_TYPE_PIIX4 2
+#define IDE_TYPE_PIIX3 0
+#define IDE_TYPE_CMD646 1
+#define IDE_TYPE_PIIX4 2
/* CMD646 specific */
-#define MRDMODE 0x71
-#define MRDMODE_INTR_CH0 0x04
-#define MRDMODE_INTR_CH1 0x08
-#define MRDMODE_BLK_CH0 0x10
-#define MRDMODE_BLK_CH1 0x20
-#define UDIDETCR0 0x73
-#define UDIDETCR1 0x7B
+#define MRDMODE 0x71
+#define MRDMODE_INTR_CH0 0x04
+#define MRDMODE_INTR_CH1 0x08
+#define MRDMODE_BLK_CH0 0x10
+#define MRDMODE_BLK_CH1 0x20
+#define UDIDETCR0 0x73
+#define UDIDETCR1 0x7B
typedef struct BMDMAState {
uint8_t cmd;
@@ -569,6 +631,14 @@ static inline int ube16_to_cpu(const uint8_t *buf)
return (buf[0] << 8) | buf[1];
}
+#if CONFIG_ATAPI_PT /* only atapi-pt uses it so let's avoid unused
+ * warning */
+static inline int ube24_to_cpu(const uint8_t *buf)
+{
+ return (buf[0] << 16) | (buf[1] << 8) | buf[2];
+}
+#endif /* CONFIG_ATAPI_PT */
+
static inline int ube32_to_cpu(const uint8_t *buf)
{
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
@@ -91,6 +91,13 @@ Use @var{file} as CD-ROM image (you cannot use @option{-hdc} and
using @file{/dev/cdrom} as filename (@pxref{host_drives}).
ETEXI
+DEF("cdrom-reject-fw-upgrade", 0, QEMU_OPTION_cdrom_reject_fw_upgrade,
+ "-cdrom-reject-fw-upgrade prevent the guest from upgrading cdrom firmware.\n")
+STEXI
+@item -cdrom-reject-fw-upgrade
+Prevent Qemu from passing through ATAPI firmware upgrade command.
+ETEXI
+
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
" [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
@@ -122,6 +122,7 @@ extern int no_quit;
extern int semihosting_enabled;
extern int old_param;
extern int boot_menu;
+extern int atapi_pt_reject_fw_upgrade;
#ifdef CONFIG_KQEMU
extern int kqemu_allowed;
@@ -142,6 +142,7 @@ int main(int argc, char **argv)
#include "hw/smbios.h"
#include "hw/xen.h"
#include "hw/qdev.h"
+#include "hw/atapi-pt.h"
#include "bt-host.h"
#include "net.h"
#include "monitor.h"
@@ -248,6 +249,7 @@ unsigned int nb_prom_envs = 0;
const char *prom_envs[MAX_PROM_ENVS];
#endif
int boot_menu;
+int atapi_pt_reject_fw_upgrade;
int nb_numa_nodes;
uint64_t node_mem[MAX_NODES];
@@ -1793,6 +1795,7 @@ static int bt_parse(const char *opt)
#define HD_ALIAS "index=%d,media=disk"
#define CDROM_ALIAS "index=2,media=cdrom"
+#define CDROM_PT_ALIAS "index=2,media=cdrompt"
#define FD_ALIAS "index=%d,if=floppy"
#define PFLASH_ALIAS "if=pflash"
#define MTD_ALIAS "if=mtd"
@@ -5068,6 +5071,9 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_cdrom:
drive_add(optarg, CDROM_ALIAS);
break;
+ case QEMU_OPTION_cdrom_reject_fw_upgrade:
+ atapi_pt_reject_fw_upgrade = 1;
+ break;
case QEMU_OPTION_boot:
{
static const char * const params[] = {