gscd.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,033 行 · 第 1/2 页
C
1,033 行
/* LOC_174 */ /* game over for this unit */ disk_state = ST_x08 | ST_x04 | ST_INVALID; return; } /* LOC_176 */#ifdef GSCD_DEBUG printk("LOC_176 ");#endif if (drv_mode == 0x09) { /* magic... */ printk("GSCD: magic ...\n"); outb(result, GSCDPORT(2)); } /* write the command to the drive */ cmd_write_cmd(cmd); /* LOC_178 */ for (;;) { result = wait_drv_ready(); if (result != drv_mode) { /* LOC_179 */ if (result == 0x04) { /* Mode 4 */ /* LOC_205 */#ifdef GSCD_DEBUG printk("LOC_205 ");#endif disk_state = inb(GSCDPORT(2)); do { result = wait_drv_ready(); } while (result != drv_mode); return; } else { if (result == 0x06) { /* Mode 6 */ /* LOC_181 */#ifdef GSCD_DEBUG printk("LOC_181 ");#endif if (cmd_type == TYPE_DATA) { /* read data */ /* LOC_184 */ if (drv_mode == 9) { /* read the data to the buffer (word) */ /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */ cmd_read_w (respo_buf, respo_count, CD_FRAMESIZE / 2); return; } else { /* read the data to the buffer (byte) */ /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW) */ cmd_read_b (respo_buf, respo_count, CD_FRAMESIZE); return; } } else { /* read the info to the buffer */ cmd_info_in(respo_buf, respo_count); return; } return; } } } else { disk_state = ST_x08 | ST_x04 | ST_INVALID; return; } } /* for (;;) */#ifdef GSCD_DEBUG printk("\n");#endif}static void cmd_write_cmd(char *pstr){ int i, j; /* LOC_177 */#ifdef GSCD_DEBUG printk("LOC_177 ");#endif /* calculate the number of parameter */ j = *pstr & 0x0F; /* shift it out */ for (i = 0; i < j; i++) { outb(*pstr, GSCDPORT(2)); pstr++; }}static int cmd_unit_alive(void){ int result; unsigned long max_test_loops; /* LOC_172 */#ifdef GSCD_DEBUG printk("LOC_172 ");#endif outb(curr_drv_state, GSCDPORT(0)); max_test_loops = 0xFFFF; do { result = wait_drv_ready(); max_test_loops--; } while ((result != 0x08) && (max_test_loops > 0)); return result;}static void cmd_info_in(char *pb, int count){ int result; char read; /* read info */ /* LOC_182 */#ifdef GSCD_DEBUG printk("LOC_182 ");#endif do { read = inb(GSCDPORT(2)); if (count > 0) { *pb = read; pb++; count--; } /* LOC_183 */ do { result = wait_drv_ready(); } while (result == 0x0E); } while (result == 6); cmd_end(); return;}static void cmd_read_b(char *pb, int count, int size){ int result; int i; /* LOC_188 */ /* LOC_189 */#ifdef GSCD_DEBUG printk("LOC_189 ");#endif do { do { result = wait_drv_ready(); } while (result != 6 || result == 0x0E); if (result != 6) { cmd_end(); return; }#ifdef GSCD_DEBUG printk("LOC_191 ");#endif for (i = 0; i < size; i++) { *pb = inb(GSCDPORT(2)); pb++; } count--; } while (count > 0); cmd_end(); return;}static void cmd_end(void){ int result; /* LOC_204 */#ifdef GSCD_DEBUG printk("LOC_204 ");#endif do { result = wait_drv_ready(); if (result == drv_mode) { return; } } while (result != 4); /* LOC_205 */#ifdef GSCD_DEBUG printk("LOC_205 ");#endif disk_state = inb(GSCDPORT(2)); do { result = wait_drv_ready(); } while (result != drv_mode); return;}static void cmd_read_w(char *pb, int count, int size){ int result; int i;#ifdef GSCD_DEBUG printk("LOC_185 ");#endif do { /* LOC_185 */ do { result = wait_drv_ready(); } while (result != 6 || result == 0x0E); if (result != 6) { cmd_end(); return; } for (i = 0; i < size; i++) { /* na, hier muss ich noch mal drueber nachdenken */ *pb = inw(GSCDPORT(2)); pb++; } count--; } while (count > 0); cmd_end(); return;}static int __init find_drives(void){ int *pdrv; int drvnum; int subdrv; int i; speed = 0; pdrv = (int *) &drv_states; curr_drv_state = 0xFE; subdrv = 0; drvnum = 0; for (i = 0; i < 8; i++) { subdrv++; cmd_status(); disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01; if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) { /* LOC_240 */ *pdrv = curr_drv_state; init_cd_drive(drvnum); pdrv++; drvnum++; } else { if (subdrv < 2) { continue; } else { subdrv = 0; } }/* curr_drv_state<<1; <-- das geht irgendwie nicht *//* muss heissen: curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */ curr_drv_state *= 2; curr_drv_state |= 1;#ifdef GSCD_DEBUG printk("DriveState: %d\n", curr_drv_state);#endif } ndrives = drvnum; return drvnum;}static void __init init_cd_drive(int num){ char resp[50]; int i; printk("GSCD: init unit %d\n", num); cc_Ident((char *) &resp); printk("GSCD: identification: "); for (i = 0; i < 0x1E; i++) { printk("%c", resp[i]); } printk("\n"); cc_SetSpeed();}#ifdef FUTURE_WORK/* return_done */static void update_state(void){ unsigned int AX; if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) { if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) { AX = ST_INVALID; } if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) { invalidate(); f_drv_ok = 0; } AX |= 0x8000; } if (disk_state & ST_PLAYING) { AX |= 0x200; } AX |= 0x100; /* pkt_esbx = AX; */ disk_state = 0;}#endifstatic struct gendisk *gscd_disk;static void __exit gscd_exit(void){ CLEAR_TIMER; del_gendisk(gscd_disk); put_disk(gscd_disk); if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) { printk("What's that: can't unregister GoldStar-module\n"); return; } blk_cleanup_queue(gscd_queue); release_region(gscd_port, GSCD_IO_EXTENT); printk(KERN_INFO "GoldStar-module released.\n");}/* This is the common initialisation for the GoldStar drive. *//* It is called at boot time AND for module init. */static int __init gscd_init(void){ int i; int result; int ret=0; printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION); printk(KERN_INFO "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n", gscd_port); if (!request_region(gscd_port, GSCD_IO_EXTENT, "gscd")) { printk(KERN_WARNING "GSCD: Init failed, I/O port (%X) already" " in use.\n", gscd_port); return -EIO; } /* check for card */ result = wait_drv_ready(); if (result == 0x09) { printk(KERN_WARNING "GSCD: DMA kann ich noch nicht!\n"); ret = -EIO; goto err_out1; } if (result == 0x0b) { drv_mode = result; i = find_drives(); if (i == 0) { printk(KERN_WARNING "GSCD: GoldStar CD-ROM Drive is" " not found.\n"); ret = -EIO; goto err_out1; } } if ((result != 0x0b) && (result != 0x09)) { printk(KERN_WARNING "GSCD: GoldStar Interface Adapter does not " "exist or H/W error\n"); ret = -EIO; goto err_out1; } /* reset all drives */ i = 0; while (drv_states[i] != 0) { curr_drv_state = drv_states[i]; printk(KERN_INFO "GSCD: Reset unit %d ... ", i); cc_Reset(); printk("done\n"); i++; } gscd_disk = alloc_disk(1); if (!gscd_disk) goto err_out1; gscd_disk->major = MAJOR_NR; gscd_disk->first_minor = 0; gscd_disk->fops = &gscd_fops; sprintf(gscd_disk->disk_name, "gscd"); sprintf(gscd_disk->devfs_name, "gscd"); if (register_blkdev(MAJOR_NR, "gscd")) { ret = -EIO; goto err_out2; } gscd_queue = blk_init_queue(do_gscd_request, &gscd_lock); if (!gscd_queue) { ret = -ENOMEM; goto err_out3; } disk_state = 0; gscdPresent = 1; gscd_disk->queue = gscd_queue; add_disk(gscd_disk); printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n"); return 0;err_out3: unregister_blkdev(MAJOR_NR, "gscd");err_out2: put_disk(gscd_disk);err_out1: release_region(gscd_port, GSCD_IO_EXTENT); return ret;}static void gscd_hsg2msf(long hsg, struct msf *msf){ hsg += CD_MSF_OFFSET; msf->min = hsg / (CD_FRAMES * CD_SECS); hsg %= CD_FRAMES * CD_SECS; msf->sec = hsg / CD_FRAMES; msf->frame = hsg % CD_FRAMES; gscd_bin2bcd(&msf->min); /* convert to BCD */ gscd_bin2bcd(&msf->sec); gscd_bin2bcd(&msf->frame);}static void gscd_bin2bcd(unsigned char *p){ int u, t; u = *p % 10; t = *p / 10; *p = u | (t << 4);}#ifdef FUTURE_WORKstatic long gscd_msf2hsg(struct msf *mp){ return gscd_bcd2bin(mp->frame) + gscd_bcd2bin(mp->sec) * CD_FRAMES + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;}static int gscd_bcd2bin(unsigned char bcd){ return (bcd >> 4) * 10 + (bcd & 0xF);}#endifMODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");MODULE_LICENSE("GPL");module_init(gscd_init);module_exit(gscd_exit);MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?