📄 sbpcd.c
字号:
#endif /* DISTRIBUTION */
char buf[256];
va_list args;
if (!(sbpcd_debug&(1<<level))) return;
msgnum++;
if (msgnum>99) msgnum=0;
sprintf(buf, MSG_LEVEL "%s-%d [%02d]: ", major_name, d, msgnum);
va_start(args, fmt);
vsprintf(&buf[18], fmt, args);
va_end(args);
printk(buf);
#if KLOGD_PAUSE
sbp_sleep(KLOGD_PAUSE); /* else messages get lost */
#endif /* KLOGD_PAUSE */
return;
}
/*==========================================================================*/
/*
* DDI interface: runtime trace bit pattern maintenance
*/
static int sbpcd_dbg_ioctl(unsigned long arg, int level)
{
switch(arg)
{
case 0: /* OFF */
sbpcd_debug = DBG_INF;
break;
default:
if (arg>=128) sbpcd_debug &= ~(1<<(arg-128));
else sbpcd_debug |= (1<<arg);
}
return (arg);
}
/*==========================================================================*/
static void mark_timeout_delay(u_long i)
{
timed_out_delay=1;
#if 0
msg(DBG_TIM,"delay timer expired.\n");
#endif
}
/*==========================================================================*/
static void mark_timeout_data(u_long i)
{
timed_out_data=1;
#if 0
msg(DBG_TIM,"data timer expired.\n");
#endif
}
/*==========================================================================*/
#if 0
static void mark_timeout_audio(u_long i)
{
timed_out_audio=1;
#if 0
msg(DBG_TIM,"audio timer expired.\n");
#endif
}
#endif
/*==========================================================================*/
/*
* Wait a little while (used for polling the drive).
*/
static void sbp_sleep(u_int time)
{
sti();
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(time);
sti();
}
/*==========================================================================*/
#define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);}
/*==========================================================================*/
/*
* convert logical_block_address to m-s-f_number (3 bytes only)
*/
static INLINE void lba2msf(int lba, u_char *msf)
{
lba += CD_MSF_OFFSET;
msf[0] = lba / (CD_SECS*CD_FRAMES);
lba %= CD_SECS*CD_FRAMES;
msf[1] = lba / CD_FRAMES;
msf[2] = lba % CD_FRAMES;
}
/*==========================================================================*/
/*==========================================================================*/
/*
* convert msf-bin to msf-bcd
*/
static INLINE void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */
{
*p=((*p/10)<<4)|(*p%10);
}
/*==========================================================================*/
static INLINE u_int blk2msf(u_int blk)
{
MSF msf;
u_int mm;
msf.c[3] = 0;
msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES);
mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES);
msf.c[1] = mm / CD_FRAMES;
msf.c[0] = mm % CD_FRAMES;
return (msf.n);
}
/*==========================================================================*/
static INLINE u_int make16(u_char rh, u_char rl)
{
return ((rh<<8)|rl);
}
/*==========================================================================*/
static INLINE u_int make32(u_int rh, u_int rl)
{
return ((rh<<16)|rl);
}
/*==========================================================================*/
static INLINE u_char swap_nibbles(u_char i)
{
return ((i<<4)|(i>>4));
}
/*==========================================================================*/
static INLINE u_char byt2bcd(u_char i)
{
return (((i/10)<<4)+i%10);
}
/*==========================================================================*/
static INLINE u_char bcd2bin(u_char bcd)
{
return ((bcd>>4)*10+(bcd&0x0F));
}
/*==========================================================================*/
static INLINE int msf2blk(int msfx)
{
MSF msf;
int i;
msf.n=msfx;
i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET;
if (i<0) return (0);
return (i);
}
/*==========================================================================*/
/*
* convert m-s-f_number (3 bytes only) to logical_block_address
*/
static INLINE int msf2lba(u_char *msf)
{
int i;
i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET;
if (i<0) return (0);
return (i);
}
/*==========================================================================*/
/* evaluate cc_ReadError code */
static int sta2err(int sta)
{
if (famT_drive)
{
if (sta==0x00) return (0);
if (sta==0x01) return (-604); /* CRC error */
if (sta==0x02) return (-602); /* drive not ready */
if (sta==0x03) return (-607); /* unknown media */
if (sta==0x04) return (-612); /* general failure */
if (sta==0x05) return (0);
if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */
if (sta==0x0b) return (-612); /* general failure */
if (sta==0xff) return (-612); /* general failure */
return (0);
}
else
{
if (sta<=2) return (sta);
if (sta==0x05) return (-604); /* CRC error */
if (sta==0x06) return (-606); /* seek error */
if (sta==0x0d) return (-606); /* seek error */
if (sta==0x0e) return (-603); /* unknown command */
if (sta==0x14) return (-603); /* unknown command */
if (sta==0x0c) return (-611); /* read fault */
if (sta==0x0f) return (-611); /* read fault */
if (sta==0x10) return (-611); /* read fault */
if (sta>=0x16) return (-612); /* general failure */
if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */
if (famL_drive)
if (sta==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */
return (-602); /* drive not ready */
}
}
/*==========================================================================*/
static INLINE void clr_cmdbuf(void)
{
int i;
for (i=0;i<10;i++) drvcmd[i]=0;
cmd_type=0;
}
/*==========================================================================*/
static void flush_status(void)
{
int i;
sbp_sleep(15*HZ/10);
for (i=maxtim_data;i!=0;i--) inb(CDi_status);
}
/*====================================================================*/
/*
* CDi status loop for Teac CD-55A (Rob Riggs)
*
* This is needed because for some strange reason
* the CD-55A can take a real long time to give a
* status response. This seems to happen after we
* issue a READ command where a long seek is involved.
*
* I tried to ensure that we get max throughput with
* minimal busy waiting. We busy wait at first, then
* "switch gears" and start sleeping. We sleep for
* longer periods of time the longer we wait.
*
*/
static int CDi_stat_loop_T(void)
{
int i, gear=1;
u_long timeout_1, timeout_2, timeout_3, timeout_4;
timeout_1 = jiffies + HZ / 50; /* sbp_sleep(0) for a short period */
timeout_2 = jiffies + HZ / 5; /* nap for no more than 200ms */
timeout_3 = jiffies + 5 * HZ; /* sleep for up to 5s */
timeout_4 = jiffies + 45 * HZ; /* long sleep for up to 45s. */
do
{
i = inb(CDi_status);
if (!(i&s_not_data_ready)) return (i);
if (!(i&s_not_result_ready)) return (i);
switch(gear)
{
case 4:
sbp_sleep(HZ);
if (time_after(jiffies, timeout_4)) gear++;
msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
break;
case 3:
sbp_sleep(HZ/10);
if (time_after(jiffies, timeout_3)) gear++;
break;
case 2:
sbp_sleep(HZ/100);
if (time_after(jiffies, timeout_2)) gear++;
break;
case 1:
sbp_sleep(0);
if (time_after(jiffies, timeout_1)) gear++;
}
} while (gear < 5);
return -1;
}
/*==========================================================================*/
static int CDi_stat_loop(void)
{
int i,j;
for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); )
{
for ( ;i!=0;i--)
{
j=inb(CDi_status);
if (!(j&s_not_data_ready)) return (j);
if (!(j&s_not_result_ready)) return (j);
if (fam0L_drive) if (j&s_attention) return (j);
}
sbp_sleep(1);
i = 1;
}
msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
return (-1);
}
/*==========================================================================*/
#if 00000
/*==========================================================================*/
static int tst_DataReady(void)
{
int i;
i=inb(CDi_status);
if (i&s_not_data_ready) return (0);
return (1);
}
/*==========================================================================*/
static int tst_ResultReady(void)
{
int i;
i=inb(CDi_status);
if (i&s_not_result_ready) return (0);
return (1);
}
/*==========================================================================*/
static int tst_Attention(void)
{
int i;
i=inb(CDi_status);
if (i&s_attention) return (1);
return (0);
}
/*==========================================================================*/
#endif
/*==========================================================================*/
static int ResponseInfo(void)
{
int i,j,st=0;
u_long timeout;
for (i=0,timeout=jiffies+HZ;i<response_count;i++)
{
for (j=maxtim_data; ; )
{
for ( ;j!=0;j-- )
{
st=inb(CDi_status);
if (!(st&s_not_result_ready)) break;
}
if ((j!=0)||time_after_eq(jiffies, timeout)) break;
sbp_sleep(1);
j = 1;
}
if (time_after_eq(jiffies, timeout)) break;
infobuf[i]=inb(CDi_info);
}
#if 000
while (!(inb(CDi_status)&s_not_result_ready))
{
infobuf[i++]=inb(CDi_info);
}
j=i-response_count;
if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j);
#endif /* 000 */
for (j=0;j<i;j++)
sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
msgbuf[j*3]=0;
msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i);
j=response_count-i;
if (j>0) return (-j);
else return (i);
}
/*==========================================================================*/
static void EvaluateStatus(int st)
{
D_S[d].status_bits=0;
if (fam1_drive) D_S[d].status_bits=st|p_success;
else if (fam0_drive)
{
if (st&p_caddin_old) D_S[d].status_bits |= p_door_closed|p_caddy_in;
if (st&p_spinning) D_S[d].status_bits |= p_spinning;
if (st&p_check) D_S[d].status_bits |= p_check;
if (st&p_success_old) D_S[d].status_bits |= p_success;
if (st&p_busy_old) D_S[d].status_bits |= p_busy_new;
if (st&p_disk_ok) D_S[d].status_bits |= p_disk_ok;
}
else if (famLV_drive)
{
D_S[d].status_bits |= p_success;
if (st&p_caddin_old) D_S[d].status_bits |= p_disk_ok|p_caddy_in;
if (st&p_spinning) D_S[d].status_bits |= p_spinning;
if (st&p_check) D_S[d].status_bits |= p_check;
if (st&p_busy_old) D_S[d].status_bits |= p_busy_new;
if (st&p_lcs_door_closed) D_S[d].status_bits |= p_door_closed;
if (st&p_lcs_door_locked) D_S[d].status_bits |= p_door_locked;
}
else if (fam2_drive)
{
D_S[d].status_bits |= p_success;
if (st&p2_check) D_S[d].status_bits |= p1_check;
if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed;
if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in;
if (st&p2_busy1) D_S[d].status_bits |= p1_busy;
if (st&p2_busy2) D_S[d].status_bits |= p1_busy;
if (st&p2_spinning) D_S[d].status_bits |= p1_spinning;
if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked;
if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok;
}
else if (famT_drive)
{
return; /* still needs to get coded */
D_S[d].status_bits |= p_success;
if (st&p2_check) D_S[d].status_bits |= p1_check;
if (st&p2_door_closed) D_S[d].status_bits |= p1_door_closed;
if (st&p2_disk_in) D_S[d].status_bits |= p1_disk_in;
if (st&p2_busy1) D_S[d].status_bits |= p1_busy;
if (st&p2_busy2) D_S[d].status_bits |= p1_busy;
if (st&p2_spinning) D_S[d].status_bits |= p1_spinning;
if (st&p2_door_locked) D_S[d].status_bits |= p1_door_locked;
if (st&p2_disk_ok) D_S[d].status_bits |= p1_disk_ok;
}
return;
}
/*==========================================================================*/
static int get_state_T(void)
{
int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -