📄 sjcd.c
字号:
(&sjcd_mode, 1) != 0) {#if defined( SJCD_TRACE ) printk ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n");#endif sjcd_transfer_state = SJCD_S_STOP; goto ReSwitch; } if (sjcd_mode != SCMD_MODE_COOKED) {#if defined( SJCD_TRACE ) printk ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n");#endif sjcd_transfer_state = SJCD_S_STOP; goto ReSwitch; } } if (current_valid()) { struct sjcd_play_msf msf; sjcd_next_bn = CURRENT->sector / 4; hsg2msf(sjcd_next_bn, &msf.start); msf.end.min = 0; msf.end.sec = 0; msf.end.frame = sjcd_read_count = SJCD_BUF_SIZ;#if defined( SJCD_TRACE ) printk ("SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n", msf.start.min, msf.start.sec, msf.start.frame, msf.end.min, msf.end.sec, msf.end.frame); printk ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, sjcd_buf_bn[sjcd_buf_in]);#endif sjcd_send_6_cmd(SCMD_DATA_READ, &msf); sjcd_transfer_state = SJCD_S_DATA; sjcd_transfer_timeout = 500;#if defined( SJCD_TRACE ) printk ("SJCD_S_READ: go to SJCD_S_DATA mode\n");#endif } else {#if defined( SJCD_TRACE ) printk ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n");#endif sjcd_transfer_state = SJCD_S_STOP; goto ReSwitch; } }#if defined( SJCD_GATHER_STAT ) else statistic.read_ticks++;#endif break; } case SJCD_S_DATA:{ unsigned char stat; sjcd_s_data:stat = inb(SJCDPORT (1));#if defined( SJCD_TRACE ) printk("SJCD_S_DATA: status = 0x%02x\n", stat);#endif if (SJCD_STATUS_AVAILABLE(stat)) { /* * No data is waiting for us in the drive buffer. Status of operation * completion is available. Read and parse it. */ sjcd_load_status(); if (!sjcd_status_valid || sjcd_command_failed) {#if defined( SJCD_TRACE ) printk ("SJCD: read block %d failed, maybe audio disk? Giving up\n", sjcd_next_bn);#endif if (current_valid()) end_request(CURRENT, 0);#if defined( SJCD_TRACE ) printk ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n");#endif sjcd_transfer_state = SJCD_S_STOP; goto ReSwitch; } if (!sjcd_media_is_available) { printk ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n"); sjcd_transfer_state = SJCD_S_STOP; goto ReSwitch; } sjcd_transfer_state = SJCD_S_READ; goto ReSwitch; } else if (SJCD_DATA_AVAILABLE(stat)) { /* * One frame is read into device buffer. We must copy it to our memory. * Otherwise cdrom hangs up. Check to see if we have something to copy * to. */ if (!current_valid() && sjcd_buf_in == sjcd_buf_out) {#if defined( SJCD_TRACE ) printk ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n"); printk (" ... all the date would be discarded\n");#endif sjcd_transfer_state = SJCD_S_STOP; goto ReSwitch; } /* * Everything seems to be OK. Just read the frame and recalculate * indices. */ sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */ insb(SJCDPORT(2), sjcd_buf + 2048 * sjcd_buf_in, 2048);#if defined( SJCD_TRACE ) printk ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n", sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, sjcd_buf_bn[sjcd_buf_in]);#endif sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++; if (sjcd_buf_out == -1) sjcd_buf_out = sjcd_buf_in; if (++sjcd_buf_in == SJCD_BUF_SIZ) sjcd_buf_in = 0; /* * Only one frame is ready at time. So we should turn over to wait for * another frame. If we need that, of course. */ if (--sjcd_read_count == 0) { /* * OK, request seems to be precessed. Continue transferring... */ if (!sjcd_transfer_is_active) { while (current_valid()) { /* * Continue transferring. */ sjcd_transfer(); if (CURRENT-> nr_sectors == 0) end_request (CURRENT, 1); else break; } } if (current_valid() && (CURRENT->sector / 4 < sjcd_next_bn || CURRENT->sector / 4 > sjcd_next_bn + SJCD_BUF_SIZ)) {#if defined( SJCD_TRACE ) printk ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n");#endif sjcd_transfer_state = SJCD_S_STOP; goto ReSwitch; } } /* * Now we should turn around rather than wait for while. */ goto sjcd_s_data; }#if defined( SJCD_GATHER_STAT ) else statistic.data_ticks++;#endif break; } case SJCD_S_STOP:{ sjcd_read_count = 0; sjcd_send_cmd(SCMD_STOP); sjcd_transfer_state = SJCD_S_STOPPING; sjcd_transfer_timeout = 500;#if defined( SJCD_GATHER_STAT ) statistic.stop_ticks++;#endif break; } case SJCD_S_STOPPING:{ unsigned char stat; stat = inb(SJCDPORT(1));#if defined( SJCD_TRACE ) printk("SJCD_S_STOP: status = 0x%02x\n", stat);#endif if (SJCD_DATA_AVAILABLE(stat)) { int i;#if defined( SJCD_TRACE ) printk("SJCD_S_STOP: discard data\n");#endif /* * Discard all the data from the pipe. Foolish method. */ for (i = 2048; i--; (void) inb(SJCDPORT(2))); sjcd_transfer_timeout = 500; } else if (SJCD_STATUS_AVAILABLE(stat)) { sjcd_load_status(); if (sjcd_status_valid && sjcd_media_is_changed) { sjcd_toc_uptodate = 0; sjcd_invalidate_buffers(); } if (current_valid()) { if (sjcd_status_valid) sjcd_transfer_state = SJCD_S_READ; else sjcd_transfer_state = SJCD_S_START; } else sjcd_transfer_state = SJCD_S_IDLE; goto ReSwitch; }#if defined( SJCD_GATHER_STAT ) else statistic.stopping_ticks++;#endif break; } default: printk("SJCD: poll: invalid state %d\n", sjcd_transfer_state); return; } if (--sjcd_transfer_timeout == 0) { printk("SJCD: timeout in state %d\n", sjcd_transfer_state); while (current_valid()) end_request(CURRENT, 0); sjcd_send_cmd(SCMD_STOP); sjcd_transfer_state = SJCD_S_IDLE; goto ReSwitch; } /* * Get back in some time. 1 should be replaced with count variable to * avoid unnecessary testings. */ SJCD_SET_TIMER(sjcd_poll, 1);}static void do_sjcd_request(request_queue_t * q){#if defined( SJCD_TRACE ) printk("SJCD: do_sjcd_request(%ld+%ld)\n", CURRENT->sector, CURRENT->nr_sectors);#endif sjcd_transfer_is_active = 1; while (current_valid()) { sjcd_transfer(); if (CURRENT->nr_sectors == 0) end_request(CURRENT, 1); else { sjcd_buf_out = -1; /* Want to read a block not in buffer */ if (sjcd_transfer_state == SJCD_S_IDLE) { if (!sjcd_toc_uptodate) { if (sjcd_update_toc() < 0) { printk ("SJCD: transfer: discard\n"); while (current_valid()) end_request(CURRENT, 0); break; } } sjcd_transfer_state = SJCD_S_START; SJCD_SET_TIMER(sjcd_poll, HZ / 100); } break; } } sjcd_transfer_is_active = 0;#if defined( SJCD_TRACE ) printk ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n", sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, sjcd_buf_bn[sjcd_buf_in]); printk("do_sjcd_request ends\n");#endif}/* * Open the device special file. Check disk is in. */static int sjcd_open(struct inode *ip, struct file *fp){ /* * Check the presence of device. */ if (!sjcd_present) return (-ENXIO); /* * Only read operations are allowed. Really? (:-) */ if (fp->f_mode & 2) return (-EROFS); if (sjcd_open_count == 0) { int s, sjcd_open_tries;/* We don't know that, do we? *//* sjcd_audio_status = CDROM_AUDIO_NO_STATUS;*/ sjcd_mode = 0; sjcd_door_was_open = 0; sjcd_transfer_state = SJCD_S_IDLE; sjcd_invalidate_buffers(); sjcd_status_valid = 0; /* * Strict status checking. */ for (sjcd_open_tries = 4; --sjcd_open_tries;) { if (!sjcd_status_valid) sjcd_get_status(); if (!sjcd_status_valid) {#if defined( SJCD_DIAGNOSTIC ) printk ("SJCD: open: timed out when check status.\n");#endif goto err_out; } else if (!sjcd_media_is_available) {#if defined( SJCD_DIAGNOSTIC ) printk("SJCD: open: no disk in drive\n");#endif if (!sjcd_door_closed) { sjcd_door_was_open = 1;#if defined( SJCD_TRACE ) printk ("SJCD: open: close the tray\n");#endif s = sjcd_tray_close(); if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {#if defined( SJCD_DIAGNOSTIC ) printk ("SJCD: open: tray close attempt failed\n");#endif goto err_out; } continue; } else goto err_out; } break; } s = sjcd_tray_lock(); if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {#if defined( SJCD_DIAGNOSTIC ) printk("SJCD: open: tray lock attempt failed\n");#endif goto err_out; }#if defined( SJCD_TRACE ) printk("SJCD: open: done\n");#endif } ++sjcd_open_count; return (0); err_out: return (-EIO);}/* * On close, we flush all sjcd blocks from the buffer cache. */static int sjcd_release(struct inode *inode, struct file *file){ int s;#if defined( SJCD_TRACE ) printk("SJCD: release\n");#endif if (--sjcd_open_count == 0) { sjcd_invalidate_buffers(); s = sjcd_tray_unlock(); if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {#if defined( SJCD_DIAGNOSTIC ) printk ("SJCD: release: tray unlock attempt failed.\n");#endif } if (sjcd_door_was_open) { s = sjcd_tray_open(); if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {#if defined( SJCD_DIAGNOSTIC ) printk ("SJCD: release: tray unload attempt failed.\n");#endif } } } return 0;}/* * A list of file operations allowed for this cdrom. */static struct block_device_operations sjcd_fops = { .owner = THIS_MODULE, .open = sjcd_open, .release = sjcd_release, .ioctl = sjcd_ioctl, .media_changed = sjcd_disk_change,};/* * Following stuff is intended for initialization of the cdrom. It * first looks for presence of device. If the device is present, it * will be reset. Then read the version of the drive and load status. * The version is two BCD-coded bytes. */static struct { unsigned char major, minor;} sjcd_version;static struct gendisk *sjcd_disk;/* * Test for presence of drive and initialize it. Called at boot time. * Probe cdrom, find out version and status. */static int __init sjcd_init(void){ int i; printk(KERN_INFO "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);#if defined( SJCD_TRACE ) printk("SJCD: sjcd=0x%x: ", sjcd_base);#endif if (register_blkdev(MAJOR_NR, "sjcd")) return -EIO; sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock); if (!sjcd_queue) goto out0; blk_queue_hardsect_size(sjcd_queue, 2048); sjcd_disk = alloc_disk(1); if (!sjcd_disk) { printk(KERN_ERR "SJCD: can't allocate disk"); goto out1; } sjcd_disk->major = MAJOR_NR, sjcd_disk->first_minor = 0, sjcd_disk->fops = &sjcd_fops, sprintf(sjcd_disk->disk_name, "sjcd"); sprintf(sjcd_disk->devfs_name, "sjcd"); if (!request_region(sjcd_base, 4,"sjcd")) { printk ("SJCD: Init failed, I/O port (%X) is already in use\n", sjcd_base); goto out2; } /* * Check for card. Since we are booting now, we can't use standard * wait algorithm. */ printk(KERN_INFO "SJCD: Resetting: "); sjcd_send_cmd(SCMD_RESET); for (i = 1000; i > 0 && !sjcd_status_valid; --i) { unsigned long timer; /* * Wait 10ms approx. */ for (timer = jiffies; time_before_eq(jiffies, timer);); if ((i % 100) == 0) printk("."); (void) sjcd_check_status(); } if (i == 0 || sjcd_command_failed) { printk(" reset failed, no drive found.\n"); goto out3; } else printk("\n"); /* * Get and print out cdrom version. */ printk(KERN_INFO "SJCD: Getting version: "); sjcd_send_cmd(SCMD_GET_VERSION); for (i = 1000; i > 0 && !sjcd_status_valid; --i) { unsigned long timer; /* * Wait 10ms approx. */ for (timer = jiffies; time_before_eq(jiffies, timer);); if ((i % 100) == 0) printk("."); (void) sjcd_check_status(); } if (i == 0 || sjcd_command_failed) { printk(" get version failed, no drive found.\n"); goto out3; } if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) { printk(" %1x.%02x\n", (int) sjcd_version.major, (int) sjcd_version.minor); } else { printk(" read version failed, no drive found.\n"); goto out3; } /* * Check and print out the tray state. (if it is needed?). */ if (!sjcd_status_valid) { printk(KERN_INFO "SJCD: Getting status: "); sjcd_send_cmd(SCMD_GET_STATUS); for (i = 1000; i > 0 && !sjcd_status_valid; --i) { unsigned long timer; /* * Wait 10ms approx. */ for (timer = jiffies; time_before_eq(jiffies, timer);); if ((i % 100) == 0) printk("."); (void) sjcd_check_status(); } if (i == 0 || sjcd_command_failed) { printk(" get status failed, no drive found.\n"); goto out3; } else printk("\n"); } printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); sjcd_disk->queue = sjcd_queue; add_disk(sjcd_disk); sjcd_present++; return (0);out3: release_region(sjcd_base, 4);out2: put_disk(sjcd_disk);out1: blk_cleanup_queue(sjcd_queue);out0: if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) printk("SJCD: cannot unregister device.\n"); return (-EIO);}static void __exit sjcd_exit(void){ del_gendisk(sjcd_disk); put_disk(sjcd_disk); release_region(sjcd_base, 4); blk_cleanup_queue(sjcd_queue); if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) printk("SJCD: cannot unregister device.\n"); printk(KERN_INFO "SJCD: module: removed.\n");}module_init(sjcd_init);module_exit(sjcd_exit);MODULE_LICENSE("GPL");MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -