⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sjcd.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	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_IS_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_IS_VALID ) end_request( 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_IS_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_IS_VALID ){	    /*	     * Continue transferring.	     */	    sjcd_transfer();	    if( CURRENT->nr_sectors == 0 ) end_request( 1 );	    else break;	  }	}	if( CURRENT_IS_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_IS_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_IS_VALID ) end_request( 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_IS_VALID ){    /*     * Who of us are paranoiac?     */    if( CURRENT->bh && !buffer_locked(CURRENT->bh) )      panic( DEVICE_NAME ": block not locked" );    sjcd_transfer();    if( CURRENT->nr_sectors == 0 ) end_request( 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_IS_VALID ) end_request( 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. */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 );    MOD_INC_USE_COUNT;  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:  MOD_DEC_USE_COUNT;  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#ifdef MODULE  MOD_DEC_USE_COUNT;#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 = {	open:			sjcd_open,	release:		sjcd_release,	ioctl:			sjcd_ioctl,	check_media_change:	sjcd_disk_change,};static int blksize = 2048;static int secsize = 2048;/* * 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;/* * Test for presence of drive and initialize it. Called at boot time. * Probe cdrom, find out version and status. */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  	hardsect_size[MAJOR_NR] = &secsize;	blksize_size[MAJOR_NR] = &blksize;  if( devfs_register_blkdev( MAJOR_NR, "sjcd", &sjcd_fops ) != 0 ){    printk( "SJCD: Unable to get major %d for Sanyo CD-ROM\n", MAJOR_NR );    return( -EIO );  }    blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);  read_ahead[ MAJOR_NR ] = 4;  register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &sjcd_fops, 0);    if( check_region( sjcd_base, 4 ) ){    printk( "SJCD: Init failed, I/O port (%X) is already in use\n",      sjcd_base );    sjcd_cleanup();    return( -EIO );  }    /*   * 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" );    sjcd_cleanup();    return( -EIO );  } 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" );    sjcd_cleanup();    return( -EIO );  }  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" );    sjcd_cleanup();    return( -EIO );  }  /*   * 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" );      sjcd_cleanup();      return( -EIO );    } else printk( "\n" );  }  printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);  devfs_register (NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,		  S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL);  sjcd_present++;  return( 0 );}static intsjcd_cleanup(void){  if( (devfs_unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL) )    printk( "SJCD: cannot unregister device.\n" );  else {    release_region( sjcd_base, 4 );    blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));  }  return(0);}void __exit sjcd_exit(void){  devfs_unregister(devfs_find_handle(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK,0));  if ( sjcd_cleanup() )    printk( "SJCD: module: cannot be removed.\n" );  else    printk(KERN_INFO "SJCD: module: removed.\n");}#ifdef MODULEmodule_init(sjcd_init);#endifmodule_exit(sjcd_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -