* Also for the Longshine LCS-7260 drive.
* Also for the IBM "External ISA CD-Rom" drive.
* Not for the TEAC CD-55A drive (yet).
- * Not for the CreativeLabs CD200 drive (yet).
+ * Not for the CreativeLabs CD200 drive (who knows?).
*
- * NOTE: This is release 3.2.
+ * NOTE: This is release 3.3.
* It works with my SbPro & drive CR-521 V2.11 from 2/92
- * and with the new CR-562-B V0.75 on a "naked" Panasonic
+ * and with the CR-562-B V0.75 on a "naked" Panasonic
* CI-101P interface. And vice versa.
*
*
*
* 3.2 Still testing with CD200 and CD-55A drives.
*
+ * 3.3 Working with CD200 support. Maybe a simple read is already possible.
+ *
* TODO
*
* disk change detection
* thread which brought additional hints and bug fixes.
*
*
- * Copyright (C) 1993, 1994 Eberhard Moenkeberg <emoenke@gwdg.de>
- * or <eberhard_moenkeberg@rollo.central.de>
- *
- * The FTP-home of this driver is
- * ftp.gwdg.de:/pub/linux/cdrom/drivers/sbpcd/.
+ * Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
+ * or <eberhard_moenkeberg@rollo.central.de>
*
* If you change this software, you should mail a .diff
* file with some description lines to emoenke@gwdg.de.
#include "blk.h"
-#define VERSION "3.2 Eberhard Moenkeberg <emoenke@gwdg.de>"
+#define VERSION "3.3 Eberhard Moenkeberg <emoenke@gwdg.de>"
/*
* still testing around...
*/
+#define TEAC 0 /* set to 1 for TEAC CD-55A detection test (not more) */
+
#define MULTISESSION_BY_DRIVER 0 /* if set to 0 here, we need the counterpart
* in linux/fs/isofs/inode.c
*/
#define PRINTK_BUG 0
#define TEST_STI 0
-#define DISTRIBUTION 1
+#define DISTRIBUTION 1 /* I use it with a 0 here */
#if 0
#define INLINE
#define INLINE inline
#endif
-#define TEAC 0
-#define CD200 0
-
/*==========================================================================*/
/*
* provisions for more than 1 driver issues
static int sbpcd_probe[] =
{
CDROM_PORT, SBPRO, /* probe with user's setup first */
+#if DISTRIBUTION
0x230, 1, /* Soundblaster Pro and 16 (default) */
0x300, 0, /* CI-101P (default), WDH-7001C (default),
Galaxy (default), Reveal (one default) */
0x290, 1, /* Soundblaster 16 */
0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
#endif
+#endif DISTRIBUTION
};
#else
static int sbpcd_probe[] = {CDROM_PORT, SBPRO}; /* probe with user's setup only */
static int sbpcd_debug = (1<<DBG_INF) |
(1<<DBG_TOC) |
(1<<DBG_MUL) |
- (1<<DBG_LCS) |
- (1<<DBG_TEA) |
- (1<<DBG_CD2) |
- (1<<DBG_ID) |
(1<<DBG_UPC);
-#endif
+#endif DISTRIBUTION
+
static int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */
static int sbpro_type = SBPRO;
static unsigned char setup_done = 0;
char drv_sel; /* drive select lines bits */
char drive_model[9];
- char firmware_version[4];
+ u_char firmware_version[4];
char f_eject; /* auto-eject flag: 0 or 1 */
u_char *sbp_buf; /* Pointer to internal data buffer,
space allocated during sbpcd_init() */
u_char f_multisession;
u_int lba_multi;
+#if MULTISESSION_BY_DRIVER
u_int last_redirect;
+#endif MULTISESSION_BY_DRIVER
+ int first_session;
+ int last_session;
u_char audio_state;
u_int pos_audio_start;
return (-1);
}
/*==========================================================================*/
-#if TEAC
+#if TEAC-X
/*==========================================================================*/
static int tst_DataReady(void)
{
return (0);
}
/*==========================================================================*/
-#endif TEAC
+#endif TEAC-X
/*==========================================================================*/
static int ResponseInfo(void)
{
else /* CD200, CD-55A */
{
}
- if (!fam0_drive) for (i=0;i<6;i++) OUT(CDo_command,0);
+ if (!fam0L_drive) for (i=0;i<6;i++) OUT(CDo_command,0);
SBPCD_STI;
}
/*==========================================================================*/
else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus;
}
- else /* CD200, CD-55A */
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_READ_ERR;
+ response_count=6;
+ flags_cmd_out=f_putcmd;
+ }
+ else /* CD-55A */
{
+ return (-1);
+ drvcmd[0]=CMDT_READ_ERR;
+ response_count=5;
+ flags_cmd_out=f_putcmd;
}
i=cmd_out(7);
DriveStruct[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 (fam0_drive) i=1;
- else if (fam1L_drive) i=2;
- else /* CD200, CD-55A */
- {
- }
+ else i=2;
DriveStruct[d].error_byte=infobuf[i];
DPRINTF((DBG_ERR,"SBPCD: xx_ReadError: infobuf[%d] is %d (%02X)\n",i,DriveStruct[d].error_byte,DriveStruct[d].error_byte));
i=sta2err(infobuf[i]);
if (f_blk_msf>1) return (-3);
if (fam0_drive)
{
- drvcmd[0]=CMD0_SEEK; /* same as CMD1_ and CMDL_ */
+ drvcmd[0]=CMD0_SEEK;
if (f_blk_msf==1) pos=msf2blk(pos);
drvcmd[2]=(pos>>16)&0x00FF;
drvcmd[3]=(pos>>8)&0x00FF;
else
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
}
- else /* CD200, CD-55A */
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_SEEK;
+ if (f_blk_msf==0) pos=blk2msf(pos);
+ drvcmd[2]=(pos>>16)&0x00FF;
+ drvcmd[3]=(pos>>16)&0x00FF;
+ drvcmd[4]=(pos>>8)&0x00FF;
+ drvcmd[5]=pos&0x00FF;
+ flags_cmd_out=f_putcmd|f_ResponseStatus;
+ }
+ else /* CD-55A */
{
+ return (-1);
}
response_count=0;
i=cmd_out(7);
drvcmd[0]=CMD1_SPINUP;
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
}
- else /* CD200, CD-55A */
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_TRAY_CTL;
+ drvcmd[4]=0x01;
+ flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
+ }
+ else /* CD-55A */
{
+ return (-1);
}
response_count=0;
i=cmd_out(7);
if (fam0_drive) return (-3);
clr_cmdbuf();
+ response_count=0;
if (fam1_drive)
{
drvcmd[0]=CMD1_SPINDOWN;
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- response_count=0;
+ }
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_TRAY_CTL;
+ drvcmd[4]=0x02; /* "eject" */
+ flags_cmd_out=f_putcmd|f_ResponseStatus;
}
else if (famL_drive)
{
drvcmd[0]=CMDL_SPINDOWN;
drvcmd[1]=1;
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- response_count=0;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
i=cmd_out(7);
return (i);
if (fam0L_drive) return (-3);
clr_cmdbuf();
- drvcmd[0]=CMD1_SETMODE;
- 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;
+ if (fam1_drive)
+ {
+ drvcmd[0]=CMD1_SETMODE;
+ drvcmd[1]=0x03;
+ drvcmd[2]=speed;
+ drvcmd[3]=x1;
+ drvcmd[4]=x2;
+ flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
+ }
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_SETSPEED;
+ if (speed&speed_auto)
+ {
+ drvcmd[2]=0xFF;
+ drvcmd[3]=0xFF;
+ }
+ else
+ {
+ drvcmd[2]=0;
+ drvcmd[3]=150;
+ }
+ flags_cmd_out=f_putcmd|f_ResponseStatus;
+ }
+ else /* CD-55A */
+ {
+ return (-1);
+ }
i=cmd_out(7);
return (i);
}
drvcmd[6]=value1;
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
}
+ else if (fam2_drive)
+ {
+ control0=channel0+1;
+ control1=channel1+1;
+ value0=(volume0>volume1)?volume0:volume1;
+ value1=value0;
+ if (volume0==0) control0=0;
+ if (volume1==0) control1=0;
+ drvcmd[0]=CMD2_SETMODE;
+ drvcmd[1]=0x0E;
+ drvcmd[3]=control0;
+ drvcmd[4]=value0;
+ drvcmd[5]=control1;
+ drvcmd[6]=value1;
+ flags_cmd_out=f_putcmd|f_ResponseStatus;
+ }
else if (famL_drive)
{
if ((volume0==0)||(channel0!=0)) control0 |= 0x80;
drvcmd[5]=value0;
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
response_count=0;
i=cmd_out(7);
int i;
DPRINTF((DBG_RES,"SBPCD: xy_DriveReset called.\n"));
+ clr_cmdbuf();
+ response_count=0;
if (fam0L_drive) OUT(CDo_reset,0x00);
else if (fam1_drive)
{
- clr_cmdbuf();
drvcmd[0]=CMD1_RESET;
flags_cmd_out=f_putcmd;
- response_count=0;
i=cmd_out(7);
}
- else /* CD200, CD-55A */
+ else if (fam2_drive)
{
+ drvcmd[0]=CMD2_RESET;
+ flags_cmd_out=f_putcmd;
+ i=cmd_out(7);
+ OUT(CDo_reset,0x00);
+ }
+ else /* CD-55A */
+ {
+ return (-1);
}
if (famL_drive) sbp_sleep(500); /* wait 5 seconds */
else sbp_sleep(100); /* wait a second */
int i;
clr_cmdbuf();
+ response_count=0;
if (fam1_drive)
{
drvcmd[0]=CMD1_PAU_RES;
+ if (pau_res!=1) drvcmd[1]=0x80;
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
}
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_PAU_RES;
+ if (pau_res!=1) drvcmd[2]=0x01;
+ flags_cmd_out=f_putcmd|f_ResponseStatus;
+ }
else if (fam0L_drive)
{
drvcmd[0]=CMD0_PAU_RES;
+ if (pau_res!=1) drvcmd[1]=0x80;
if (famL_drive)
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
f_obey_p_check|f_bit1;
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
f_obey_p_check;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
- if (pau_res!=1) drvcmd[1]=0x80;
- response_count=0;
i=cmd_out(7);
return (i);
}
DPRINTF((DBG_LCK,"SBPCD: yy_LockDoor: %d (drive %d)\n", lock, d));
DPRINTF((DBG_LCS,"SBPCD: p_door_locked bit %d before\n", st_door_locked));
clr_cmdbuf();
+ response_count=0;
if (fam1_drive)
{
drvcmd[0]=CMD1_LOCK_CTL;
if (lock==1) drvcmd[1]=0x01;
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- response_count=0;
+ }
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_LOCK_CTL;
+ if (lock==1) drvcmd[4]=0x01;
+ flags_cmd_out=f_putcmd|f_ResponseStatus;
}
else if (famL_drive)
{
drvcmd[0]=CMDL_LOCK_CTL;
if (lock==1) drvcmd[1]=0x01;
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- response_count=0;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
i=cmd_out(7);
DPRINTF((DBG_LCS,"SBPCD: p_door_locked bit %d after\n", st_door_locked));
DPRINTF((DBG_LCS,"SBPCD: p_door_closed bit %d before\n", st_door_closed));
clr_cmdbuf();
+ response_count=0;
if (fam1_drive)
{
drvcmd[0]=CMD1_TRAY_CTL;
flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
}
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_TRAY_CTL;
+ drvcmd[1]=0x01;
+ drvcmd[4]=0x03; /* "insert" */
+ flags_cmd_out=f_putcmd|f_ResponseStatus;
+ }
else if (famL_drive)
{
drvcmd[0]=CMDL_TRAY_CTL;
flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
f_ResponseStatus|f_obey_p_check|f_bit1;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
- response_count=0;
i=cmd_out(7);
DPRINTF((DBG_LCS,"SBPCD: p_door_closed bit %d after\n", st_door_closed));
return (i);
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
response_count=11;
}
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_READSUBQ;
+ drvcmd[1]=0x02;
+ drvcmd[3]=0x01;
+ flags_cmd_out=f_putcmd;
+ response_count=10;
+ }
else if (fam0L_drive)
{
drvcmd[0]=CMD0_READSUBQ;
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
response_count=13;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
i=cmd_out(7);
if (i<0) return (i);
DPRINTF((DBG_SQ,"SBPCD: xx_ReadSubQ:"));
- for (i=0;i<(fam1_drive?11:13);i++)
+ for (i=0;i<response_count;i++)
{
DPRINTF((DBG_SQ," %02X", infobuf[i]));
}
{
int i;
+ if (fam2_drive) return (0);
DriveStruct[d].diskstate_flags &= ~frame_size_bit;
clr_cmdbuf();
if (fam1_drive)
{
drvcmd[0]=CMD1_GETMODE;
- drvcmd[1]=0x00;
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
response_count=5;
}
else if (fam0L_drive)
{
drvcmd[0]=CMD0_GETMODE;
- drvcmd[1]=0x00;
if (famL_drive)
flags_cmd_out=f_putcmd;
else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
response_count=2;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
i=cmd_out(7);
if (i<0) return (i);
i=0;
- if (fam0L_drive) DriveStruct[d].sense_byte=0;
if (fam1_drive) DriveStruct[d].sense_byte=infobuf[i++];
- else /* CD200, CD-55A */
+ else if (fam0L_drive) DriveStruct[d].sense_byte=0;
+ else /* CD-55A */
{
}
DriveStruct[d].frame_size=make16(infobuf[i],infobuf[i+1]);
{
int i;
+ if (fam2_drive) return (0);
DriveStruct[d].diskstate_flags &= ~frame_size_bit;
clr_cmdbuf();
DriveStruct[d].frame_size=framesize;
else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
response_count=0;
i=cmd_out(7);
response_count=5;
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
}
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_GETMODE;
+ drvcmd[1]=0x0E;
+ response_count=5;
+ flags_cmd_out=f_putcmd;
+ }
else if (fam0L_drive)
{
drvcmd[0]=CMD0_GETMODE;
else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
i=cmd_out(7);
if (i<0) return (i);
chan0 >>= 1;
chan1 >>= 1;
}
+ else if (fam2_drive)
+ {
+ chan0=infobuf[1];
+ vol0=infobuf[2];
+ chan1=infobuf[3];
+ vol1=infobuf[4];
+ }
else if (famL_drive)
{
chan0=0;
}
}
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
DriveStruct[d].vol_chan0=chan0;
DriveStruct[d].vol_ctrl0=vol0;
DriveStruct[d].vol_chan1=chan1;
DriveStruct[d].vol_ctrl1=vol1;
- if (fam01_drive)
- {
- DriveStruct[d].vol_chan2=2;
- DriveStruct[d].vol_ctrl2=0xFF;
- DriveStruct[d].vol_chan3=3;
- DriveStruct[d].vol_ctrl3=0xFF;
- }
- else if (famL_drive)
- {
- }
- else /* CD200, CD-55A */
- {
- }
+ DriveStruct[d].vol_chan2=2;
+ DriveStruct[d].vol_ctrl2=0xFF;
+ DriveStruct[d].vol_chan3=3;
+ DriveStruct[d].vol_ctrl3=0xFF;
DriveStruct[d].diskstate_flags |= volume_bit;
return (0);
}
{
int i;
+ if (famL_drive) return (0);
DriveStruct[d].diskstate_flags &= ~cd_size_bit;
clr_cmdbuf();
if (fam1_drive)
{
drvcmd[0]=CMD1_CAPACITY;
+ response_count=5;
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
}
- else if (fam0L_drive)
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_CAPACITY;
+ response_count=8;
+ flags_cmd_out=f_putcmd;
+ }
+ else if (fam0_drive)
{
drvcmd[0]=CMD0_CAPACITY;
+ response_count=5;
if(famL_drive)
flags_cmd_out=f_putcmd;
else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
- response_count=5;
i=cmd_out(7);
if (i<0) return (i);
- DriveStruct[d].CDsize_blk=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
- if (fam1_drive) DriveStruct[d].CDsize_blk=msf2blk(DriveStruct[d].CDsize_blk);
- DriveStruct[d].CDsize_frm = (DriveStruct[d].CDsize_blk * make16(infobuf[3],infobuf[4])) / CD_FRAMESIZE;
- DriveStruct[d].CDsize_blk += 151;
+ if (fam1_drive) DriveStruct[d].CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_BLOCK_OFFSET;
+ else if (fam0_drive) DriveStruct[d].CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
+ else if (fam2_drive) DriveStruct[d].CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3]));
DriveStruct[d].diskstate_flags |= cd_size_bit;
return (0);
}
if (fam1_drive)
{
drvcmd[0]=CMD1_DISKINFO;
+ response_count=6;
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
}
else if (fam0L_drive)
{
drvcmd[0]=CMD0_DISKINFO;
+ response_count=6;
if(famL_drive)
flags_cmd_out=f_putcmd;
else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
}
- else /* CD200, CD-55A */
+ else if (fam2_drive)
{
+ /* possibly longer timeout periods necessary */
+ DriveStruct[d].f_multisession=0;
+ drvcmd[0]=CMD2_DISKINFO;
+ drvcmd[1]=0x02;
+ drvcmd[2]=0xAB;
+ drvcmd[3]=0xFF; /* session */
+ response_count=8;
+ flags_cmd_out=f_putcmd;
+ }
+ else /* CD-55A */
+ {
+ return (-1);
}
- response_count=6;
i=cmd_out(7);
if (i<0) return (i);
DriveStruct[d].xa_byte=infobuf[0];
- DriveStruct[d].n_first_track=infobuf[1];
- DriveStruct[d].n_last_track=infobuf[2];
- DriveStruct[d].size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
- DriveStruct[d].size_blk=msf2blk(DriveStruct[d].size_msf);
+ if (fam2_drive)
+ {
+ DriveStruct[d].first_session=infobuf[1];
+ DriveStruct[d].last_session=infobuf[2];
+ DriveStruct[d].n_first_track=infobuf[3];
+ DriveStruct[d].n_last_track=infobuf[4];
+ if (DriveStruct[d].first_session!=DriveStruct[d].last_session)
+ {
+ DriveStruct[d].f_multisession=1;
+ DriveStruct[d].lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])));
+ }
+#if 0
+ if (DriveStruct[d].first_session!=DriveStruct[d].last_session)
+ {
+ if (DriveStruct[d].last_session<=20)
+ zwanzig=DriveStruct[d].last_session+1;
+ else zwanzig=20;
+ for (count=DriveStruct[d].first_session;count<zwanzig;count++)
+ {
+ drvcmd[0]=CMD2_DISKINFO;
+ drvcmd[1]=0x02;
+ drvcmd[2]=0xAB;
+ drvcmd[3]=count;
+ response_count=8;
+ flags_cmd_out=f_putcmd;
+ i=cmd_out(7);
+ if (i<0) return (i);
+ DriveStruct[d].msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]));
+ }
+ DriveStruct[d].diskstate_flags |= multisession_bit;
+ }
+#endif
+ drvcmd[0]=CMD2_DISKINFO;
+ drvcmd[1]=0x02;
+ drvcmd[2]=0xAA;
+ drvcmd[3]=0xFF;
+ response_count=5;
+ flags_cmd_out=f_putcmd;
+ i=cmd_out(7);
+ if (i<0) return (i);
+ DriveStruct[d].size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4]));
+ DriveStruct[d].size_blk=msf2blk(DriveStruct[d].size_msf);
+ }
+ else
+ {
+ DriveStruct[d].n_first_track=infobuf[1];
+ DriveStruct[d].n_last_track=infobuf[2];
+ DriveStruct[d].size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
+ DriveStruct[d].size_blk=msf2blk(DriveStruct[d].size_msf);
+ if (famL_drive) DriveStruct[d].CDsize_frm=DriveStruct[d].size_blk+1;
+ }
DriveStruct[d].diskstate_flags |= toc_bit;
DPRINTF((DBG_TOC,"SBPCD: TocDesc: %02X %02X %02X %08X\n",
- DriveStruct[d].xa_byte,DriveStruct[d].n_first_track,DriveStruct[d].n_last_track,DriveStruct[d].size_msf));
+ DriveStruct[d].xa_byte,
+ DriveStruct[d].n_first_track,
+ DriveStruct[d].n_last_track,
+ DriveStruct[d].size_msf));
return (0);
}
/*==========================================================================*/
if (fam1_drive)
{
drvcmd[0]=CMD1_READTOC;
+ response_count=8;
flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
}
+ else if (fam2_drive)
+ {
+ /* possibly longer timeout periods necessary */
+ drvcmd[0]=CMD2_DISKINFO;
+ drvcmd[1]=0x02;
+ response_count=5;
+ flags_cmd_out=f_putcmd;
+ }
else if (fam0L_drive)
{
drvcmd[0]=CMD0_READTOC;
drvcmd[1]=0x02;
+ response_count=8;
if(famL_drive)
flags_cmd_out=f_putcmd;
else
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
drvcmd[2]=num;
- response_count=8;
i=cmd_out(7);
if (i<0) return (i);
- DriveStruct[d].TocEnt_nixbyte=infobuf[0];
- DriveStruct[d].TocEnt_ctl_adr=swap_nibbles(infobuf[1]);
- DriveStruct[d].TocEnt_number=infobuf[2];
- DriveStruct[d].TocEnt_format=infobuf[3];
+ if (fam2_drive) i=0;
+ else
+ {
+ DriveStruct[d].TocEnt_nixbyte=infobuf[0];
+ i=1;
+ }
+ DriveStruct[d].TocEnt_ctl_adr=swap_nibbles(infobuf[i++]);
+ if (!(fam2_drive))
+ {
+ DriveStruct[d].TocEnt_number=infobuf[i++];
+ DriveStruct[d].TocEnt_format=infobuf[i];
+ }
if (fam1_drive) i=4;
- else i=5;
+ else if (fam0L_drive) i=5;
+ else if (fam2_drive) i=2;
DriveStruct[d].TocEnt_address=make32(make16(0,infobuf[i]),
make16(infobuf[i+1],infobuf[i+2]));
DPRINTF((DBG_TOC,"SBPCD: TocEntry: %02X %02X %02X %02X %08X\n",
flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
else /* CD200, CD-55A */
{
+ return (-1);
}
i=cmd_out(7);
return (i);
}
else /* CD200, CD-55A */
{
+ return (-1);
}
}
DriveStruct[d].UPC_buf[6] &= 0xF0;
}
else /* CD200, CD-55A */
{
+ return (-1);
}
i=cmd_out(7);
if (i<0) return (i);
{
int i;
+ if (fam2_drive) return (0);
DriveStruct[d].f_multisession=0;
- clr_cmdbuf();
DriveStruct[d].lba_multi=0;
if (fam0_drive) return (0);
+ clr_cmdbuf();
if (fam1_drive)
{
drvcmd[0]=CMD1_MULTISESS;
DriveStruct[d].f_multisession=1;
DriveStruct[d].lba_multi=msf2blk(make32(make16(0,infobuf[1]),
make16(infobuf[2],infobuf[3])));
+#if MULTISESSION_BY_DRIVER
DriveStruct[d].last_redirect=19;
- /* preliminary - has to get adjusted the following way:
- * look at the first byte of frames 17 ff. until 0xFF is seen
- * the frame before this one is the last continuation frame
- */
+#endif MULTISESSION_BY_DRIVER
DPRINTF((DBG_MUL,"SBPCD: MultiSession CD detected: %02X %02X %02X %02X %02X %02X (%d)\n",
infobuf[0], infobuf[1], infobuf[2],
infobuf[3], infobuf[4], infobuf[5],
{
DPRINTF((DBG_MUL,"SBPCD: MultiSession base: %06X\n", DriveStruct[d].lba_multi));
DriveStruct[d].f_multisession=1;
+#if MULTISESSION_BY_DRIVER
DriveStruct[d].last_redirect=19;
- /* preliminary - has to get adjusted the following way:
- * look at the first byte of frames 17 ff. until 0xFF is seen;
- * the frame before this one is the last repetition frame.
- */
+#endif MULTISESSION_BY_DRIVER
}
}
- else /* CD200, CD-55A */
+ else /* CD-55A */
{
+ return (-1);
}
return (0);
}
#endif CDMKE
}
/*==========================================================================*/
-#if TEAC
+#if TEAC-X
/*==========================================================================*/
static void teac_reset(int drv_id)
{
return (found);
}
/*==========================================================================*/
-#endif TEAC
+#endif TEAC-X
/*==========================================================================*/
/*==========================================================================*/
#ifdef CD200
static int check_version(void)
{
int i, j;
+ u_char lcs_firm[][4]={"A4F4","A E1"};
DPRINTF((DBG_INI,"SBPCD: check_version entered.\n"));
DriveStruct[d].drv_type=0;
- /* check for CD200 first */
+#if TEAC
+ /* check for CD-55A */
+ clr_cmdbuf();
+ drvcmd[0]=CMDT_READ_ERR;
+ response_count=5;
+ flags_cmd_out=f_putcmd;
+ i=cmd_out(7);
+ if (i<0) DPRINTF((DBG_INI,"SBPCD: CMDT_READERR returns %d (ok anyway).\n",i));
+ /* read drive version */
+ clr_cmdbuf();
+ for (i=0;i<12;i++) infobuf[i]=0;
+ if (sbpro_type==1) OUT(CDo_sel_i_d,0);
+ response_count=12; /* may be too much */
+ drvcmd[0]=CMDT_READ_VER;
+ drvcmd[4]=response_count;
+ flags_cmd_out=f_putcmd;
+ i=cmd_out(10); /* possibly only 6 */
+ if (i<0) DPRINTF((DBG_INI,"SBPCD: CMDT_READ_VER returns %d\n",i));
+#else
+ /* check for CD200 */
clr_cmdbuf();
drvcmd[0]=CMD2_READ_ERR;
response_count=9;
flags_cmd_out=f_putcmd;
i=cmd_out(7);
if (i<0) DPRINTF((DBG_INI,"SBPCD: CMD2_READ_VER returns %d\n",i));
-
- if (i<0)
- {
- /* check for CD-55A */
- clr_cmdbuf();
- drvcmd[0]=CMDT_READ_ERR;
- response_count=5;
- flags_cmd_out=f_putcmd;
- i=cmd_out(7);
- if (i<0) DPRINTF((DBG_INI,"SBPCD: CMDT_READERR returns %d (ok anyway).\n",i));
- /* read drive version */
- clr_cmdbuf();
- for (i=0;i<12;i++) infobuf[i]=0;
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- response_count=12; /* may be too much */
- drvcmd[0]=CMDT_READ_VER;
- drvcmd[4]=response_count;
- flags_cmd_out=f_putcmd;
- i=cmd_out(10); /* possibly only 6 */
- if (i<0) DPRINTF((DBG_INI,"SBPCD: CMDT_READ_VER returns %d\n",i));
- }
+#endif TEAC
if (i>=0) /* either from CD200 or CD-55A */
{
for (i=0, j=0;i<12;i++) j+=infobuf[i];
for (j=0;j<4;j++) DriveStruct[d].firmware_version[j]=infobuf[i+j];
if (famL_drive)
{
+ for (i=0;i<2;i++)
+ {
+ for (j=0;j<4;j++)
+ if (DriveStruct[d].firmware_version[j]!=lcs_firm[i][j]) break;
+ if (j==4) break;
+ }
+ if (j!=4) ask_mail();
DriveStruct[d].drv_type=drv_260;
- if ((DriveStruct[d].firmware_version[0]!='A') ||
- (DriveStruct[d].firmware_version[1]!='4') ||
- (DriveStruct[d].firmware_version[2]!='F') ||
- (DriveStruct[d].firmware_version[3]!='4'))
- ask_mail();
}
else if (famT_drive)
{
{
printk("\n\nSBPCD: new drive CD200 (%s)detected.\n",
DriveStruct[d].firmware_version);
- printk("SBPCD: support is not fulfilled yet - drive gets ignored.\n");
+ printk("SBPCD: support is not fulfilled yet.\n");
if (j!=101) /* only 1.01 known at time */
ask_mail();
- else
- printk("SBPCD: just wait some days...\n\n");
- DriveStruct[d].drv_type=0;
- return (-1);
}
}
DPRINTF((DBG_LCS,"SBPCD: drive type %02X\n",DriveStruct[d].drv_type));
int error_flag;
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADAUDIO requested.\n"));
-#if 0
- if (fam0L_drive) return (-EINVAL);
-#endif
+ if (fam0_drive) return (-EINVAL);
+ if (famL_drive) return (-EINVAL);
+ if (fam2_drive) return (-EINVAL);
+ if (famT_drive) return (-EINVAL);
if (DriveStruct[d].aud_buf==NULL) return (-EINVAL);
i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio));
if (i) return (i);
}
else if (fam1_drive)
{
- drvcmd[0]=CMD1_READ; /* "read frames", new drives */
+ drvcmd[0]=CMD1_READ;
lba2msf(block,&drvcmd[1]); /* msf-bin format required */
drvcmd[4]=0;
drvcmd[5]=0;
drvcmd[6]=DriveStruct[d].sbp_read_frames;
}
- else /* CD200, CD-55A */
+ else if (fam2_drive)
+ {
+ drvcmd[0]=CMD2_READ;
+ lba2msf(block,&drvcmd[1]); /* msf-bin format required */
+ drvcmd[4]=0;
+ drvcmd[5]=DriveStruct[d].sbp_read_frames;
+ drvcmd[6]=0x02;
+ }
+ else /* CD-55A */
{
}
SBPCD_CLI;
sbpcd_release, /* release */
NULL, /* fsync */
NULL, /* fasync */
- sbpcd_chk_disk_change, /* media_change */
+ sbpcd_chk_disk_change, /* media_change */
NULL /* revalidate */
};
/*==========================================================================*/
* kraxel@cs.tu-berlin.de (Gerd Knorr)
*/
+#define DEBUG
+
static void sr_photocd(struct inode *inode)
{
unsigned long sector,min,sec,frame;
- unsigned char buf[40];
- int rc;
+ unsigned char buf[40]; /* the buffer for the ioctl */
+ unsigned char *cmd; /* the scsi-command */
+ unsigned char *send; /* the data we send to the drive ... */
+ unsigned char *rec; /* ... and get back */
+ int rc,is_xa;
if (!suser()) {
/* I'm not the superuser, so SCSI_IOCTL_SEND_COMMAND isn't allowed for me.
scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = 0;
return;
}
-
+
+ cmd = rec = &buf[8];
switch(scsi_CDs[MINOR(inode->i_rdev)].device->manufacturer) {
case SCSI_MAN_NEC:
printk("sr_photocd: use NEC code\n");
#endif
memset(buf,0,40);
- *((unsigned long*)buf) = 0;
- *((unsigned long*)buf+1) = 0x16;
- buf[8+0] = 0xde;
- buf[8+1] = 0x03;
- buf[8+2] = 0xb0;
+ *((unsigned long*)buf) = 0x0; /* we send nothing... */
+ *((unsigned long*)buf+1) = 0x16; /* and receive 0x16 bytes */
+ cmd[0] = 0xde;
+ cmd[1] = 0x03;
+ cmd[2] = 0xb0;
rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
SCSI_IOCTL_SEND_COMMAND, buf);
if (rc != 0) {
printk("sr_photocd: ioctl error (NEC): 0x%x\n",rc);
sector = 0;
} else {
- min = (unsigned long)buf[8+15]/16*10 + (unsigned long)buf[8+15]%16;
- sec = (unsigned long)buf[8+16]/16*10 + (unsigned long)buf[8+16]%16;
- frame = (unsigned long)buf[8+17]/16*10 + (unsigned long)buf[8+17]%16;
- sector = min*60*75 + sec*75 + frame;
+ min = (unsigned long) rec[15]/16*10 + (unsigned long) rec[15]%16;
+ sec = (unsigned long) rec[16]/16*10 + (unsigned long) rec[16]%16;
+ frame = (unsigned long) rec[17]/16*10 + (unsigned long) rec[17]%16;
+ /* if rec[14] is'nt 0xb0, the drive does not support multisession CD's, use zero */
+ sector = (0xb0 == rec[14]) ? min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame : 0;
#ifdef DEBUG
+ printk("NEC: (%2x) %2li:%02li:%02li = %li\n",buf[8+14],min,sec,frame,sector);
if (sector) {
printk("sr_photocd: multisession CD detected. start: %lu\n",sector);
}
printk("sr_photocd: use TOSHIBA code\n");
#endif
- /* first I do a set_density-call (for reading XA-sectors) ... */
+ /* we request some disc information (is it a XA-CD ?,
+ where starts the last session ?) */
memset(buf,0,40);
- *((unsigned long*)buf) = 12;
- *((unsigned long*)buf+1) = 12;
- buf[8+0] = 0x15;
- buf[8+1] = (1 << 4);
- buf[8+4] = 12;
- buf[14+ 3] = 0x08;
- buf[14+ 4] = 0x83;
- buf[14+10] = 0x08;
+ *((unsigned long*)buf) = 0;
+ *((unsigned long*)buf+1) = 4; /* we receive 4 bytes from the drive */
+ cmd[0] = 0xc7;
+ cmd[1] = 3;
rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
SCSI_IOCTL_SEND_COMMAND, buf);
if (rc != 0) {
printk("sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc);
+ sector = 0;
+ break; /* if the first ioctl fails, we don't call the secound one */
+ }
+ is_xa = (rec[0] == 0x20);
+#ifdef DEBUG
+ printk("sr_photocd: TOSHIBA %x\n",rec[0]);
+#endif
+ min = (unsigned long) rec[1]/16*10 + (unsigned long) rec[1]%16;
+ sec = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16;
+ frame = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16;
+ sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
+ if (sector) {
+ sector -= CD_BLOCK_OFFSET;
+#ifdef DEBUG
+ printk("sr_photocd: multisession CD detected: start: %lu\n",sector);
+#endif
}
- /* ... and then I ask, if there is a multisession-Disk */
+ /* now we do a get_density... */
memset(buf,0,40);
*((unsigned long*)buf) = 0;
- *((unsigned long*)buf+1) = 4;
- buf[8+0] = 0xc7;
- buf[8+1] = 3;
+ *((unsigned long*)buf+1) = 12;
+ cmd[0] = 0x1a;
+ cmd[2] = 1;
+ cmd[4] = 12;
rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
SCSI_IOCTL_SEND_COMMAND, buf);
if (rc != 0) {
printk("sr_photocd: ioctl error (TOSHIBA #2): 0x%x\n",rc);
- sector = 0;
- } else {
- min = (unsigned long)buf[8+1]/16*10 + (unsigned long)buf[8+1]%16;
- sec = (unsigned long)buf[8+2]/16*10 + (unsigned long)buf[8+2]%16;
- frame = (unsigned long)buf[8+3]/16*10 + (unsigned long)buf[8+3]%16;
- sector = min*60*75 + sec*75 + frame;
- if (sector) {
- sector -= CD_BLOCK_OFFSET;
+ break;
+ }
+#ifdef DEBUG
+ printk("sr_photocd: get_density: 0x%x\n",rec[4]);
+#endif
+
+ /* ...and only if nessesary a set_density */
+ if ((rec[4] != 0x81 && is_xa) || (rec[4] != 0 && !is_xa)) {
#ifdef DEBUG
- printk("sr_photocd: multisession CD detected: start: %lu\n",sector);
+ printk("sr_photocd: doing set_density\n");
#endif
+ memset(buf,0,40);
+ *((unsigned long*)buf) = 12; /* sending 12 bytes... */
+ *((unsigned long*)buf+1) = 0;
+ cmd[0] = 0x15;
+ cmd[1] = (1 << 4);
+ cmd[4] = 12;
+ send = &cmd[6]; /* this is a 6-Byte command */
+ send[ 3] = 0x08; /* the data for the command */
+ send[ 4] = (is_xa) ? 0x81 : 0; /* density 0x81 for XA-CD's, 0 else */
+ send[10] = 0x08;
+ rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
+ SCSI_IOCTL_SEND_COMMAND, buf);
+ if (rc != 0) {
+ printk("sr_photocd: ioctl error (TOSHIBA #3): 0x%x\n",rc);
}
}
break;
return;
}
+#undef DEBUG
+
static int sr_open(struct inode * inode, struct file * filp)
{
if(MINOR(inode->i_rdev) >= sr_template.nr_dev ||
if (scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)
(*scsi_CDs[MINOR(inode->i_rdev)].device->host->hostt->usage_count)++;
-#if 1 /* don't use for now - it doesn't seem to work for everybody */
sr_photocd(inode);
-#endif
/* If this device did not have media in the drive at boot time, then
we would have been unable to get the sector size. Check to see if
and we have 2048 byte sectors. This code should work for buffers that
are any multiple of 512 bytes long. */
-#if 1
- /* Here we redirect the volume descriptor block of the CD-ROM.
- * Necessary for multisession CD's, until the isofs-routines
- * handle this via the CDROMMULTISESSION_SYS call
- */
- if (block >= 64 && block < 68) {
- block += scsi_CDs[dev].mpcd_sector*4; }
-#endif
-
SCpnt->use_sg = 0;
if (SCpnt->host->sg_tablesize > 0 &&
: : :"$1", "$16", "$17", "$22","$23","$24","$25")
/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT 13
-#define PGDIR_SHIFT 23
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PAGE_SHIFT 13
+#define PMD_SHIFT 23
+#define PGDIR_SHIFT 33
+
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PMD_SIZE (1UL << PMD_SHIFT)
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+
+#define PAGE_MASK (~(PAGE_SIZE-1))
+#define PMD_MASK (~(PMD_SIZE-1))
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
#ifdef __KERNEL__
#define PAGE_OFFSET 0xFFFFFC0000000000
-#define MAP_NR(addr) (((addr) - PAGE_OFFSET) >> PAGE_SHIFT)
+#define MAP_NR(addr) ((((unsigned long) (addr)) - PAGE_OFFSET) >> PAGE_SHIFT)
#define MAP_PAGE_RESERVED (1<<31)
typedef unsigned int mem_map_t;
* These are used to make use of C type-checking..
*/
typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
#define pte_val(x) ((x).pte)
+#define pmd_val(x) ((x).pmd)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
* .. while these make it easier on the compiler
*/
typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
typedef unsigned long pgd_t;
typedef unsigned long pgprot_t;
#define pte_val(x) (x)
+#define pmd_val(x) (x)
#define pgd_val(x) (x)
#define pgprot_val(x) (x)
* for zero-mapped memory areas etc..
*/
extern pte_t __bad_page(void);
-extern pte_t * __bad_pagetable(void);
+extern pmd_t * __bad_pagetable(void);
extern unsigned long __zero_page(void);
/* number of bits that fit into a memory pointer */
#define BITS_PER_PTR (8*sizeof(unsigned long))
-/* to mask away the intra-page address bits */
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
-/* to mask away the intra-page address bits */
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
-
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
#define PAGE_PTR(address) \
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-/* the no. of pointers that fit on a page */
-#define PTRS_PER_PAGE (PAGE_SIZE/sizeof(void*))
-
-/* to set the page-dir */
-extern inline void SET_PAGE_DIR(struct task_struct * tsk, pgd_t * pgdir)
-{
- tsk->tss.ptbr = ((unsigned long) pgdir - PAGE_OFFSET) >> PAGE_SHIFT;
- if (tsk == current)
- invalidate();
-}
+/* This one will go away */
+#define PTRS_PER_PAGE 1024
-/* to find an entry in a page-table-directory */
-extern inline pgd_t * PAGE_DIR_OFFSET(struct task_struct * tsk, unsigned long address)
-{
- return (pgd_t *) ((tsk->tss.ptbr << PAGE_SHIFT) + PAGE_OFFSET) +
- ((address >> 33) & PTR_MASK);
-}
+#define PTRS_PER_PTE 1024
+#define PTRS_PER_PMD 1024
+#define PTRS_PER_PGD 1024
extern unsigned long high_memory;
* and a page entry and page directory to the page they refer to.
*/
extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = (page << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; }
+{ pte_t pte; pte_val(pte) = ((page-PAGE_OFFSET) << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; }
extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
-extern inline void pgd_set(pgd_t * pgdp, pte_t * ptep)
-{ pgd_val(*pgdp) = _PAGE_TABLE | (((unsigned long) ptep) << (32-PAGE_SHIFT)); }
+extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
+{ pmd_val(*pmdp) = _PAGE_TABLE | ((((unsigned long) ptep) - PAGE_OFFSET) << (32-PAGE_SHIFT)); }
+
+extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
+{ pgd_val(*pgdp) = _PAGE_TABLE | ((((unsigned long) pmdp) - PAGE_OFFSET) << (32-PAGE_SHIFT)); }
-extern inline unsigned long pte_page(pte_t pte) { return (pte_val(pte) & _PFN_MASK) >> (32-PAGE_SHIFT); }
-extern inline unsigned long pgd_page(pgd_t pgd) { return (pgd_val(pgd) & _PFN_MASK) >> (32-PAGE_SHIFT); }
+extern inline unsigned long pte_page(pte_t pte)
+{ return PAGE_OFFSET + ((pte_val(pte) & _PFN_MASK) >> (32-PAGE_SHIFT)); }
+
+extern inline pte_t * pmd_page(pmd_t pmd)
+{ return (pte_t *) (PAGE_OFFSET + ((pmd_val(pmd) & _PFN_MASK) >> (32-PAGE_SHIFT))); }
+
+extern inline pmd_t * pgd_page(pgd_t pgd)
+{ return (pmd_t *) (PAGE_OFFSET + ((pgd_val(pgd) & _PFN_MASK) >> (32-PAGE_SHIFT))); }
extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; }
extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; }
+extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); }
+extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~_PFN_MASK) != _PAGE_TABLE || (unsigned long) pmd_page(pmd) > high_memory; }
+extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _PAGE_VALID; }
+extern inline void pmd_clear(pmd_t * pmdp) { pmd_val(*pmdp) = 0; }
+
extern inline int pgd_none(pgd_t pgd) { return !pgd_val(pgd); }
-extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~_PFN_MASK) != _PAGE_TABLE || pgd_page(pgd) > high_memory; }
+extern inline int pgd_bad(pgd_t pgd) { return (pgd_val(pgd) & ~_PFN_MASK) != _PAGE_TABLE || (unsigned long) pgd_page(pgd) > high_memory; }
extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) & _PAGE_VALID; }
extern inline void pgd_clear(pgd_t * pgdp) { pgd_val(*pgdp) = 0; }
extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= __ACCESS_BITS; return pte; }
extern inline pte_t pte_mkcow(pte_t pte) { pte_val(pte) |= _PAGE_COW; return pte; }
+/* to set the page-dir */
+extern inline void SET_PAGE_DIR(struct task_struct * tsk, pgd_t * pgdir)
+{
+ tsk->tss.ptbr = ((unsigned long) pgdir - PAGE_OFFSET) >> PAGE_SHIFT;
+ if (tsk == current)
+ invalidate();
+}
+
+/* to find an entry in a page-table-directory */
+extern inline pgd_t * PAGE_DIR_OFFSET(struct task_struct * tsk, unsigned long address)
+{
+ return (pgd_t *) ((tsk->tss.ptbr << PAGE_SHIFT) + PAGE_OFFSET) +
+ ((address >> 33) & (PTRS_PER_PGD - 1));
+}
+
+/* to find an entry in the second-level page-table-directory */
+extern inline pmd_t * PAGE_MIDDLE_OFFSET(pgd_t * dir, unsigned long address)
+{
+ return pgd_page(*dir) + ((address >> 23) & (PTRS_PER_PMD - 1));
+}
+
+/* to find an entry in the third-level page-table-directory */
+extern inline pte_t * PAGE_ENTRY_OFFSET(pmd_t * dir, unsigned long address)
+{
+ return pmd_page(*dir) + ((address >> 13) & (PTRS_PER_PTE - 1));
+}
+
+extern inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address)
+{
+ unsigned long page;
+
+ address = (address >> 13) & (PTRS_PER_PTE - 1);
+ if (pmd_none(*pmd)) {
+ pte_t *page = (pte_t *) get_free_page(GFP_KERNEL);
+ if (pmd_none(*pmd)) {
+ if (page) {
+ pmd_set(pmd, page);
+ return page + address;
+ }
+ pmd_set(pmd, BAD_PAGETABLE);
+ return NULL;
+ }
+ free_page((unsigned long) page);
+ }
+ if (pmd_bad(*pmd)) {
+ printk("pte_alloc: bad pmd\n");
+ pmd_set(pmd, BAD_PAGETABLE);
+ return NULL;
+ }
+ return pmd_page(*pmd) + address;
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
+{
+ unsigned long page;
+
+ address = (address >> 23) & (PTRS_PER_PMD - 1);
+ if (pgd_none(*pgd)) {
+ pmd_t *page = (pmd_t *) get_free_page(GFP_KERNEL);
+ if (pgd_none(*pgd)) {
+ if (page) {
+ pgd_set(pgd, page);
+ return page + address;
+ }
+ pgd_set(pgd, BAD_PAGETABLE);
+ return NULL;
+ }
+ free_page((unsigned long) page);
+ }
+ if (pgd_bad(*pgd)) {
+ printk("pmd_alloc: bad pgd\n");
+ pgd_set(pgd, BAD_PAGETABLE);
+ return NULL;
+ }
+ return pgd_page(*pgd) + address;
+}
+
#endif /* __KERNEL__ */
#endif /* _ALPHA_PAGE_H */