From: Nuno Jesus Newsgroups: comp.os.msdos.djgpp Subject: segment:offset block buffer Date: Tue, 22 Oct 1996 15:39:38 +0200 Organization: CET/PT Lines: 810 Message-ID: <326CCE9A.68D2@cet.pt> NNTP-Posting-Host: briol.cet.pt Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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 #include #include #include #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