[devel] feat-drivers-mtrw patch for 2.6.1-rc1
Konstantin A. Lepikhov
=?iso-8859-1?q?lakostis_=CE=C1_elektrostal=2Eru?=
Сб Янв 3 22:02:23 MSK 2004
Hi!
К сожалению, в firmware для моей TOSHIBA SD-1312 нет поддержки mt, так что
проверить мне его так и не удалось :( Может быть кому-то из участников
devel или kernel-devel будет интересно проверить этот патч? Вроде бы ядро
с ним вполне рабочее + он не конфликтует с pktcdvd. Так же прилагаю и
обновленную Jens'ом cdmrw.c
--
WBR, Konstantin chat with ==>ICQ: 109916175
Lepikhov, speak to ==>JID: lakostis на jabber.org
aka L.A. Kostis write to ==>mailto:lakostis на pisem.net.nospam
...The information is like the bank... (c) EC8OR
----------- следующая часть -----------
diff -urN new.orig/drivers/cdrom/cdrom.c new/drivers/cdrom/cdrom.c
--- new.orig/drivers/cdrom/cdrom.c 2003-12-30 23:09:39 +0300
+++ new/drivers/cdrom/cdrom.c 2004-01-03 16:52:45 +0300
@@ -228,10 +228,16 @@
3.12 Oct 18, 2000 - Jens Axboe <axboe на suse.de>
-- Use quiet bit on packet commands not known to work
+ 3.20 Dec 17, 2003 - Jens Axboe <axboe на suse.de>
+ -- Various fixes and lots of cleanups not listed :-)
+ -- Locking fixes
+ -- Mt Rainier support
+ -- DVD-RAM write open fixes
+
-------------------------------------------------------------------------*/
-#define REVISION "Revision: 3.12"
-#define VERSION "Id: cdrom.c 3.12 2000/10/18"
+#define REVISION "Revision: 3.20"
+#define VERSION "Id: cdrom.c 3.20 2003/12/17"
/* I use an error-log mask to give fine grain control over the type of
messages dumped to the system logs. The available masks include: */
@@ -282,11 +288,25 @@
static int lockdoor = 1;
/* will we ever get to use this... sigh. */
static int check_media_type;
+/* automatically restart mrw format */
+static int mrw_format_restart = 1;
MODULE_PARM(debug, "i");
MODULE_PARM(autoclose, "i");
MODULE_PARM(autoeject, "i");
MODULE_PARM(lockdoor, "i");
MODULE_PARM(check_media_type, "i");
+MODULE_PARM(mrw_format_restart, "i");
+
+static spinlock_t cdrom_lock = SPIN_LOCK_UNLOCKED;
+
+static const char *mrw_format_status[] = {
+ "not mrw",
+ "bgformat inactive",
+ "bgformat active",
+ "mrw complete",
+};
+
+static const char *mrw_address_space[] = { "DMA", "GAA" };
#if (ERRLOGMASK!=CD_NOTHING)
#define cdinfo(type, fmt, args...) \
@@ -325,6 +345,10 @@
static int cdrom_get_next_writable(struct cdrom_device_info *, long *);
static void cdrom_count_tracks(struct cdrom_device_info *, tracktype*);
+static int cdrom_mrw_exit(struct cdrom_device_info *cdi);
+
+static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di);
+
#ifdef CONFIG_SYSCTL
static void cdrom_sysctl_register(void);
#endif /* CONFIG_SYSCTL */
@@ -347,13 +371,14 @@
if (cdo->open == NULL || cdo->release == NULL)
return -2;
- if ( !banner_printed ) {
+ if (!banner_printed) {
printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n");
banner_printed = 1;
#ifdef CONFIG_SYSCTL
cdrom_sysctl_register();
#endif /* CONFIG_SYSCTL */
}
+
ENSURE(drive_status, CDC_DRIVE_STATUS );
ENSURE(media_changed, CDC_MEDIA_CHANGED);
ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
@@ -378,9 +403,14 @@
if (check_media_type==1)
cdi->options |= (int) CDO_CHECK_TYPE;
+ if (CDROM_CAN(CDC_MRW_W))
+ cdi->exit = cdrom_mrw_exit;
+
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
+ spin_lock(&cdrom_lock);
cdi->next = topCdromPtr;
topCdromPtr = cdi;
+ spin_unlock(&cdrom_lock);
return 0;
}
#undef ENSURE
@@ -391,23 +421,311 @@
cdinfo(CD_OPEN, "entering unregister_cdrom\n");
prev = NULL;
+ spin_lock(&cdrom_lock);
cdi = topCdromPtr;
while (cdi && cdi != unreg) {
prev = cdi;
cdi = cdi->next;
}
- if (cdi == NULL)
+ if (cdi == NULL) {
+ spin_unlock(&cdrom_lock);
return -2;
+ }
if (prev)
prev->next = cdi->next;
else
topCdromPtr = cdi->next;
+
+ spin_unlock(&cdrom_lock);
+
+ if (cdi->exit)
+ cdi->exit(cdi);
+
cdi->ops->n_minors--;
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
return 0;
}
+int cdrom_get_media_event(struct cdrom_device_info *cdi,
+ struct media_event_desc *med)
+{
+ struct cdrom_generic_command cgc;
+ unsigned char buffer[8];
+ struct event_header *eh = (struct event_header *) buffer;
+
+ init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+ cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
+ cgc.cmd[1] = 1; /* IMMED */
+ cgc.cmd[4] = 1 << 4; /* media event */
+ cgc.cmd[8] = sizeof(buffer);
+ cgc.quiet = 1;
+
+ if (cdi->ops->generic_packet(cdi, &cgc))
+ return 1;
+
+ if (be16_to_cpu(eh->data_len) < sizeof(*med))
+ return 1;
+
+ memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
+ return 0;
+}
+
+/*
+ * the first prototypes used 0x2c as the page code for the mrw mode page,
+ * subsequently this was changed to 0x03. probe the one used by this drive
+ */
+int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi)
+{
+ struct cdrom_generic_command cgc;
+ char buffer[16];
+
+ init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+ cgc.buffer = buffer;
+ cgc.buflen = sizeof(buffer);
+ cgc.timeout = HZ;
+ cgc.quiet = 1;
+
+ if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) {
+ cdi->mrw_mode_page = MRW_MODE_PC;
+ return 0;
+ } else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) {
+ cdi->mrw_mode_page = MRW_MODE_PC_PRE1;
+ return 0;
+ } else {
+ printk("cdrom: %s: unknown mrw mode page\n", cdi->name);
+ return 1;
+ }
+
+ printk("cdrom: %s: mrw mode page %x\n", cdi->name, cdi->mrw_mode_page);
+}
+
+int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write)
+{
+ struct cdrom_generic_command cgc;
+ struct mrw_feature_desc *mfd;
+ unsigned char buffer[16];
+ int ret;
+
+ init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+ cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+ cgc.cmd[3] = CDF_MRW;
+ cgc.cmd[8] = sizeof(buffer);
+ cgc.quiet = 1;
+
+ if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+ return ret;
+
+ mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
+ *write = mfd->write;
+
+ if ((ret = cdrom_mrw_probe_pc(cdi)))
+ return ret;
+
+ return 0;
+}
+
+static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
+{
+ struct cdrom_generic_command cgc;
+ unsigned char buffer[12];
+ int ret;
+
+ printk("cdrom: %sstarting format\n", cont ? "Re" : "");
+
+ /*
+ * FmtData bit set (bit 4), format type is 1
+ */
+ init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_WRITE);
+ cgc.cmd[0] = GPCMD_FORMAT_UNIT;
+ cgc.cmd[1] = (1 << 4) | 1;
+
+ cgc.timeout = 5 * 60 * HZ;
+
+ /*
+ * 4 byte format list header, 8 byte format list descriptor
+ */
+ buffer[1] = 1 << 1;
+ buffer[3] = 8;
+
+ /*
+ * nr_blocks field
+ */
+ buffer[4] = 0xff;
+ buffer[5] = 0xff;
+ buffer[6] = 0xff;
+ buffer[7] = 0xff;
+
+ buffer[8] = 0x24 << 2;
+ buffer[11] = cont;
+
+ ret = cdi->ops->generic_packet(cdi, &cgc);
+ if (ret)
+ printk("cdrom: bgformat failed\n");
+
+ return ret;
+}
+
+static int cdrom_mrw_bgformat_susp(struct cdrom_device_info *cdi, int immed)
+{
+ struct cdrom_generic_command cgc;
+
+ init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
+ cgc.cmd[0] = GPCMD_CLOSE_TRACK;
+
+ /*
+ * Session = 1, Track = 0
+ */
+ cgc.cmd[1] = !!immed;
+ cgc.cmd[2] = 1 << 1;
+
+ cgc.timeout = 300 * HZ;
+
+ return cdi->ops->generic_packet(cdi, &cgc);
+}
+
+static int cdrom_flush_cache(struct cdrom_device_info *cdi)
+{
+ struct cdrom_generic_command cgc;
+
+ init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
+ cgc.cmd[0] = GPCMD_FLUSH_CACHE;
+
+ cgc.timeout = 5 * 60 * HZ;
+
+ return cdi->ops->generic_packet(cdi, &cgc);
+}
+
+static int cdrom_mrw_exit(struct cdrom_device_info *cdi)
+{
+ disc_information di;
+ int ret = 0;
+
+ if (cdrom_get_disc_info(cdi, &di))
+ return 1;
+
+ if (di.mrw_status == CDM_MRW_BGFORMAT_ACTIVE) {
+ printk("cdrom: issuing MRW back ground format suspend\n");
+ ret = cdrom_mrw_bgformat_susp(cdi, 0);
+ }
+
+ if (!ret)
+ ret = cdrom_flush_cache(cdi);
+
+ return ret;
+}
+
+static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
+{
+ struct cdrom_generic_command cgc;
+ struct mode_page_header *mph;
+ char buffer[16];
+ int ret, offset, size;
+
+ init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+ cgc.buffer = buffer;
+ cgc.buflen = sizeof(buffer);
+
+ if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
+ return ret;
+
+ mph = (struct mode_page_header *) buffer;
+ offset = be16_to_cpu(mph->desc_length);
+ size = be16_to_cpu(mph->mode_data_length) + 2;
+
+ buffer[offset + 3] = space;
+ cgc.buflen = size;
+
+ if ((ret = cdrom_mode_select(cdi, &cgc)))
+ return ret;
+
+ printk("cdrom: %s: mrw address space %s selected\n", cdi->name, mrw_address_space[space]);
+ return 0;
+}
+
+static int cdrom_media_erasable(struct cdrom_device_info *cdi)
+{
+ disc_information di;
+
+ if (cdrom_get_disc_info(cdi, &di))
+ return 0;
+
+ return di.erasable;
+}
+
+/*
+ * FIXME: check RO bit
+ */
+static int cdrom_dvdram_open_write(struct cdrom_device_info *cdi)
+{
+ return !cdrom_media_erasable(cdi);
+}
+
+static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
+{
+ disc_information di;
+ int ret;
+
+ /*
+ * always reset to DMA lba space on open
+ */
+ if (cdrom_mrw_set_lba_space(cdi, MRW_LBA_DMA)) {
+ printk("failed setting lba address space\n");
+ return 1;
+ }
+
+ if (cdrom_get_disc_info(cdi, &di))
+ return 1;
+
+ if (!di.erasable) {
+ printk("cdrom not erasable\n");
+ return 1;
+ }
+
+ /*
+ * mrw_status
+ * 0 - not MRW formatted
+ * 1 - MRW bgformat started, but not running or complete
+ * 2 - MRW bgformat in progress
+ * 3 - MRW formatting complete
+ */
+ ret = 0;
+ printk("cdrom open: mrw_status '%s'\n", mrw_format_status[di.mrw_status]);
+ if (!di.mrw_status)
+ ret = 1;
+ else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE && mrw_format_restart)
+ ret = cdrom_mrw_bgformat(cdi, 1);
+
+ return ret;
+}
+
+/*
+ * returns 0 for ok to open write, non-0 to disallow
+ */
+static int cdrom_open_write(struct cdrom_device_info *cdi)
+{
+ int ret = 1;
+
+ if (CDROM_CAN(CDC_MRW_W))
+ ret = cdrom_mrw_open_write(cdi);
+ else if (CDROM_CAN(CDC_DVD_RAM))
+ ret = cdrom_dvdram_open_write(cdi);
+
+ return ret;
+}
+
+static int cdrom_close_write(struct cdrom_device_info *cdi)
+{
+#if 0
+ return cdrom_flush_cache(cdi);
+#else
+ return 0;
+#endif
+}
+
/* We use the open-option O_NONBLOCK to indicate that the
* purpose of opening is only for subsequent ioctl() calls; no device
* integrity checks are performed.
@@ -421,23 +739,32 @@
int ret;
cdinfo(CD_OPEN, "entering cdrom_open\n");
+ cdi->use_count++;
+ ret = -EROFS;
+ if (fp->f_mode & FMODE_WRITE) {
+ printk("cdrom: %s opening for WRITE\n", current->comm);
+ if (!CDROM_CAN(CDC_RAM)) {
+ printk("bzzt\n");
+ goto out;
+ }
+ if (cdrom_open_write(cdi))
+ goto out;
+ }
+
/* if this was a O_NONBLOCK open and we should honor the flags,
* do a quick open without drive/disc integrity checks. */
if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS))
ret = cdi->ops->open(cdi, 1);
- else {
- if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_DVD_RAM))
- return -EROFS;
-
+ else
ret = open_for_data(cdi);
- }
-
- if (!ret) cdi->use_count++;
cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdi->name, cdi->use_count);
/* Do this on open. Don't wait for mount, because they might
not be mounting, but opening with O_NONBLOCK */
check_disk_change(ip->i_bdev);
+ out:
+ if (ret)
+ cdi->use_count--;
return ret;
}
@@ -525,7 +852,7 @@
cdinfo(CD_OPEN, "open device failed.\n");
goto clean_up_and_return;
}
- if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
+ if (CDROM_CAN(CDC_LOCK) && (cdi->options & CDO_LOCK)) {
cdo->lock_door(cdi, 1);
cdinfo(CD_OPEN, "door locked.\n");
}
@@ -603,7 +930,6 @@
return 0;
}
-
/* Admittedly, the logic below could be performed in a nicer way. */
int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
{
@@ -612,17 +938,23 @@
cdinfo(CD_CLOSE, "entering cdrom_release\n");
- if (cdi->use_count > 0)
- cdi->use_count--;
- if (cdi->use_count == 0)
+ if (!--cdi->use_count) {
cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
- if (cdi->use_count == 0 &&
- cdo->capability & CDC_LOCK && !keeplocked) {
- cdinfo(CD_CLOSE, "Unlocking door!\n");
- cdo->lock_door(cdi, 0);
+ if ((cdo->capability & CDC_LOCK) && !keeplocked) {
+ cdinfo(CD_CLOSE, "Unlocking door!\n");
+ cdo->lock_door(cdi, 0);
+ }
}
+
opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
!(fp && fp->f_flags & O_NONBLOCK);
+
+ /*
+ * flush cache on last write release
+ */
+ if (CDROM_CAN(CDC_RAM) && !cdi->use_count && opened_for_data)
+ cdrom_close_write(cdi);
+
cdo->release(cdi);
if (cdi->use_count == 0) { /* last process that closes dev*/
if (opened_for_data &&
@@ -2203,7 +2535,6 @@
return cdo->generic_packet(cdi, &cgc);
}
-
/* return the last written block on the CD-R media. this is for the udf
file system. */
int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written)
@@ -2310,6 +2641,8 @@
EXPORT_SYMBOL(cdrom_mode_select);
EXPORT_SYMBOL(cdrom_mode_sense);
EXPORT_SYMBOL(init_cdrom_command);
+EXPORT_SYMBOL(cdrom_get_media_event);
+EXPORT_SYMBOL(cdrom_is_mrw);
#ifdef CONFIG_SYSCTL
@@ -2406,6 +2739,14 @@
for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
+ pos += sprintf(info+pos, "\nCan read MRW:");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(info+pos, "\t\t%d", CDROM_CAN(CDC_MRW) != 0);
+
+ pos += sprintf(info+pos, "\nCan write MRW:");
+ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+ pos += sprintf(info+pos, "\t\t%d", CDROM_CAN(CDC_MRW_W) != 0);
+
strcpy(info+pos,"\n\n");
return proc_dostring(ctl, write, filp, buffer, lenp);
diff -urN new.orig/drivers/ide/ide-cd.c new/drivers/ide/ide-cd.c
--- new.orig/drivers/ide/ide-cd.c 2004-01-01 18:59:23 +0300
+++ new/drivers/ide/ide-cd.c 2004-01-03 16:55:43 +0300
@@ -291,10 +291,13 @@
* - Use extended sense on drives that support it for
* correctly reporting tray status -- from
* Michael D Johnson <johnsom на orst.edu>
+ * 4.60 Dec 17, 2003 - Add mt rainier support
+ * - Bump timeout for packet commands, matches sr
+ * - Odd stuff
*
*************************************************************************/
-#define IDECD_VERSION "4.59-ac1"
+#define IDECD_VERSION "4.60"
#include <linux/config.h>
#include <linux/module.h>
@@ -774,11 +777,14 @@
if (sense_key == NOT_READY) {
/* Tray open. */
- cdrom_saw_media_change (drive);
+ if (rq_data_dir(rq) == READ) {
+ cdrom_saw_media_change (drive);
- /* Fail the request. */
- printk ("%s: tray open\n", drive->name);
- do_end_request = 1;
+ /* Fail the request. */
+ printk ("%s: tray open\n", drive->name);
+ do_end_request = 1;
+ }
+ /* FIXME: need to timeout writes */
} else if (sense_key == UNIT_ATTENTION) {
/* Media change. */
cdrom_saw_media_change (drive);
@@ -844,9 +850,13 @@
case GPCMD_BLANK:
case GPCMD_FORMAT_UNIT:
case GPCMD_RESERVE_RZONE_TRACK:
- wait = WAIT_CMD;
+ case GPCMD_CLOSE_TRACK:
+ case GPCMD_FLUSH_CACHE:
+ wait = ATAPI_WAIT_PC;
break;
default:
+ if (!(rq->flags & REQ_QUIET))
+ printk(KERN_INFO "ide-cd: cmd 0x%x timed out\n", rq->cmd[0]);
wait = 0;
break;
}
@@ -894,7 +904,7 @@
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
/* packet command */
- ide_execute_command(drive, WIN_PACKETCMD, handler, WAIT_CMD, cdrom_timer_expiry);
+ ide_execute_command(drive, WIN_PACKETCMD, handler, ATAPI_WAIT_PC, cdrom_timer_expiry);
return ide_started;
} else {
/* packet command */
@@ -1167,7 +1177,7 @@
}
/* Done moving data! Wait for another interrupt. */
- ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL);
+ ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL);
return ide_started;
}
@@ -1277,7 +1287,7 @@
(65534 / CD_FRAMESIZE) : 65535);
/* Set up the command */
- rq->timeout = WAIT_CMD;
+ rq->timeout = ATAPI_WAIT_PC;
/* Send the command to the drive and return. */
return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr);
@@ -1286,7 +1296,7 @@
#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
-#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */
+#define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */
static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
{
@@ -1326,7 +1336,7 @@
rq->cmd[0] = GPCMD_SEEK;
put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
- rq->timeout = WAIT_CMD;
+ rq->timeout = ATAPI_WAIT_PC;
return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_intr);
}
@@ -1502,7 +1512,7 @@
}
/* Now we wait for another interrupt. */
- ide_set_handler(drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
+ ide_set_handler(drive, &cdrom_pc_intr, ATAPI_WAIT_PC, cdrom_timer_expiry);
return ide_started;
}
@@ -1511,7 +1521,7 @@
struct request *rq = HWGROUP(drive)->rq;
if (!rq->timeout)
- rq->timeout = WAIT_CMD;
+ rq->timeout = ATAPI_WAIT_PC;
/* Send the command to the drive and return. */
return cdrom_transfer_packet_command(drive, rq, &cdrom_pc_intr);
@@ -1716,11 +1726,8 @@
/*
* If DRQ is clear, the command has completed.
*/
- if ((stat & DRQ_STAT) == 0) {
- if (rq->data_len)
- printk("%s: %u residual after xfer\n", __FUNCTION__, rq->data_len);
+ if ((stat & DRQ_STAT) == 0)
goto end_request;
- }
/*
* check which way to transfer data
@@ -1826,10 +1833,8 @@
}
}
- if (cdrom_decode_status(drive, 0, &stat)) {
- printk("ide-cd: write_intr decode_status bad\n");
+ if (cdrom_decode_status(drive, 0, &stat))
return ide_stopped;
- }
/*
* using dma, transfer is complete now
@@ -1904,7 +1909,7 @@
}
/* re-arm handler */
- ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);
+ ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL);
return ide_started;
}
@@ -1915,7 +1920,7 @@
#if 0 /* the immediate bit */
rq->cmd[1] = 1 << 3;
#endif
- rq->timeout = 2 * WAIT_CMD;
+ rq->timeout = ATAPI_WAIT_PC;
return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr);
}
@@ -1956,7 +1961,7 @@
struct request *rq = HWGROUP(drive)->rq;
if (!rq->timeout)
- rq->timeout = WAIT_CMD;
+ rq->timeout = ATAPI_WAIT_PC;
return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
@@ -2483,7 +2488,7 @@
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
if (cgc->timeout <= 0)
- cgc->timeout = WAIT_CMD;
+ cgc->timeout = ATAPI_WAIT_PC;
/* here we queue the commands from the uniform CD-ROM
layer. the packet must be complete, as we do not
@@ -2688,37 +2693,49 @@
return 0;
}
+/*
+ * add logic to try GET_EVENT command first to check for media and tray
+ * status. this should be supported by newer cd-r/w and all DVD etc
+ * drives
+ */
static
int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct media_event_desc med;
+ struct request_sense sense;
+ int stat;
- if (slot_nr == CDSL_CURRENT) {
- struct request_sense sense;
- int stat = cdrom_check_status(drive, &sense);
- if (stat == 0 || sense.sense_key == UNIT_ATTENTION)
- return CDS_DISC_OK;
+ if (slot_nr != CDSL_CURRENT)
+ return -EINVAL;
- if (sense.sense_key == NOT_READY && sense.asc == 0x04 &&
- sense.ascq == 0x04)
+ stat = cdrom_check_status(drive, &sense);
+ if (!stat || sense.sense_key == UNIT_ATTENTION)
+ return CDS_DISC_OK;
+
+ if (!cdrom_get_media_event(cdi, &med)) {
+ if (med.media_present)
return CDS_DISC_OK;
+ if (med.door_open)
+ return CDS_TRAY_OPEN;
+ }
+ if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
+ return CDS_DISC_OK;
- /*
- * If not using Mt Fuji extended media tray reports,
- * just return TRAY_OPEN since ATAPI doesn't provide
- * any other way to detect this...
- */
- if (sense.sense_key == NOT_READY) {
- if (sense.asc == 0x3a && sense.ascq == 1)
- return CDS_NO_DISC;
- else
- return CDS_TRAY_OPEN;
- }
-
- return CDS_DRIVE_NOT_READY;
+ /*
+ * If not using Mt Fuji extended media tray reports,
+ * just return TRAY_OPEN since ATAPI doesn't provide
+ * any other way to detect this...
+ */
+ if (sense.sense_key == NOT_READY) {
+ if (sense.asc == 0x3a && sense.ascq == 1)
+ return CDS_NO_DISC;
+ else
+ return CDS_TRAY_OPEN;
}
- return -EINVAL;
+
+ return CDS_DRIVE_NOT_READY;
}
static
@@ -2826,7 +2843,8 @@
CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R |
CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
- CDC_GENERIC_PACKET | CDC_MO_DRIVE,
+ CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW |
+ CDC_MRW_W | CDC_RAM,
.generic_packet = ide_cdrom_packet,
};
@@ -2861,6 +2879,10 @@
devinfo->mask |= CDC_CLOSE_TRAY;
if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
devinfo->mask |= CDC_MO_DRIVE;
+ if (!CDROM_CONFIG_FLAGS(drive)->mrw)
+ devinfo->mask |= CDC_MRW;
+ if (!CDROM_CONFIG_FLAGS(drive)->mrw_w)
+ devinfo->mask |= CDC_MRW_W;
return register_cdrom(devinfo);
}
@@ -2881,14 +2903,6 @@
!strcmp(drive->id->model, "WPI CDS-32X")))
size -= sizeof(cap->pad);
- /* we have to cheat a little here. the packet will eventually
- * be queued with ide_cdrom_packet(), which extracts the
- * drive from cdi->handle. Since this device hasn't been
- * registered with the Uniform layer yet, it can't do this.
- * Same goes for cdi->ops.
- */
- cdi->handle = (ide_drive_t *) drive;
- cdi->ops = &ide_cdrom_dops;
init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
@@ -2904,7 +2918,7 @@
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
struct atapi_capabilities_page cap;
- int nslots = 1;
+ int nslots = 1, mrw_write = 0;
if (drive->media == ide_optical) {
CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
@@ -2912,15 +2926,34 @@
return nslots;
}
- if (CDROM_CONFIG_FLAGS(drive)->nec260) {
- CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
- CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
+ if (CDROM_CONFIG_FLAGS(drive)->nec260 ||
+ !strcmp(drive->id->model,"STINGRAY 8422 IDE 8X CD-ROM 7-27-95")) {
+ CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
+ CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
return nslots;
}
+ /*
+ * we have to cheat a little here. the packet will eventually
+ * be queued with ide_cdrom_packet(), which extracts the
+ * drive from cdi->handle. Since this device hasn't been
+ * registered with the Uniform layer yet, it can't do this.
+ * Same goes for cdi->ops.
+ */
+ cdi->handle = (ide_drive_t *) drive;
+ cdi->ops = &ide_cdrom_dops;
+
if (ide_cdrom_get_capabilities(drive, &cap))
return 0;
+ if (!cdrom_is_mrw(cdi, &mrw_write)) {
+ CDROM_CONFIG_FLAGS(drive)->mrw = 1;
+ if (mrw_write) {
+ CDROM_CONFIG_FLAGS(drive)->mrw_w = 1;
+ CDROM_CONFIG_FLAGS(drive)->ram = 1;
+ }
+ }
+
if (cap.lock == 0)
CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
if (cap.eject)
@@ -2933,8 +2966,10 @@
CDROM_CONFIG_FLAGS(drive)->test_write = 1;
if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
CDROM_CONFIG_FLAGS(drive)->dvd = 1;
- if (cap.dvd_ram_write)
+ if (cap.dvd_ram_write) {
CDROM_CONFIG_FLAGS(drive)->dvd_ram = 1;
+ CDROM_CONFIG_FLAGS(drive)->ram = 1;
+ }
if (cap.dvd_r_write)
CDROM_CONFIG_FLAGS(drive)->dvd_r = 1;
if (cap.audio_play)
@@ -2998,6 +3033,9 @@
(CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "",
(CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : "");
+ if (CDROM_CONFIG_FLAGS(drive)->mrw || CDROM_CONFIG_FLAGS(drive)->mrw_w)
+ printk(" CD-MR%s", CDROM_CONFIG_FLAGS(drive)->mrw_w ? "W" : "");
+
if (CDROM_CONFIG_FLAGS(drive)->is_changer)
printk(" changer w/%d slots", nslots);
else
@@ -3105,12 +3143,6 @@
struct cdrom_device_info *cdi = &info->devinfo;
int nslots;
- /*
- * default to read-only always and fix latter at the bottom
- */
- set_disk_ro(drive->disk, 1);
- blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
-
blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
blk_queue_dma_alignment(drive->queue, 3);
@@ -3215,8 +3247,11 @@
nslots = ide_cdrom_probe_capabilities (drive);
- if (CDROM_CONFIG_FLAGS(drive)->dvd_ram || CDROM_CONFIG_FLAGS(drive)->cd_rw)
- set_disk_ro(drive->disk, 0);
+ /*
+ * set correct block size and read-only for non-ram media
+ */
+ set_disk_ro(drive->disk, !CDROM_CONFIG_FLAGS(drive)->ram || CDROM_CONFIG_FLAGS(drive)->cd_rw);
+ blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
#if 0
drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1;
diff -urN new.orig/drivers/ide/ide-cd.h new/drivers/ide/ide-cd.h
--- new.orig/drivers/ide/ide-cd.h 2003-12-30 23:11:52 +0300
+++ new/drivers/ide/ide-cd.h 2004-01-03 16:46:17 +0300
@@ -35,6 +35,11 @@
#define NO_DOOR_LOCKING 0
#endif
+/*
+ * typical timeout for packet command
+ */
+#define ATAPI_WAIT_PC (60 * HZ)
+
/************************************************************************/
#define SECTOR_BITS 9
@@ -75,6 +80,9 @@
__u8 dvd : 1; /* Drive is a DVD-ROM */
__u8 dvd_r : 1; /* Drive can write DVD-R */
__u8 dvd_ram : 1; /* Drive can write DVD-RAM */
+ __u8 mrw : 1; /* drive can read mrw */
+ __u8 mrw_w : 1; /* drive can write mrw */
+ __u8 ram : 1; /* generic WRITE (dvd-ram/mrw) */
__u8 test_write : 1; /* Drive can fake writes */
__u8 supp_disc_present : 1; /* Changer can report exact contents
of slots. */
diff -urN new.orig/drivers/scsi/sr.c new/drivers/scsi/sr.c
--- new.orig/drivers/scsi/sr.c 2004-01-03 16:46:17 +0300
+++ new/drivers/scsi/sr.c 2004-01-03 16:58:39 +0300
@@ -68,7 +68,7 @@
CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \
CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \
CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \
- CDC_MRW|CDC_MRW_R|CDC_RAM)
+ CDC_MRW|CDC_MRW_W|CDC_RAM)
static int sr_probe(struct device *);
static int sr_remove(struct device *);
@@ -693,7 +693,7 @@
static void get_capabilities(struct scsi_cd *cd)
{
unsigned char *buffer;
- int rc, n, mwr_write = 0, mrw = 1;
+ int rc, n, mrw_write = 0, mrw = 1;
struct scsi_mode_data data;
struct scsi_request *SRpnt;
unsigned char cmd[MAX_COMMAND_SIZE];
@@ -767,13 +767,13 @@
return;
}
- if (cdrom_is_mrw(&scsi_CDs[i].cdi, &mrw_write)) {
+ if (cdrom_is_mrw(&cd->cdi, &mrw_write)) {
mrw = 0;
- scsi_CDs[i].cdi.mask |= CDC_MRW;
- scsi_CDs[i].cdi.mask |= CDC_MRW_W;
+ cd->cdi.mask |= CDC_MRW;
+ cd->cdi.mask |= CDC_MRW_W;
}
if (!mrw_write)
- scsi_CDs[i].cdi.mask |= CDC_MRW_W;
+ cd->cdi.mask |= CDC_MRW_W;
n = data.header_length + data.block_descriptor_length;
cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
@@ -798,7 +798,7 @@
if ((buffer[n + 3] & 0x20) == 0) {
/* can't write DVD-RAM media */
cd->cdi.mask |= CDC_DVD_RAM;
- }
+ } else
if ((buffer[n + 3] & 0x10) == 0)
/* can't write DVD-R media */
cd->cdi.mask |= CDC_DVD_R;
@@ -825,8 +825,8 @@
/*
* if DVD-RAM of MRW-W, we are randomly writeable
*/
- if ((scsi_CDs[i].cdi.mask & (CDC_DVD_RAM | CDC_MRW_W)) != (CDC_DVD_RAM | CDC_MRW_W))
- scsi_CDs[i].device->writeable = 1;
+ if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W)) != (CDC_DVD_RAM | CDC_MRW_W))
+ cd->device->writeable = 1;
if (~cd->cdi.mask & (CDC_DVD_RAM | CDC_CD_RW))
/* can write to DVD-RAM or CD-RW */
----------- следующая часть -----------
/*
* Copyright (c) 2002 Jens Axboe <axboe на suse.de>
*
* cdmrw -- utility to manage mt rainier cd drives + media
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <byteswap.h>
#include <sys/ioctl.h>
/*
* you probably want to copy 2.6.0 (patched mrw) to /usr/include/linux
* or change the include path
*/
#include <linux/cdrom.h>
#define INIT_CGC(cgc) memset((cgc), 0, sizeof(struct cdrom_generic_command))
#define FORMAT_TYPE_RESTART 1
#define FORMAT_TYPE_FULL 2
#define LBA_DMA 0
#define LBA_GAA 1
/*
* early mrw drives may use mode page 0x2c still, 0x03 is the official one
*/
#define MRW_MODE_PC_PRE1 0x2c
#define MRW_MODE_PC 0x03
#define UHZ 100
static int format_type, format_force, poll_wait, poll_err, suspend_format;
static int lba_space = -1, mrw_mode_page;
static char mrw_device[256];
static char *lba_spaces[] = { "DMA", "GAA" };
void dump_cgc(struct cdrom_generic_command *cgc)
{
struct request_sense *sense = cgc->sense;
int i;
printf("cdb: ");
for (i = 0; i < 12; i++)
printf("%02x ", cgc->cmd[i]);
printf("\n");
printf("buffer (%d): ", cgc->buflen);
for (i = 0; i < cgc->buflen; i++)
printf("%02x ", cgc->buffer[i]);
printf("\n");
if (!sense)
return;
printf("sense: %02x.%02x.%02x\n", sense->sense_key, sense->asc, sense->ascq);
}
/*
* issue packet command (blocks until it has completed)
*/
int wait_cmd(int fd, struct cdrom_generic_command *cgc, void *buffer,
int len, int ddir, int timeout, int quiet)
{
struct request_sense sense;
int ret;
memset(&sense, 0, sizeof(sense));
cgc->timeout = timeout;
cgc->buffer = buffer;
cgc->buflen = len;
cgc->data_direction = ddir;
cgc->sense = &sense;
cgc->quiet = 0;
ret = ioctl(fd, CDROM_SEND_PACKET, cgc);
if (ret == -1 && !quiet) {
perror("ioctl");
dump_cgc(cgc);
}
return ret;
}
int start_bg_format(int fd, int new)
{
struct cdrom_generic_command cgc;
unsigned char buffer[12];
INIT_CGC(&cgc);
memset(buffer, 0, sizeof(buffer));
cgc.cmd[0] = GPCMD_FORMAT_UNIT;
cgc.cmd[1] = (1 << 4) | 1;
buffer[1] = 1 << 1;
buffer[3] = 8;
buffer[4] = 0xff;
buffer[5] = 0xff;
buffer[6] = 0xff;
buffer[7] = 0xff;
buffer[8] = 0x24 << 2;
buffer[11] = !new;
return wait_cmd(fd, &cgc, buffer, sizeof(buffer), CGC_DATA_WRITE, 121 * UHZ, 0);
}
/*
* instantiate a format, if appropriate
*/
int mrw_format(int fd, int media_status)
{
if (media_status == CDM_MRW_BGFORMAT_ACTIVE) {
printf("%s: back ground format already active\n", mrw_device);
return 1;
} else if (media_status == CDM_MRW_BGFORMAT_COMPLETE && !format_force) {
printf("%s: disc is already mrw formatted\n", mrw_device);
return 1;
}
if (format_type == FORMAT_TYPE_RESTART && media_status != CDM_MRW_BGFORMAT_INACTIVE) {
printf("%s: can't restart format, need full\n", mrw_device);
return 1;
}
return start_bg_format(fd, format_type == FORMAT_TYPE_FULL);
}
int mrw_format_suspend(int fd, int media_status)
{
struct cdrom_generic_command cgc;
if (media_status != CDM_MRW_BGFORMAT_ACTIVE) {
printf("%s: can't suspend, format not running\n", mrw_device);
return 1;
}
printf("%s: suspending back ground format: ", mrw_device);
INIT_CGC(&cgc);
cgc.cmd[0] = GPCMD_CLOSE_TRACK;
cgc.cmd[1] = 0; /* IMMED */
cgc.cmd[2] = 1 << 1;
if (wait_cmd(fd, &cgc, NULL, 0, CGC_DATA_NONE, 300 * UHZ, 0)) {
printf("failed\n");
return 1;
}
printf("done\n");
return 0;
}
int get_media_event(int fd)
{
struct cdrom_generic_command cgc;
unsigned char buffer[8];
int ret;
INIT_CGC(&cgc);
memset(buffer, 0, sizeof(buffer));
cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
cgc.cmd[1] = 1;
cgc.cmd[4] = 16;
cgc.cmd[8] = sizeof(buffer);
ret = wait_cmd(fd, &cgc, buffer, sizeof(buffer), CGC_DATA_READ, 10*UHZ, 0);
if (ret < 0) {
perror("GET_EVENT");
return ret;
}
return buffer[4] & 0xf;
}
int get_progress(int fd)
{
struct cdrom_generic_command cgc;
struct request_sense sense;
int progress;
INIT_CGC(&cgc);
memset(&sense, 0, sizeof(sense));
cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
cgc.sense = &sense;
(void) wait_cmd(fd, &cgc, NULL, 0, CGC_DATA_NONE, 10 * UHZ, 0);
printf("progress: ");
if (sense.sks[0] & 0x80) {
progress = (sense.sks[1] << 8) + sense.sks[2];
fprintf(stderr, "%d%%\r", progress);
} else
printf("no progress indicator\n");
return 0;
}
int get_format_progress(int fd)
{
struct cdrom_generic_command cgc;
struct request_sense sense;
#if 0
if (poll_err)
return 0;
#endif
INIT_CGC(&cgc);
memset(&sense, 0, sizeof(sense));
cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
cgc.sense = &sense;
if (wait_cmd(fd, &cgc, NULL, 0, CGC_DATA_NONE, 10 * UHZ, 0)) {
printf("%s: TUR failed\n", mrw_device);
return 0;
}
/*
* all mrw drives should support progress indicator, but you never
* know...
*/
if (!(sense.sks[0] & 0x80)) {
printf("drive fails to support progress indicator\n");
poll_err = 1;
//return 0;
}
return (sense.sks[1] << 8) + sense.sks[2];
}
/*
* return mrw media status bits from disc info or -1 on failure
*/
int get_mrw_media_status(int fd)
{
struct cdrom_generic_command cgc;
disc_information di;
INIT_CGC(&cgc);
cgc.cmd[0] = GPCMD_READ_DISC_INFO;
cgc.cmd[8] = sizeof(di);
if (wait_cmd(fd, &cgc, &di, sizeof(di), CGC_DATA_READ, UHZ, 0)) {
printf("read disc info failed\n");
return -1;
}
return di.mrw_status;
}
int poll_events(int fd)
{
int event, quit, first, progress, media_status;
quit = 0;
first = 1;
do {
event = get_media_event(fd);
if (event < 0)
break;
switch (event) {
case 0:
if (first)
printf("no media change\n");
break;
case 1:
printf("eject request\n");
if ((media_status = get_mrw_media_status(fd)) == -1)
break;
if (media_status == CDM_MRW_BGFORMAT_ACTIVE)
mrw_format_suspend(fd, media_status);
quit = 1;
break;
case 2:
printf("new media\n");
break;
case 3:
printf("media removal\n");
quit = 1;
break;
case 4:
printf("media change\n");
break;
case 5:
printf("bgformat complete!\n");
quit = 1;
break;
case 6:
printf("bgformat automatically restarted\n");
break;
default:
printf("unknown media event (%d)\n", event);
break;
}
if (!quit) {
first = 0;
progress = get_progress(fd);
if (event)
continue;
sleep(2);
}
} while (!quit);
return event;
}
/*
* issue GET_CONFIGURATION and check for the mt rainier profile
*/
int check_for_mrw(int fd)
{
struct mrw_feature_desc *mfd;
struct cdrom_generic_command cgc;
char buffer[16];
INIT_CGC(&cgc);
cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
cgc.cmd[3] = CDF_MRW;
cgc.cmd[8] = sizeof(buffer);
if (wait_cmd(fd, &cgc, buffer, sizeof(buffer), CGC_DATA_READ, UHZ, 1))
return 1;
mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
return !mfd->write;
}
int __get_lba_space(int fd, int pc, char *buffer, int size)
{
struct cdrom_generic_command cgc;
INIT_CGC(&cgc);
cgc.cmd[0] = GPCMD_MODE_SENSE_10;
cgc.cmd[2] = pc | (0 << 6);
cgc.cmd[8] = size;
if (wait_cmd(fd, &cgc, buffer, size, CGC_DATA_READ, UHZ, 1))
return 1;
return 0;
}
/*
* return LBA_DMA or LBA_GAA, -1 on failure
*/
int get_lba_space(int fd)
{
struct mode_page_header *mph;
char buffer[32];
int offset;
if (__get_lba_space(fd, mrw_mode_page, buffer, sizeof(buffer)))
return -1;
mph = (struct mode_page_header *) buffer;
offset = sizeof(*mph) + bswap_16(mph->desc_length);
/*
* LBA space bit is bit 0 in byte 3 of the mrw mode page
*/
return buffer[offset + 3] & 1;
}
int probe_mrw_mode_page(int fd)
{
char buffer[32];
mrw_mode_page = -1;
if (!__get_lba_space(fd, MRW_MODE_PC, buffer, sizeof(buffer)))
mrw_mode_page = MRW_MODE_PC;
else if (!__get_lba_space(fd, MRW_MODE_PC_PRE1, buffer, sizeof(buffer)))
mrw_mode_page = MRW_MODE_PC_PRE1;
if (mrw_mode_page == MRW_MODE_PC_PRE1)
printf("%s: still using deprecated mrw mode page\n",mrw_device);
return mrw_mode_page;
}
int switch_lba_space(int fd, int lba_space)
{
struct cdrom_generic_command cgc;
struct mode_page_header *mph;
int cur_space, offset, size;
char buffer[32];
if (__get_lba_space(fd, mrw_mode_page, buffer, sizeof(buffer)))
return 1;
mph = (struct mode_page_header *) buffer;
offset = sizeof(*mph) + bswap_16(mph->desc_length);
cur_space = buffer[offset + 3] & 1;
if (cur_space == lba_space)
return 0;
/*
* mode data length doesn't include its own space
*/
size = bswap_16(mph->mode_data_length) + 2;
/*
* init command and set the required lba space
*/
INIT_CGC(&cgc);
cgc.cmd[0] = GPCMD_MODE_SELECT_10;
cgc.cmd[8] = size;
buffer[offset + 3] = lba_space;
if (wait_cmd(fd, &cgc, buffer, size, CGC_DATA_WRITE, UHZ, 0))
return 1;
return 0;
}
void print_mrw_status(int media_status)
{
switch (media_status) {
case CDM_MRW_NOTMRW:
printf("not a mrw formatted disc\n");
break;
case CDM_MRW_BGFORMAT_INACTIVE:
printf("mrw format inactive and not complete\n");
break;
case CDM_MRW_BGFORMAT_ACTIVE:
printf("mrw format running\n");
break;
case CDM_MRW_BGFORMAT_COMPLETE:
printf("disc is mrw formatted\n");
break;
}
}
void print_options(const char *prg)
{
printf("%s: options:\n", prg);
printf("\t-d:\t<device>\n");
printf("\t-f:\t<{restart, full} format type\n");
printf("\t-F:\tforce format\n");
printf("\t-s:\tsuspend format\n");
printf("\t-p:\tpoll for format completion\n");
}
void get_options(int argc, char *argv[])
{
char c;
strcpy(mrw_device, "/dev/cdrom");
while ((c = getopt(argc, argv, "d:f:Fpsl:")) != EOF) {
switch (c) {
case 'd':
strcpy(mrw_device, optarg);
break;
case 'f':
if (!strcmp(optarg, "full"))
format_type = FORMAT_TYPE_FULL;
else if (!strcmp(optarg, "restart"))
format_type = FORMAT_TYPE_RESTART;
else
printf("%s: invalid format type %s\n", argv[0], optarg);
break;
case 'F':
format_force = 1;
break;
case 'p':
poll_wait = 1;
break;
case 's':
suspend_format = 1;
break;
case 'l':
if (!strcmp(optarg, "gaa"))
lba_space = LBA_GAA;
else if (!strcmp(optarg, "dma"))
lba_space = LBA_DMA;
else
printf("%s: invalid address space %s\n", argv[0], optarg);
break;
default:
if (optarg)
printf("%s: unknown option '%s'\n", argv[0], optarg);
print_options(argv[0]);
exit(1);
}
}
}
int main(int argc, char *argv[])
{
int fd, media_status, progress;
if (argc == 1) {
print_options(argv[0]);
return 1;
}
get_options(argc, argv);
// fd = concat(mrw_device, O_RDONLY | O_NONBLOCK);
fd = open(mrw_device, O_RDONLY | O_NONBLOCK);
if (fd == -1) {
perror("open");
return 1;
}
if (check_for_mrw(fd)) {
printf("%s: %s is not a mrw drive or mrw reader\n", argv[0], mrw_device);
return 1;
}
if ((media_status = get_mrw_media_status(fd)) == -1) {
printf("%s: failed to retrieve media status\n", argv[0]);
return 1;
}
print_mrw_status(media_status);
if (probe_mrw_mode_page(fd) == -1) {
printf("%s: failed to probe mrw mode page\n", mrw_device);
return 1;
}
if (lba_space != -1) {
if (switch_lba_space(fd, lba_space)) {
printf("%s: failed switching lba space\n", mrw_device);
return 1;
}
}
printf("LBA space: %s\n", lba_spaces[get_lba_space(fd)]);
if (media_status == CDM_MRW_BGFORMAT_ACTIVE) {
progress = get_format_progress(fd);
printf("%s: back ground format %d%% complete\n", mrw_device, progress);
}
if (format_type) {
if (mrw_format(fd, media_status))
return 1;
} else if (suspend_format)
mrw_format_suspend(fd, media_status);
if (poll_wait)
poll_events(fd);
return 0;
}
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя : =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Тип : text/ignore
Размер : 40 байтов
Описание: =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Url : <http://lists.altlinux.org/pipermail/devel/attachments/20040103/bc29c93b/attachment-0001.bin>
Подробная информация о списке рассылки Devel