?? sbpcd.c
字號:
msf.c[3] = 0;
msf.c[2] = (blk + CD_BLOCK_OFFSET) / (CD_SECS * CD_FRAMES);
mm = (blk + CD_BLOCK_OFFSET) % (CD_SECS * CD_FRAMES);
msf.c[1] = mm / CD_FRAMES;
msf.c[0] = mm % CD_FRAMES;
return (msf.n);
}
/*==========================================================================*/
static u_int make16(u_char rh, u_char rl)
{
return ((rh<<8)|rl);
}
/*==========================================================================*/
static u_int make32(u_int rh, u_int rl)
{
return ((rh<<16)|rl);
}
/*==========================================================================*/
static u_char swap_nibbles(u_char i)
{
return ((i<<4)|(i>>4));
}
/*==========================================================================*/
static u_char byt2bcd(u_char i)
{
return (((i/10)<<4)+i%10);
}
/*==========================================================================*/
static u_char bcd2bin(u_char bcd)
{
return ((bcd>>4)*10+(bcd&0x0F));
}
/*==========================================================================*/
static 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_BLOCK_OFFSET;
if (i<0) return (0);
return (i);
}
/*==========================================================================*/
/* evaluate xx_ReadError code (still mysterious) */
static int sta2err(int sta)
{
if (sta<=2) return (sta);
if (sta==0x05) return (-4);
if (sta==0x06) return (-6);
if (sta==0x0d) return (-6);
if (sta==0x0e) return (-3);
if (sta==0x14) return (-3);
if (sta==0x0c) return (-11);
if (sta==0x0f) return (-11);
if (sta==0x10) return (-11);
if (sta>=0x16) return (-12);
DS[d].CD_changed=0xFF;
if (sta==0x11) return (-15);
return (-2);
}
/*==========================================================================*/
static void clr_cmdbuf(void)
{
int i;
for (i=0;i<7;i++) drvcmd[i]=0;
cmd_type=0;
}
/*==========================================================================*/
static void mark_timeout(void)
{
timed_out=1;
DPRINTF((DBG_TIM,"SBPCD: timer stopped.\n"));
}
/*==========================================================================*/
static void flush_status(void)
{
#ifdef CDMKE
int i;
if (current == task[0])
for (i=maxtim02;i!=0;i--) inb(CDi_status);
else
{
sbp_sleep(150);
for (i=maxtim_data;i!=0;i--) inb(CDi_status);
}
#else
timed_out=0;
SET_TIMER(mark_timeout,150);
do { }
while (!timed_out);
CLEAR_TIMER;
inb(CDi_status);
#endif CDMKE
}
/*==========================================================================*/
static int CDi_stat_loop(void)
{
int i,j;
u_long timeout;
if (current == task[0])
for(i=maxtim16;i!=0;i--)
{
j=inb(CDi_status);
if (!(j&s_not_data_ready)) return (j);
if (!(j&s_not_result_ready)) return (j);
if (!new_drive) if (j&s_attention) return (j);
}
else
for(timeout = jiffies + 1000, i=maxtim_data; timeout > jiffies; )
{
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 (!new_drive) if (j&s_attention) return (j);
}
sbp_sleep(1);
i = 1;
}
return (-1);
}
/*==========================================================================*/
static int ResponseInfo(void)
{
int i,j, st=0;
u_long timeout;
if (current == task[0])
for (i=0;i<response_count;i++)
{
for (j=maxtim_8;j!=0;j--)
{
st=inb(CDi_status);
if (!(st&s_not_result_ready)) break;
}
if (j==0) return (-1);
infobuf[i]=inb(CDi_info);
}
else
{
for (i=0, timeout = jiffies + 100; 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 || timeout <= jiffies) break;
sbp_sleep(0);
j = 1;
}
if (timeout <= jiffies) return (-1);
infobuf[i]=inb(CDi_info);
}
}
return (0);
}
/*==========================================================================*/
static int EvaluateStatus(int st)
{
if (!new_drive)
{
DS[d].status_byte=0;
if (st&p_caddin_old) DS[d].status_byte |= p_door_closed|p_caddy_in;
if (st&p_spinning) DS[d].status_byte |= p_spinning;
if (st&p_check) DS[d].status_byte |= p_check;
if (st&p_busy_old) DS[d].status_byte |= p_busy_new;
if (st&p_disk_ok) DS[d].status_byte |= p_disk_ok;
}
else { DS[d].status_byte=st;
st=p_success_old; /* for new drives: fake "successful" bit of old drives */
}
return (st);
}
/*==========================================================================*/
static int ResponseStatus(void)
{
int i,j;
u_long timeout;
DPRINTF((DBG_STA,"SBPCD: doing ResponseStatus...\n"));
if (current == task[0])
{
if (flags_cmd_out & f_respo3) j = maxtim_8;
else if (flags_cmd_out&f_respo2) j=maxtim16;
else j=maxtim04;
for (;j!=0;j--)
{
i=inb(CDi_status);
if (!(i&s_not_result_ready)) break;
}
}
else
{
if (flags_cmd_out & f_respo3) timeout = jiffies;
else if (flags_cmd_out & f_respo2) timeout = jiffies + 1600;
else timeout = jiffies + 400;
j=maxtim_8;
do
{
for ( ;j!=0;j--)
{
i=inb(CDi_status);
if (!(i&s_not_result_ready)) break;
}
if (j != 0 || timeout <= jiffies) break;
sbp_sleep(0);
j = 1;
}
while (1);
}
if (j==0)
{ if ((flags_cmd_out & f_respo3) == 0)
DPRINTF((DBG_STA,"SBPCD: ResponseStatus: timeout.\n"));
EvaluateStatus(0);
return (-1);
}
i=inb(CDi_info);
i=EvaluateStatus(i);
return (i);
}
/*==========================================================================*/
static void xx_ReadStatus(void)
{
int i;
DPRINTF((DBG_STA,"SBPCD: giving xx_ReadStatus command\n"));
if (!new_drive) OUT(CDo_command,0x81);
else
{
#if SBPCD_DIS_IRQ
cli();
#endif SBPCD_DIS_IRQ
OUT(CDo_command,0x05);
for (i=0;i<6;i++) OUT(CDo_command,0);
#if SBPCD_DIS_IRQ
sti();
#endif SBPCD_DIS_IRQ
}
}
/*==========================================================================*/
int xx_ReadError(void)
{
int cmd_out(void);
int i;
clr_cmdbuf();
DPRINTF((DBG_ERR,"SBPCD: giving xx_ReadError command.\n"));
if (new_drive)
{
drvcmd[0]=0x82;
response_count=8;
flags_cmd_out=f_putcmd|f_ResponseStatus;
}
else
{
drvcmd[0]=0x82;
response_count=6;
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus;
}
i=cmd_out();
DS[d].error_byte=0;
DPRINTF((DBG_ERR,"SBPCD: xx_ReadError: cmd_out(82) returns %d (%02X)\n",i,i));
if (i<0) return (i);
if (new_drive) i=2;
else i=1;
DS[d].error_byte=infobuf[i];
DPRINTF((DBG_ERR,"SBPCD: xx_ReadError: infobuf[%d] is %d (%02X)\n",i,DS[d].error_byte,DS[d].error_byte));
i=sta2err(infobuf[i]);
return (i);
}
/*==========================================================================*/
int cmd_out(void)
{
int i=0;
if (flags_cmd_out&f_putcmd)
{
DPRINTF((DBG_CMD,"SBPCD: cmd_out: put"));
for (i=0;i<7;i++) DPRINTF((DBG_CMD," %02X",drvcmd[i]));
DPRINTF((DBG_CMD,"\n"));
#if SBPCD_DIS_IRQ
cli();
#endif SBPCD_DIS_IRQ
for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
#if SBPCD_DIS_IRQ
sti();
#endif SBPCD_DIS_IRQ
}
if (response_count!=0)
{
if (cmd_type!=0)
{
if (sbpro_type) OUT(CDo_sel_d_i,0x01);
DPRINTF((DBG_INF,"SBPCD: misleaded to try ResponseData.\n"));
if (sbpro_type) OUT(CDo_sel_d_i,0x00);
}
else i=ResponseInfo();
if (i<0) return (-9);
}
if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to CDi_stat_loop.\n"));
if (flags_cmd_out&f_lopsta)
{
i=CDi_stat_loop();
if ((i<0)||!(i&s_attention)) return (-9);
}
if (!(flags_cmd_out&f_getsta)) goto LOC_229;
LOC_228:
if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to xx_ReadStatus.\n"));
xx_ReadStatus();
LOC_229:
if (flags_cmd_out&f_ResponseStatus)
{
if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to ResponseStatus.\n"));
i=ResponseStatus();
/* builds status_byte, returns orig. status or p_busy_new */
if (i<0) return (-9);
if (flags_cmd_out&(f_bit1|f_wait_if_busy))
{
if (!st_check)
{
if (flags_cmd_out&f_bit1) if (i&p_success_old) goto LOC_232;
if (!(flags_cmd_out&f_wait_if_busy)) goto LOC_228;
if (!st_busy) goto LOC_228;
}
}
}
LOC_232:
if (!(flags_cmd_out&f_obey_p_check)) return (0);
if (!st_check) return (0);
if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to xx_ReadError.\n"));
i=xx_ReadError();
if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to cmd_out OK.\n"));
return (i);
}
/*==========================================================================*/
static int xx_Seek(u_int pos, char f_blk_msf)
{
int i;
clr_cmdbuf();
if (f_blk_msf>1) return (-3);
if (!new_drive)
{
if (f_blk_msf==1) pos=msf2blk(pos);
drvcmd[2]=(pos>>16)&0x00FF;
drvcmd[3]=(pos>>8)&0x00FF;
drvcmd[4]=pos&0x00FF;
flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
f_ResponseStatus | f_obey_p_check | f_bit1;
}
else
{
if (f_blk_msf==0) pos=blk2msf(pos);
drvcmd[1]=(pos>>16)&0x00FF;
drvcmd[2]=(pos>>8)&0x00FF;
drvcmd[3]=pos&0x00FF;
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
}
drvcmd[0]=0x01;
response_count=0;
i=cmd_out();
return (i);
}
/*==========================================================================*/
static int xx_SpinUp(void)
{
int i;
DPRINTF((DBG_SPI,"SBPCD: SpinUp.\n"));
DS[d].in_SpinUp = 1;
clr_cmdbuf();
if (!new_drive)
{
drvcmd[0]=0x05;
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
}
else
{
drvcmd[0]=0x02;
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
}
response_count=0;
i=cmd_out();
DS[d].in_SpinUp = 0;
return (i);
}
/*==========================================================================*/
static int yy_SpinDown(void)
{
int i;
if (!new_drive) return (-3);
clr_cmdbuf();
drvcmd[0]=0x06;
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
response_count=0;
i=cmd_out();
return (i);
}
/*==========================================================================*/
static int yy_SetSpeed(u_char speed, u_char x1, u_char x2)
{
int i;
if (!new_drive) return (-3);
clr_cmdbuf();
drvcmd[0]=0x09;
drvcmd[1]=0x03;
drvcmd[2]=speed;
drvcmd[3]=x1;
drvcmd[4]=x2;
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
response_count=0;
i=cmd_out();
return (i);
}
/*==========================================================================*/
static int xx_SetVolume(void)
{
int i;
u_char channel0,channel1,volume0,volume1;
u_char control0,value0,control1,value1;
DS[d].diskstate_flags &= ~volume_bit;
clr_cmdbuf();
channel0=DS[d].vol_chan0;
volume0=DS[d].vol_ctrl0;
channel1=control1=DS[d].vol_chan1;
volume1=value1=DS[d].vol_ctrl1;
control0=value0=0;
if (((DS[d].drv_options&sax_a)!=0)&&(DS[d].drv_type>=drv_211))
{
if ((volume0!=0)&&(volume1==0))
{
volume1=volume0;
channel1=channel0;
}
else if ((volume0==0)&&(volume1!=0))
{
volume0=volume1;
channel0=channel1;
}
}
if (channel0>1)
{
channel0=0;
volume0=0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -