diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c --- /opt/kernel/linux-2.4.19-pre4/drivers/cdrom/cdrom.c Fri Nov 16 19:14:08 2001 +++ linux/drivers/cdrom/cdrom.c Tue Mar 26 09:49:44 2002 @@ -228,10 +228,16 @@ 3.12 Oct 18, 2000 - Jens Axboe -- Use quiet bit on packet commands not known to work + 3.20 Sep 24, 2001 - 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 2001/09/24" /* 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: */ @@ -266,7 +272,6 @@ #include #include -#include #include /* used to tell the module to turn on full debugging messages */ @@ -279,11 +284,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...) \ @@ -321,6 +340,10 @@ int cdrom_get_last_written(kdev_t dev, long *last_written); int cdrom_get_next_writable(kdev_t dev, long *next_writable); +static int __cdrom_get_di(struct cdrom_device_info *cdi, disc_information *di); + +static int cdrom_mrw_exit(struct cdrom_device_info *cdi); + #ifdef CONFIG_SYSCTL static void cdrom_sysctl_register(void); #endif /* CONFIG_SYSCTL */ @@ -348,13 +371,14 @@ return -1; 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); @@ -379,6 +403,9 @@ if (check_media_type==1) cdi->options |= (int) CDO_CHECK_TYPE; + if (CDROM_CAN(CDC_MRW_W)) + cdi->exit = cdrom_mrw_exit; + if (!devfs_handle) devfs_handle = devfs_mk_dir (NULL, "cdroms", NULL); cdi->number = devfs_alloc_unique_number (&cdrom_numspace); @@ -399,9 +426,12 @@ devfs_auto_unregister (cdi->de, slave); } } + 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 @@ -417,18 +447,26 @@ return -1; prev = NULL; + spin_lock(&cdrom_lock); cdi = topCdromPtr; while (cdi != NULL && cdi->dev != unreg->dev) { 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--; devfs_unregister (cdi->de); devfs_dealloc_unique_number (&cdrom_numspace, cdi->number); @@ -440,13 +478,292 @@ { struct cdrom_device_info *cdi; + spin_lock(&cdrom_lock); cdi = topCdromPtr; while (cdi != NULL && cdi->dev != dev) cdi = cdi->next; + spin_unlock(&cdrom_lock); return cdi; } +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_di(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_di(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 GAA lba space on open + */ + if (cdrom_mrw_set_lba_space(cdi, MRW_LBA_GAA)) + return 1; + + if (__cdrom_get_di(cdi, &di)) + return 1; + + if (!di.erasable) + 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; + + 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); + else + ret = 1; + + 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. @@ -465,8 +782,15 @@ if ((cdi = cdrom_find_device(dev)) == NULL) return -ENODEV; - if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_DVD_RAM)) - return -EROFS; + 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)) + 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. */ @@ -475,12 +799,13 @@ 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(dev); +out: + if (ret) + cdi->use_count--; return ret; } @@ -491,6 +816,7 @@ struct cdrom_device_ops *cdo = cdi->ops; tracktype tracks; cdinfo(CD_OPEN, "entering open_for_data\n"); + /* Check if the driver can report drive status. If it can, we can do clever things. If it can't, well, we at least tried! */ if (cdo->drive_status != NULL) { @@ -568,7 +894,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"); } @@ -646,7 +972,6 @@ return 0; } - /* Admittedly, the logic below could be performed in a nicer way. */ int cdrom_release(struct inode *ip, struct file *fp) { @@ -657,17 +982,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 && @@ -1902,10 +2233,24 @@ } } + /* + * queue command and wait for it to complete + */ ret = cdi->ops->generic_packet(cdi, cgc); - __copy_to_user(usense, cgc->sense, sizeof(*usense)); + + /* + * always copy back sense, command need not have failed for it to + * contain useful info + */ + if (usense) + __copy_to_user(usense, cgc->sense, sizeof(*usense)); + + /* + * this really needs to be modified to copy back good bytes + */ if (!ret && cgc->data_direction == CGC_DATA_READ) __copy_to_user(ubuf, cgc->buffer, cgc->buflen); + kfree(cgc->buffer); return ret; } @@ -2234,10 +2579,8 @@ return cdo->generic_packet(cdi, &cgc); } -/* requires CD R/RW */ -int cdrom_get_disc_info(kdev_t dev, disc_information *di) +static int __cdrom_get_di(struct cdrom_device_info *cdi, disc_information *di) { - struct cdrom_device_info *cdi = cdrom_find_device(dev); struct cdrom_device_ops *cdo = cdi->ops; struct cdrom_generic_command cgc; int ret; @@ -2264,6 +2607,14 @@ return cdo->generic_packet(cdi, &cgc); } +/* requires CD R/RW */ +int cdrom_get_disc_info(kdev_t dev, disc_information *di) +{ + struct cdrom_device_info *cdi = cdrom_find_device(dev); + + return __cdrom_get_di(cdi, di); +} + /* return the last written block on the CD-R media. this is for the udf file system. */ @@ -2379,6 +2730,8 @@ EXPORT_SYMBOL(cdrom_mode_sense); EXPORT_SYMBOL(init_cdrom_command); EXPORT_SYMBOL(cdrom_find_device); +EXPORT_SYMBOL(cdrom_get_media_event); +EXPORT_SYMBOL(cdrom_is_mrw); #ifdef CONFIG_SYSCTL @@ -2475,6 +2828,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 -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c --- /opt/kernel/linux-2.4.19-pre4/drivers/ide/ide-cd.c Tue Mar 26 09:52:55 2002 +++ linux/drivers/ide/ide-cd.c Mon Mar 25 17:40:39 2002 @@ -292,9 +292,13 @@ * correctly reporting tray status -- from * Michael D Johnson * + * 4.60 Mar 21, 2002 - Add mt rainier support + * - Bump timeout value for packet commands + * - Odd stuff + * *************************************************************************/ -#define IDECD_VERSION "4.59" +#define IDECD_VERSION "4.60" #include #include @@ -694,12 +698,17 @@ 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 (!pc->quiet) + printk("ide-cd: cmd 0x%x timed out\n",pc->c[0]); wait = 0; break; } + return wait; } @@ -745,7 +754,7 @@ (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); + ide_set_handler (drive, handler, ATAPI_WAIT_PC, cdrom_timer_expiry); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ return ide_started; } else { @@ -1009,7 +1018,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; } @@ -1125,16 +1134,15 @@ pc.c[7] = (nframes >> 8); pc.c[8] = (nframes & 0xff); put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); - pc.timeout = WAIT_CMD; + pc.timeout = ATAPI_WAIT_PC; /* Send the command to the drive and return. */ return cdrom_transfer_packet_command(drive, &pc, &cdrom_read_intr); } - #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) { @@ -1178,7 +1186,7 @@ pc.c[0] = GPCMD_SEEK; put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); - pc.timeout = WAIT_CMD; + pc.timeout = ATAPI_WAIT_PC; return cdrom_transfer_packet_command(drive, &pc, &cdrom_seek_intr); } @@ -1192,26 +1200,6 @@ return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation); } -static inline int cdrom_merge_requests(struct request *rq, struct request *nxt) -{ - int ret = 1; - - /* - * partitions not really working, but better check anyway... - */ - if (rq->cmd == nxt->cmd && rq->rq_dev == nxt->rq_dev) { - rq->nr_sectors += nxt->nr_sectors; - rq->hard_nr_sectors += nxt->nr_sectors; - rq->bhtail->b_reqnext = nxt->bh; - rq->bhtail = nxt->bhtail; - list_del(&nxt->queue); - blkdev_release_request(nxt); - ret = 0; - } - - return ret; -} - /* * the current request will always be the first one on the list */ @@ -1229,13 +1217,31 @@ break; nxt = blkdev_entry_to_request(entry); + + if (rq->cmd != nxt->cmd) + break; + if (rq->rq_dev != nxt->rq_dev) + break; if (rq->sector + rq->nr_sectors != nxt->sector) break; - else if (rq->nr_sectors + nxt->nr_sectors > SECTORS_MAX) + if (rq->nr_sectors + nxt->nr_sectors >= SECTORS_MAX) break; - - if (cdrom_merge_requests(rq, nxt)) + if (rq->nr_segments + nxt->nr_segments > PRD_ENTRIES) break; + + /* + * ok to merge them + */ + rq->nr_sectors += nxt->nr_sectors; + rq->hard_nr_sectors += nxt->nr_sectors; + rq->bhtail->b_reqnext = nxt->bh; + rq->bhtail = nxt->bhtail; + + /* + * release nxt + */ + blkdev_dequeue_request(nxt); + blkdev_release_request(nxt); } spin_unlock_irqrestore(&io_request_lock, flags); @@ -1399,7 +1405,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; } @@ -1410,7 +1416,7 @@ struct packet_command *pc = (struct packet_command *)rq->buffer; if (!pc->timeout) - pc->timeout = WAIT_CMD; + pc->timeout = ATAPI_WAIT_PC; /* Send the command to the drive and return. */ return cdrom_transfer_packet_command(drive, pc, &cdrom_pc_intr); @@ -1624,7 +1630,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; } @@ -1649,7 +1655,7 @@ pc.c[7] = (nframes >> 8) & 0xff; pc.c[8] = nframes & 0xff; put_unaligned(cpu_to_be32(frame), (unsigned int *)&pc.c[2]); - pc.timeout = 2 * WAIT_CMD; + pc.timeout = ATAPI_WAIT_PC; return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr); } @@ -2188,7 +2194,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 @@ -2200,6 +2206,7 @@ pc.quiet = cgc->quiet; pc.timeout = cgc->timeout; pc.sense = cgc->sense; + return cgc->stat = cdrom_queue_packet_command(drive, &pc); } @@ -2385,37 +2392,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) - return CDS_DISC_OK; + 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 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; - } + if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04) + return CDS_DISC_OK; - 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 @@ -2523,7 +2542,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_GENERIC_PACKET | CDC_MRW | CDC_MRW_W | + CDC_RAM, generic_packet: ide_cdrom_packet, }; @@ -2558,6 +2578,10 @@ devinfo->mask |= CDC_PLAY_AUDIO; if (!CDROM_CONFIG_FLAGS (drive)->close_tray) devinfo->mask |= CDC_CLOSE_TRAY; + if (!CDROM_CONFIG_FLAGS(drive)->mrw) + devinfo->mask |= CDC_MRW; + if (!CDROM_CONFIG_FLAGS(drive)->mrw_w) + devinfo->mask |= CDC_MRW_W; devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT, HWIF(drive)->major, minor, @@ -2585,14 +2609,6 @@ 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); @@ -2608,17 +2624,36 @@ 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 (CDROM_CONFIG_FLAGS (drive)->nec260) { + 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) @@ -2631,8 +2666,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) @@ -2693,6 +2730,10 @@ (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 @@ -2726,14 +2767,9 @@ struct cdrom_info *info = drive->driver_data; struct cdrom_device_info *cdi = &info->devinfo; int minor = drive->select.b.unit << PARTN_BITS; + kdev_t cd_dev = MKDEV(HWIF(drive)->major, minor); int nslots; - /* - * default to read-only always and fix latter at the bottom - */ - set_device_ro(MKDEV(HWIF(drive)->major, minor), 1); - set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE); - drive->special.all = 0; drive->ready_stat = 0; @@ -2850,8 +2886,11 @@ nslots = ide_cdrom_probe_capabilities (drive); - if (CDROM_CONFIG_FLAGS(drive)->dvd_ram) - set_device_ro(MKDEV(HWIF(drive)->major, minor), 0); + /* + * set correct block size and read-only for non-ram media + */ + set_blocksize(cd_dev, CD_FRAMESIZE); + set_device_ro(cd_dev, !CDROM_CONFIG_FLAGS(drive)->ram); if (ide_cdrom_register (drive, nslots)) { printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/drivers/ide/ide-cd.h linux/drivers/ide/ide-cd.h --- /opt/kernel/linux-2.4.19-pre4/drivers/ide/ide-cd.h Tue Mar 26 09:52:55 2002 +++ linux/drivers/ide/ide-cd.h Tue Mar 26 09:55:15 2002 @@ -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 -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/drivers/ide/ide-dma.c linux/drivers/ide/ide-dma.c --- /opt/kernel/linux-2.4.19-pre4/drivers/ide/ide-dma.c Tue Mar 26 09:52:55 2002 +++ linux/drivers/ide/ide-dma.c Mon Mar 25 08:42:18 2002 @@ -204,25 +204,6 @@ #endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ /* - * Our Physical Region Descriptor (PRD) table should be large enough - * to handle the biggest I/O request we are likely to see. Since requests - * can have no more than 256 sectors, and since the typical blocksize is - * two or more sectors, we could get by with a limit of 128 entries here for - * the usual worst case. Most requests seem to include some contiguous blocks, - * further reducing the number of table entries required. - * - * The driver reverts to PIO mode for individual requests that exceed - * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling - * 100% of all crazy scenarios here is not necessary. - * - * As it turns out though, we must allocate a full 4KB page for this, - * so the two PRD tables (ide0 & ide1) will each get half of that, - * allowing each to have about 256 entries (8 bytes each) from this. - */ -#define PRD_BYTES 8 -#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES)) - -/* * dma_intr() is the handler for disk read/write DMA interrupts */ ide_startstop_t ide_dma_intr (ide_drive_t *drive) diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- /opt/kernel/linux-2.4.19-pre4/drivers/scsi/sr.c Tue Mar 26 09:52:56 2002 +++ linux/drivers/scsi/sr.c Tue Mar 26 08:00:47 2002 @@ -128,7 +128,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_DVD_RAM | CDC_GENERIC_PACKET | CDC_MRW | + CDC_MRW_W | CDC_RAM, generic_packet: sr_packet, }; @@ -690,7 +691,7 @@ { unsigned char cmd[6]; unsigned char *buffer; - int rc, n; + int rc, n, mrw_write = 0, mrw = 1; static char *loadmech[] = { @@ -716,7 +717,7 @@ cmd[2] = 0x2a; cmd[4] = 128; cmd[3] = cmd[5] = 0; - rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL, 0); if (rc) { /* failed, drive doesn't have capabilities mode page */ @@ -728,6 +729,15 @@ printk("sr%i: scsi-1 drive\n", i); return; } + + if (cdrom_is_mrw(&scsi_CDs[i].cdi, &mrw_write)) { + mrw = 0; + scsi_CDs[i].cdi.mask |= CDC_MRW; + scsi_CDs[i].cdi.mask |= CDC_MRW_W; + } + if (!mrw_write) + scsi_CDs[i].cdi.mask |= CDC_MRW_W; + n = buffer[3] + 4; scsi_CDs[i].cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176; scsi_CDs[i].readcd_known = 1; @@ -751,8 +761,6 @@ if ((buffer[n + 3] & 0x20) == 0) { /* can't write DVD-RAM media */ scsi_CDs[i].cdi.mask |= CDC_DVD_RAM; - } else { - scsi_CDs[i].device->writeable = 1; } if ((buffer[n + 3] & 0x10) == 0) /* can't write DVD-R media */ @@ -777,7 +785,14 @@ /*else I don't think it can close its tray scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; */ + /* + * 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; + scsi_free(buffer, 512); + } /* @@ -792,7 +807,7 @@ if (device->scsi_level <= SCSI_2) cgc->cmd[1] |= device->lun << 5; - cgc->stat = sr_do_ioctl(MINOR(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense); + cgc->stat = sr_do_ioctl(MINOR(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense, cgc->timeout); return cgc->stat; } diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/drivers/scsi/sr.h linux/drivers/scsi/sr.h --- /opt/kernel/linux-2.4.19-pre4/drivers/scsi/sr.h Fri Jul 20 06:18:31 2001 +++ linux/drivers/scsi/sr.h Mon Mar 25 17:46:24 2002 @@ -36,7 +36,7 @@ extern Scsi_CD *scsi_CDs; -int sr_do_ioctl(int, unsigned char *, void *, unsigned, int, int, struct request_sense *); +int sr_do_ioctl(int, unsigned char *, void *, unsigned, int, int, struct request_sense *, int); int sr_lock_door(struct cdrom_device_info *, int); int sr_tray_move(struct cdrom_device_info *, int); diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c --- /opt/kernel/linux-2.4.19-pre4/drivers/scsi/sr_ioctl.c Tue Mar 26 09:52:56 2002 +++ linux/drivers/scsi/sr_ioctl.c Mon Mar 25 17:47:12 2002 @@ -68,14 +68,14 @@ sr_cmd[6] = trk1_te.cdte_addr.msf.minute; sr_cmd[7] = trk1_te.cdte_addr.msf.second; sr_cmd[8] = trk1_te.cdte_addr.msf.frame; - return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); + return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL, 0); } /* We do our own retries because we want to know what the specific error code is. Normally the UNIT_ATTENTION code will automatically clear after one error */ -int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense) +int sr_do_ioctl(int target, unsigned char *sr_cmd, void *buffer, unsigned buflength, int quiet, int readwrite, struct request_sense *sense, int timeout) { Scsi_Request *SRpnt; Scsi_Device *SDev; @@ -83,6 +83,9 @@ int result, err = 0, retries = 0; char *bounce_buffer; + if (!timeout) + timeout = IOCTL_TIMEOUT; + SDev = scsi_CDs[target].device; SRpnt = scsi_allocate_request(scsi_CDs[target].device); if (!SRpnt) { @@ -109,7 +112,7 @@ scsi_wait_req(SRpnt, (void *) sr_cmd, (void *) buffer, buflength, - IOCTL_TIMEOUT, IOCTL_RETRIES); + timeout, IOCTL_RETRIES); req = &SRpnt->sr_request; if (SRpnt->sr_buffer && req->buffer && SRpnt->sr_buffer != req->buffer) { @@ -198,7 +201,7 @@ sr_cmd[1] = (scsi_CDs[minor].device->scsi_level <= SCSI_2) ? ((scsi_CDs[minor].device->lun) << 5) : 0; sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; - return sr_do_ioctl(minor, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL); + return sr_do_ioctl(minor, sr_cmd, NULL, 0, 1, SCSI_DATA_NONE, NULL, 0); } int sr_tray_move(struct cdrom_device_info *cdi, int pos) @@ -211,7 +214,7 @@ sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0; sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */ ; - return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); + return sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL, 0); } int sr_lock_door(struct cdrom_device_info *cdi, int lock) @@ -289,7 +292,7 @@ sr_cmd[8] = 24; sr_cmd[9] = 0; - result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL); + result = sr_do_ioctl(MINOR(cdi->dev), sr_cmd, buffer, 24, 0, SCSI_DATA_READ, NULL, 0); memcpy(mcn->medium_catalog_number, buffer + 9, 13); mcn->medium_catalog_number[13] = 0; @@ -319,7 +322,7 @@ sr_cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */ sr_cmd[3] = speed & 0xff; /* LSB */ - if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL)) + if (sr_do_ioctl(MINOR(cdi->dev), sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL, 0)) return -EIO; return 0; } @@ -349,7 +352,7 @@ sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0; sr_cmd[8] = 12; /* LSB of length */ - result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); + result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1, SCSI_DATA_READ, NULL, 0); tochdr->cdth_trk0 = buffer[2]; tochdr->cdth_trk1 = buffer[3]; @@ -369,7 +372,7 @@ sr_cmd[6] = tocentry->cdte_track; sr_cmd[8] = 12; /* LSB of length */ - result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL); + result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0, SCSI_DATA_READ, NULL, 0); tocentry->cdte_ctrl = buffer[5] & 0xf; tocentry->cdte_adr = buffer[5] >> 4; @@ -396,7 +399,7 @@ sr_cmd[7] = ti->cdti_trk1; sr_cmd[8] = ti->cdti_ind1; - result = sr_do_ioctl(target, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL); + result = sr_do_ioctl(target, sr_cmd, NULL, 0, 0, SCSI_DATA_NONE, NULL, 0); if (result == -EDRIVE_CANT_DO_THIS) result = sr_fake_playtrkind(cdi, ti); @@ -462,7 +465,7 @@ cmd[9] = 0x10; break; } - return sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL); + return sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL, 0); } /* @@ -501,7 +504,7 @@ cmd[4] = (unsigned char) (lba >> 8) & 0xff; cmd[5] = (unsigned char) lba & 0xff; cmd[8] = 1; - rc = sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(minor, cmd, dest, blksize, 0, SCSI_DATA_READ, NULL, 0); return rc; } diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c --- /opt/kernel/linux-2.4.19-pre4/drivers/scsi/sr_vendor.c Thu Jul 5 20:28:17 2001 +++ linux/drivers/scsi/sr_vendor.c Mon Mar 25 17:47:34 2002 @@ -134,7 +134,7 @@ modesel->density = density; modesel->block_length_med = (blocklength >> 8) & 0xff; modesel->block_length_lo = blocklength & 0xff; - if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL))) { + if (0 == (rc = sr_do_ioctl(minor, cmd, buffer, sizeof(*modesel), 0, SCSI_DATA_WRITE, NULL, 0))) { scsi_CDs[minor].device->sector_size = blocklength; } #ifdef DEBUG @@ -179,7 +179,7 @@ (scsi_CDs[minor].device->lun << 5) : 0; cmd[8] = 12; cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL, 0); if (rc != 0) break; if ((buffer[0] << 8) + buffer[1] < 0x0a) { @@ -205,7 +205,7 @@ (scsi_CDs[minor].device->lun << 5) : 0; cmd[1] |= 0x03; cmd[2] = 0xb0; - rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1, SCSI_DATA_READ, NULL, 0); if (rc != 0) break; if (buffer[14] != 0 && buffer[14] != 0xb0) { @@ -231,7 +231,7 @@ cmd[1] = (scsi_CDs[minor].device->scsi_level <= SCSI_2) ? (scsi_CDs[minor].device->lun << 5) : 0; cmd[1] |= 0x03; - rc = sr_do_ioctl(minor, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(minor, cmd, buffer, 4, 1, SCSI_DATA_READ, NULL, 0); if (rc == -EINVAL) { printk(KERN_INFO "sr%d: Hmm, seems the drive " "doesn't support multisession CD's\n", minor); @@ -257,7 +257,7 @@ (scsi_CDs[minor].device->lun << 5) : 0; cmd[8] = 0x04; cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1, SCSI_DATA_READ, NULL, 0); if (rc != 0) { break; } @@ -272,7 +272,7 @@ cmd[6] = rc & 0x7f; /* number of last session */ cmd[8] = 0x0c; cmd[9] = 0x40; - rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL); + rc = sr_do_ioctl(minor, cmd, buffer, 12, 1, SCSI_DATA_READ, NULL, 0); if (rc != 0) { break; } diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/include/linux/cdrom.h linux/include/linux/cdrom.h --- /opt/kernel/linux-2.4.19-pre4/include/linux/cdrom.h Thu Nov 22 20:47:04 2001 +++ linux/include/linux/cdrom.h Tue Mar 26 09:55:09 2002 @@ -5,7 +5,7 @@ * 1994, 1995 Eberhard Moenkeberg, emoenke@gwdg.de * 1996 David van Leeuwen, david@tm.tno.nl * 1997, 1998 Erik Andersen, andersee@debian.org - * 1998-2000 Jens Axboe, axboe@suse.de + * 1998-2002 Jens Axboe, axboe@suse.de */ #ifndef _LINUX_CDROM_H @@ -387,6 +387,9 @@ #define CDC_DVD 0x8000 /* drive is a DVD */ #define CDC_DVD_R 0x10000 /* drive can write DVD-R */ #define CDC_DVD_RAM 0x20000 /* drive can write DVD-RAM */ +#define CDC_MRW 0x40000 /* drive can read MRW */ +#define CDC_MRW_W 0x80000 /* drive can write MRW */ +#define CDC_RAM 0x100000 /* ok to open WRITE */ /* drive status possibilities returned by CDROM_DRIVE_STATUS ioctl */ #define CDS_NO_INFO 0 /* if not implemented */ @@ -714,16 +717,61 @@ __u8 asb[46]; }; -#ifdef __KERNEL__ -#include +/* + * feature profile + */ +#define CDF_MRW 0x28 + +/* + * media status bits + */ +#define CDM_MRW_NOTMRW 0 +#define CDM_MRW_BGFORMAT_INACTIVE 1 +#define CDM_MRW_BGFORMAT_ACTIVE 2 +#define CDM_MRW_BGFORMAT_COMPLETE 3 + +/* + * mrw address spaces + */ +#define MRW_LBA_DMA 0 +#define MRW_LBA_GAA 1 + +/* + * mrw mode pages (first is deprecated) -- probed at init time and + * cdi->mrw_mode_page is set + */ +#define MRW_MODE_PC_PRE1 0x2c +#define MRW_MODE_PC 0x03 -struct cdrom_write_settings { - unsigned char fpacket; /* fixed/variable packets */ - unsigned long packet_size; /* write out this number of packets */ - unsigned long nwa; /* next writeable address */ - unsigned char writeable; /* cdrom is writeable */ +struct mrw_feature_desc { + __u16 feature_code; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 reserved1 : 2; + __u8 feature_version : 4; + __u8 persistent : 1; + __u8 curr : 1; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 curr : 1; + __u8 persistent : 1; + __u8 feature_version : 4; + __u8 reserved1 : 2; +#endif + __u8 add_len; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 reserved2 : 7; + __u8 write : 1; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 write : 1; + __u8 reserved2 : 7; +#endif + __u8 reserved3; + __u8 reserved4; + __u8 reserved5; }; +#ifdef __KERNEL__ +#include + /* Uniform cdrom data structures for cdrom.c */ struct cdrom_device_info { struct cdrom_device_ops *ops; /* link to device_ops */ @@ -744,7 +792,9 @@ /* per-device flags */ __u8 sanyo_slot : 2; /* Sanyo 3 CD changer support */ __u8 reserved : 6; /* not used yet */ - struct cdrom_write_settings write; + + int (*exit)(struct cdrom_device_info *); + int mrw_mode_page; }; struct cdrom_device_ops { @@ -819,6 +869,8 @@ void *buffer, int len, int type); extern struct cdrom_device_info *cdrom_find_device(kdev_t dev); +#endif /* __KERNEL__ */ + typedef struct { __u16 disc_information_length; #if defined(__BIG_ENDIAN_BITFIELD) @@ -842,9 +894,13 @@ __u8 did_v : 1; __u8 dbc_v : 1; __u8 uru : 1; - __u8 reserved2 : 5; + __u8 reserved2 : 2; + __u8 dbit : 1; + __u8 mrw_status : 2; #elif defined(__LITTLE_ENDIAN_BITFIELD) - __u8 reserved2 : 5; + __u8 mrw_status : 2; + __u8 dbit : 1; + __u8 reserved2 : 2; __u8 uru : 1; __u8 dbc_v : 1; __u8 did_v : 1; @@ -901,10 +957,6 @@ __u32 last_rec_address; } track_information; -extern int cdrom_get_disc_info(kdev_t dev, disc_information *di); -extern int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type, - track_information *ti); - /* The SCSI spec says there could be 256 slots. */ #define CDROM_MAX_SLOTS 256 @@ -1053,6 +1105,51 @@ __u8 reserved3; } rpc_state_t; -#endif /* End of kernel only stuff */ +struct feature_header { + __u32 data_len; + __u8 reserved1; + __u8 reserved2; + __u16 curr_profile; +}; + +struct event_header { + __u16 data_len; +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 nea : 1; + __u8 reserved1 : 4; + __u8 notification_class : 3; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 notification_class : 3; + __u8 reserved1 : 4; + __u8 nea : 1; +#endif + __u8 supp_event_class; +}; + +struct media_event_desc { +#if defined(__BIG_ENDIAN_BITFIELD) + __u8 reserved1 : 4; + __u8 media_event_code : 4; + __u8 reserved2 : 6; + __u8 media_present : 1; + __u8 door_open : 1; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + __u8 media_event_code : 4; + __u8 reserved1 : 4; + __u8 door_open : 1; + __u8 media_present : 1; + __u8 reserved2 : 6; +#endif + __u8 start_slot; + __u8 end_slot; +}; + +#ifdef __KERNEL__ +extern int cdrom_get_disc_info(kdev_t dev, disc_information *di); +extern int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type, + track_information *ti); +extern int cdrom_get_media_event(struct cdrom_device_info *cdi, struct media_event_desc *med); +extern int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write); +#endif /* __KERNEL__ */ #endif /* _LINUX_CDROM_H */ diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/include/linux/ide.h linux/include/linux/ide.h --- /opt/kernel/linux-2.4.19-pre4/include/linux/ide.h Tue Mar 26 09:52:58 2002 +++ linux/include/linux/ide.h Mon Mar 25 11:55:23 2002 @@ -259,6 +259,25 @@ #endif /* + * Our Physical Region Descriptor (PRD) table should be large enough + * to handle the biggest I/O request we are likely to see. Since requests + * can have no more than 256 sectors, and since the typical blocksize is + * two or more sectors, we could get by with a limit of 128 entries here for + * the usual worst case. Most requests seem to include some contiguous blocks, + * further reducing the number of table entries required. + * + * The driver reverts to PIO mode for individual requests that exceed + * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling + * 100% of all crazy scenarios here is not necessary. + * + * As it turns out though, we must allocate a full 4KB page for this, + * so the two PRD tables (ide0 & ide1) will each get half of that, + * allowing each to have about 256 entries (8 bytes each) from this. + */ +#define PRD_BYTES 8 +#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES)) + +/* * hwif_chipset_t is used to keep track of the specific hardware * chipset used by each IDE interface, if known. */ diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.19-pre4/include/linux/udf_fs.h linux/include/linux/udf_fs.h --- /opt/kernel/linux-2.4.19-pre4/include/linux/udf_fs.h Tue Mar 26 09:52:58 2002 +++ linux/include/linux/udf_fs.h Mon Mar 25 08:50:14 2002 @@ -30,6 +30,7 @@ * HISTORY * */ +#include #ifndef _UDF_FS_H #define _UDF_FS_H 1