From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Date: Sat, 3 Jan 2004 22:02:23 +0300 From: "Konstantin A. Lepikhov" To: ALT Linux Devel Mailing List Message-ID: <20040103190127.GA17075@lks.home> Mail-Followup-To: ALT Linux Devel Mailing List Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="24zk1gE8NUlDmwG9" Content-Disposition: inline User-Agent: Mutt/1.4.1i X-Operation-System: ALT Linux Sisyphus (20031219) 2.6.1-std26-up-alt2.lks0.4 Content-Transfer-Encoding: 7bit Subject: [devel] feat-drivers-mtrw patch for 2.6.1-rc1 X-BeenThere: devel@altlinux.ru X-Mailman-Version: 2.1.3 Precedence: list Reply-To: ALT Devel discussion list List-Id: ALT Devel discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 03 Jan 2004 19:01:46 -0000 Archived-At: List-Archive: List-Post: --24zk1gE8NUlDmwG9 Content-Type: text/plain; charset=koi8-r Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi! =EB =D3=CF=D6=C1=CC=C5=CE=C9=C0, =D7 firmware =C4=CC=D1 =CD=CF=C5=CA TOSH= IBA SD-1312 =CE=C5=D4 =D0=CF=C4=C4=C5=D2=D6=CB=C9 mt, =D4=C1=CB =DE=D4=CF =D0=D2=CF=D7=C5=D2=C9=D4=D8 =CD=CE=C5 =C5=C7=CF =D4=C1=CB =C9 =CE=C5 =D5=C4= =C1=CC=CF=D3=D8 :( =ED=CF=D6=C5=D4 =C2=D9=D4=D8 =CB=CF=CD=D5-=D4=CF =C9=DA= =D5=DE=C1=D3=D4=CE=C9=CB=CF=D7 devel =C9=CC=C9 kernel-devel =C2=D5=C4=C5=D4 =C9=CE=D4=C5=D2=C5=D3=CE=CF = =D0=D2=CF=D7=C5=D2=C9=D4=D8 =DC=D4=CF=D4 =D0=C1=D4=DE? =F7=D2=CF=C4=C5 =C2= =D9 =D1=C4=D2=CF =D3 =CE=C9=CD =D7=D0=CF=CC=CE=C5 =D2=C1=C2=CF=DE=C5=C5 + =CF=CE =CE=C5 =CB= =CF=CE=C6=CC=C9=CB=D4=D5=C5=D4 =D3 pktcdvd. =F4=C1=CB =D6=C5 =D0=D2=C9=CC= =C1=C7=C1=C0 =C9 =CF=C2=CE=CF=D7=CC=C5=CE=CE=D5=C0 Jens'=CF=CD cdmrw.c --=20 WBR, Konstantin chat with =3D=3D>ICQ: 109916175 Lepikhov, speak to =3D=3D>JID: lakostis@jabber.org aka L.A. Kostis write to =3D=3D>mailto:lakostis@pisem.net.nospam ...The information is like the bank... (c) EC8OR --24zk1gE8NUlDmwG9 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mtrw-2.6.1-patch" 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 -- Use quiet bit on packet commands not known to work + 3.20 Dec 17, 2003 - Jens Axboe + -- 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 + * 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 #include @@ -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 */ --24zk1gE8NUlDmwG9 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="cdmrw.c" /* * Copyright (c) 2002 Jens Axboe * * 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 #include #include #include #include #include #include /* * you probably want to copy 2.6.0 (patched mrw) to /usr/include/linux * or change the include path */ #include #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\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; } --24zk1gE8NUlDmwG9 Content-Type: text/ignore; charset=US-ASCII; name="SecurityCheck.txt" Content-Disposition: inline Checked by RAV - it's better than KAV! --24zk1gE8NUlDmwG9--