Mail Archives: djgpp/1996/10/22/18:24:06
From: | Nuno Jesus <njesus AT cet DOT pt>
|
Newsgroups: | comp.os.msdos.djgpp
|
Subject: | segment:offset block buffer
|
Date: | Tue, 22 Oct 1996 15:38:15 +0200
|
Organization: | CET/PT
|
Lines: | 810
|
Message-ID: | <326CCE47.2AE6@cet.pt>
|
NNTP-Posting-Host: | briol.cet.pt
|
Mime-Version: | 1.0
|
CC: | djgpp AT delorie DOT com
|
To: | djgpp AT delorie DOT com
|
DJ-Gateway: | from newsgroup comp.os.msdos.djgpp
|
Hi, there. I don't know if you fed up with questions like
this one, but I'm new here and I'm having trouble with this:
I want to port the Borland C++ 3.1 source of a CD-Audio player
routines that I included here, into DJGPP. The only problem is
that I need to pass into the int 0x2F the adress of the block
that will serve as communication between my prog and the
interface. I just can't get a way to pass a segment:register
pair into a protected mode program, so I'm doomed. I know that
that in the past two days (at least), there was a similar
flow of questions with the tread Protected Mode -> Real Mode,
in wich I couldn't learn a thing! It's obscure (I think), and
I couldn't catch it. Can you Help, please?
Gratefull in advance...
/* CDROM AUDIO ROUTINES
By Barry Egerter
Written July 18, 1994
Using Borland C++ 3.1
Code : FREEWARE - alter and use at will.
Internet Email: barry DOT egerter AT softnet DOT com
*/
#include <dos.h>
#include <io.h>
#include <mem.h>
#include <fcntl.h>
#include "cdrom.h"
#define CDROM 0x21
#define EJECT_TRAY 0
#define RESET 2
#define CLOSE_TRAY 5
#define MEDIA_CHANGE 9
#define BUSY 512
#define TRACK_MASK 208
/*
struct playinfo {
unsigned char control;
unsigned char adr;
unsigned char track;
unsigned char index;
unsigned char min;
unsigned char sec;
unsigned char frame;
unsigned char zero;
unsigned char amin;
unsigned char asec;
unsigned char aframe;
};
typedef struct volumeinfo {
unsigned char mode;
unsigned char input0;
unsigned char volume0;
unsigned char input1;
unsigned char volume1;
unsigned char input2;
unsigned char volume2;
unsigned char input3;
unsigned char volume3;
};
struct {
unsigned short drives;
unsigned char first_drive;
unsigned short current_track;
unsigned long track_position;
unsigned char track_type;
unsigned char low_audio;
unsigned char high_audio;
unsigned char disk_length_min;
unsigned char disk_length_sec;
unsigned char disk_length_frames;
unsigned long endofdisk;
unsigned char upc[7];
unsigned char diskid[6];
unsigned long status;
unsigned short error; See description below
} cdrom_data;
*/
/* CDROM_DATA.ERROR Description
Bit 15 - Error bit
Bit 14-10 - Reserved
Bit 9 - Busy
Bit 8 - Done
Bit 7-0 - Error code (bit 15 on)
Error codes are the following:
0 Write-protect violation
1 Unknown unit
2 Drive not ready
3 Unknown command
4 CRC error
5 Bad drive request structure length
6 Seek error
7 Unknown media
8 Sector not found
9 Printer out of paper
A Write fault
B Read fault
C General failure
D Reserved
E Reserved
F Invalid disk change
*/
/* Multiplex Interrupt routines
"borrowed" from Ralf Brown's MSDOS Interrupt List v4.1
INT 21 - CD-ROM device driver - IOCTL INPUT
AX = 4402h
BX = file handle referencing character device for CD-ROM driver
CX = number of bytes to read
DS:DX -> control block (see #0563)
Return: CF clear if successful
AX = number of bytes actually read
CF set on error
AX = error code (01h,05h,06h,0Dh) (see #0770 at AH=59h)
Note: the data returned depends on the first byte of the control
block; the
remainder of the control block is filled by the driver
SeeAlso: AX=4403h"CD-ROM",INT 2F/AX=0802h
(Table 0562)
Values for CD-ROM data being requested:
00h device driver header address
01h drive head location
02h reserved
03h error statistics
04h audio channel info
05h raw drive bytes (uninterpreted and device-specific)
06h device status
07h sector size
08h volume size
09h media change status
0Ah audio disk info
0Bh audio track info
0Ch audio Q-Channel info
0Dh audio sub-channel info
0Eh UPC code
Format of CD-ROM control block:
Offset Size Description (Table 0563)
00h BYTE data being requested (see #0562)
---function 00h---
01h DWORD device driver header address (see also AH=52h)
---function 01h---
01h BYTE addressing mode
00h HSG
01h Red Book
02h DWORD current location of drive's head
logical sector number in HSG mode
frame/second/minute/unused in Red Book mode
(HSG sector = minute * 4500 + second * 75 + frame - 150)
---function 03h---
01h N BYTEs undefined as of 5 Aug 88 specification
---function 04h---
01h BYTE input channel (0-3) for output channel 0
02h BYTE volume for output channel 0
03h BYTE input channel (0-3) for output channel 1
04h BYTE volume for output channel 1
05h BYTE input channel (0-3) for output channel 2
06h BYTE volume for output channel 2
07h BYTE input channel (0-3) for output channel 3
08h BYTE volume for output channel 3
Notes: output channels 0 and 1 are left and right, 2 and 3 are left
prime and
right prime; a volume of 00h is off
the default setting is for each input channel to be assigned to
the
same-numbered output channel at full (FFh) volume
---function 05h---
01h BYTE number of bytes read
02h 128 BYTEs buffer for drive bytes
---function 06h---
01h DWORD device parameters (see #0564)
---function 07h---
01h BYTE read mode
00h cooked
01h raw
02h WORD sector size in bytes
---function 08h---
01h DWORD volume size in sectors
---function 09h---
01h BYTE media change status
00h don't know
01h media unchanged
FFh media has been changed
---function 0Ah---
01h BYTE lowest audio track number
02h BYTE highest audio track number
03h DWORD start address of lead-out track (Red Book format)
--function 0Bh---
01h BYTE track number (set by caller)
02h DWORD starting point of track (Red Book format)
06h BYTE track control info
bits 15,14,12: track type (notice: bits not contiguous!)
000 two audio channels, no pre-emphasis
001 two audio channels with pre-emphasis
010 data track
100 four audio channels, no pre-emphasis
101 four audio channels with pre-emphasis
other reserved
bit 13: digital copy permitted
---function 0Ch---
01h BYTE CONTROL and ADR byte (as received from drive)
02h BYTE track number
03h BYTE point or index
04h BYTE minute \
05h BYTE second > running time within track
06h BYTE frame /
07h BYTE zero
08h BYTE "AMIN" or "PMIN" \
09h BYTE "ASEC" or "PSEC" > running time on disk
0Ah BYTE "AFRAME" or "PFRAME" /
---function 0Dh---
01h DWORD starting frame address (Red Book format)
05h DWORD transfer address
09h DWORD number of sectors to read
Note: copies 96 bytes of sub-channel info per sector into buffer
---function 0Eh---
01h BYTE CONTROL and ADR byte
02h 7 BYTEs UPC/EAN code (13 BCD digits,low-order nybble of last
byte is 0)
09h BYTE zero
0Ah BYTE "AFRAME"
Bitfields for CD-ROM device parameters:
Bit(s) Description (Table 0564)
0 door open
1 door unlocked
2 supports raw reading in addition to cooked
3 writable
4 can play audio/video tracks
5 supports interleaving
6 reserved
7 supports prefetch requests
8 supports audio channel control
9 supports Red Book addressing in addition to HSG
10 audio is playing
*/
static union REGS inregs, outregs;
static struct SREGS sregs;
void device_request (void *block)
{
inregs.x.ax = 0x1510;
inregs.x.cx = cdrom_data.first_drive;
inregs.x.bx = block;
sregs.es = dos_ds;
int86x (0x2f, &inregs, &outregs, &sregs);
}
void red_book (unsigned long value, unsigned char *min, unsigned char
*sec, unsigned char *frame)
{
*frame = value & 0x000000ff;
*sec = (value & 0x0000ff00) >> 8;
*min = (value & 0x00ff0000) >> 16;
}
unsigned long hsg (unsigned long value)
{
unsigned char min, sec, frame;
red_book (value, &min, &sec, &frame);
value = (unsigned long)min * 4500;
value += (short)sec * 75;
value += frame - 150;
return value;
}
unsigned long cd_head_position (void)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned short sector;
unsigned long volid;
unsigned char unused[4];
} tray_request;
struct {
unsigned char mode;
unsigned char adr_mode;
unsigned long address;
} head_data;
tray_request.length = sizeof (tray_request);
tray_request.subunit = 0;
tray_request.comcode = 3;
tray_request.media = tray_request.sector = tray_request.volid = 0;
tray_request.address = (unsigned long)&head_data;
tray_request.bytes = 6;
head_data.mode = 0x01;
head_data.adr_mode = 0x00;
device_request (&tray_request);
cdrom_data.error = tray_request.status;
return head_data.address;
}
void cd_get_volume (struct volumeinfo *vol)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned short sector;
unsigned long volid;
} tray_request;
tray_request.length = sizeof (tray_request);
tray_request.subunit = 0;
tray_request.comcode = 3;
tray_request.media = 0;
tray_request.media = tray_request.sector = tray_request.volid = 0;
tray_request.address = (unsigned long)vol;
tray_request.bytes = 9;
vol->mode = 0x04;
device_request (&tray_request);
cdrom_data.error = tray_request.status;
}
void cd_set_volume (struct volumeinfo *vol)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned char unused[4];
} cd_request;
vol->mode = 3;
cd_request.length = sizeof (cd_request);
cd_request.subunit = 0;
cd_request.comcode = 12;
cd_request.media = 0;
cd_request.address = (unsigned long)vol;
cd_request.bytes = 9;
device_request (&cd_request);
cdrom_data.error = cd_request.status;
}
short cd_getupc (void)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned short sector;
unsigned long volid;
} tray_request;
struct {
unsigned char mode;
unsigned char adr;
unsigned char upc[7];
unsigned char zero;
unsigned char aframe;
} upc_data;
tray_request.length = sizeof (tray_request);
tray_request.subunit = 0;
tray_request.comcode = 3;
tray_request.media = 0;
tray_request.media = tray_request.sector = tray_request.volid = 0;
tray_request.address = (unsigned long)&upc_data;
tray_request.bytes = 11;
upc_data.mode = 0x0e;
upc_data.adr = 2;
device_request (&tray_request);
cdrom_data.error = tray_request.status;
if (upc_data.adr == 0)
memset (&upc_data.upc, 0, 7);
memcpy (&cdrom_data.upc[0], &upc_data.upc[0], 7);
return 1;
}
void cd_get_audio_info (void)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
long address;
short bytes;
short sector;
long volid;
} ioctli;
struct {
unsigned char mode;
unsigned char lowest;
unsigned char highest;
unsigned long address;
} track_data;
ioctli.length = sizeof (ioctli);
ioctli.subunit = 0;
ioctli.comcode = 3;
ioctli.media = 0;
ioctli.sector = 0;
ioctli.volid = 0;
ioctli.address = (long)&track_data;
ioctli.bytes = sizeof (track_data);
track_data.mode = 0x0a;
device_request (&ioctli);
memcpy (&cdrom_data.diskid, &track_data.lowest, 6);
cdrom_data.low_audio = track_data.lowest;
cdrom_data.high_audio = track_data.highest;
red_book (track_data.address, &cdrom_data.disk_length_min,
&cdrom_data.disk_length_sec, &cdrom_data.disk_length_frames);
cdrom_data.endofdisk = hsg (track_data.address);
cdrom_data.error = ioctli.status;
}
void cd_set_track (short tracknum)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned short sector;
unsigned long volid;
} tray_request;
struct {
unsigned char mode;
unsigned char track;
unsigned long address;
unsigned char control;
} track_data;
tray_request.length = sizeof (tray_request);
tray_request.subunit = 0;
tray_request.comcode = 3;
tray_request.media = 0;
tray_request.media = tray_request.sector = tray_request.volid = 0;
tray_request.address = (unsigned long)&track_data;
tray_request.bytes = 7;
track_data.mode = 0x0b;
track_data.track = tracknum;
device_request (&tray_request);
cdrom_data.error = tray_request.status;
cdrom_data.track_position = hsg (track_data.address);
cdrom_data.current_track = tracknum;
cdrom_data.track_type = track_data.control & TRACK_MASK;
}
unsigned long get_track_length (short tracknum)
{
unsigned long start, finish;
unsigned short ct;
ct = cdrom_data.current_track;
cd_set_track (tracknum);
start = cdrom_data.track_position;
if (tracknum < cdrom_data.high_audio)
{
cd_set_track (tracknum+1);
finish = cdrom_data.track_position;
}
else finish = cdrom_data.endofdisk;
cd_set_track (ct);
finish -= start;
return finish;
}
void cd_track_length (short tracknum, unsigned char *min, unsigned char
*sec, unsigned char *frame)
{
unsigned long value;
value = get_track_length (tracknum);
value += 150;
*frame = value % 75;
value -= *frame;
value /= 75;
*sec = value % 60;
value -= *sec;
value /= 60;
*min = value;
}
void cd_status (void)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned short sector;
unsigned long volid;
} tray_request;
struct {
unsigned char mode;
unsigned long status;
} cd_data;
tray_request.length = sizeof (tray_request);
tray_request.subunit = 0;
tray_request.comcode = 3;
tray_request.media = 0;
tray_request.media = tray_request.sector = tray_request.volid = 0;
tray_request.address = (unsigned long)&cd_data;
tray_request.bytes = 5;
cd_data.mode = 0x06;
device_request (&tray_request);
cdrom_data.status = cd_data.status;
cdrom_data.error = tray_request.status;
}
void cd_seek (unsigned long location)
{
unsigned char min, sec, frame;
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char addressmode;
unsigned long transfer;
unsigned short sectors;
unsigned long seekpos;
} play_request;
play_request.length = sizeof (play_request);
play_request.subunit = 0;
play_request.comcode = 131;
play_request.addressmode = 0;
play_request.transfer = 0;
play_request.sectors = 0;
play_request.seekpos = location;
device_request (&play_request);
cdrom_data.error = play_request.status;
}
void cd_play_audio (unsigned long begin, unsigned long end)
{
unsigned long leng;
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char addressmode;
unsigned long start;
unsigned long playlength;
} play_request;
play_request.length = sizeof (play_request);
play_request.subunit = 0;
play_request.comcode = 132;
play_request.addressmode = 0;
play_request.start = begin;
play_request.playlength = end-begin;
device_request (&play_request);
cdrom_data.error = play_request.status;
}
void cd_stop_audio (void)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
} stop_request;
stop_request.length = sizeof (stop_request);
stop_request.subunit = 0;
stop_request.comcode = 133;
device_request (&stop_request);
cdrom_data.error = stop_request.status;
}
void cd_resume_audio (void)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
} stop_request;
stop_request.length = sizeof (stop_request);
stop_request.subunit = 0;
stop_request.comcode = 136;
device_request (&stop_request);
cdrom_data.error = stop_request.status;
}
void cd_cmd (unsigned char mode)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned char unused[4];
} tray_request;
unsigned char cd_mode;
cd_mode = mode;
tray_request.length = sizeof (tray_request);
tray_request.subunit = 0;
tray_request.comcode = 12;
tray_request.media = 0;
tray_request.address = (unsigned long)&cd_mode;
tray_request.bytes = 1;
device_request (&tray_request);
cdrom_data.error = tray_request.status;
}
void cd_getpos (struct playinfo *info)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned short sector;
unsigned long volid;
} tray_request;
tray_request.length = sizeof (tray_request);
tray_request.subunit = 0;
tray_request.comcode = 3;
tray_request.media = 0;
tray_request.media = tray_request.sector = tray_request.volid = 0;
tray_request.address = (unsigned long)info;
tray_request.bytes = 6;
info->control = 12;
device_request (&tray_request);
cdrom_data.error = tray_request.status;
}
short cdrom_installed (void)
{
inregs.h.ah = 0x15;
inregs.h.al = 0x00;
inregs.x.bx = 0;
int86 (0x2f, &inregs, &outregs);
if (outregs.x.bx == 0)
return (0);
cdrom_data.drives = outregs.x.bx;
cdrom_data.first_drive = outregs.x.cx;
cd_get_audio_info ();
return (1);
}
short cd_done_play (void)
{
cd_cmd (CLOSE_TRAY);
return ((cdrom_data.error & BUSY) == 0);
}
short cd_mediach (void)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned short sector;
unsigned long volid;
} tray_request;
struct {
unsigned char mode;
unsigned char media;
} cd_data;
tray_request.length = sizeof (tray_request);
tray_request.subunit = 0;
tray_request.comcode = 3;
tray_request.media = 0;
tray_request.media = tray_request.sector = tray_request.volid = 0;
tray_request.address = (unsigned long)&cd_data;
tray_request.bytes = 2;
cd_data.mode = 0x09;
device_request (&tray_request);
cdrom_data.error = tray_request.status;
return cd_data.media;
}
void cd_lock (unsigned char doormode)
{
struct {
unsigned char length;
unsigned char subunit;
unsigned char comcode;
unsigned short status;
char ununsed[8];
unsigned char media;
unsigned long address;
unsigned short bytes;
unsigned char unused[4];
} tray_request;
struct {
unsigned char mode;
unsigned char media;
} cd_data;
tray_request.length = sizeof (tray_request);
tray_request.subunit = 0;
tray_request.comcode = 12;
tray_request.media = 0;
tray_request.address = (unsigned long)&cd_data;
tray_request.bytes = 2;
cd_data.mode = 1;
cd_data.media = doormode;
device_request (&tray_request);
cdrom_data.error = tray_request.status;
}
END.OF.MESSAGE
- Raw text -