1//----------------------------------------------------------------------
2//  This software is part of the Haiku distribution and is covered
3//  by the MIT License.
4//
5//  Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
6//---------------------------------------------------------------------
7#ifndef _SCSI_MMC_H
8#define _SCSI_MMC_H
9
10/*!
11	\file scsi-mmc.h
12	SCSI-3 MMC support structures.
13
14	The protocols followed in this module are based on information
15	taken from the "SCSI-3 Multimedia Commands" draft, revision 10A.
16
17	The SCSI command of interest is "READ TOC/PMA/ATIP", command
18	number \c 0x43.
19
20	The format of interest for said command is "Full TOC", format
21	number \c 0x2.
22*/
23
24#include <errno.h>
25#include <new>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include <ByteOrder.h>
31#include <KernelExport.h>
32#include <scsi.h>
33
34#include "Debug.h"
35
36/*! \brief raw_device_command flags
37
38	This is the only combination of flags that works on my system. :-)
39*/
40const uint8 kScsiFlags = B_RAW_DEVICE_DATA_IN
41                           | B_RAW_DEVICE_REPORT_RESIDUAL
42                           | B_RAW_DEVICE_SHORT_READ_VALID;
43
44/*! \brief Timeout value used when making scsi commands
45
46	I'm honestly not sure what value to use here. It's currently
47	1 second because I got sick of waiting for the timeout while
48	figuring out how to get the commands to work.
49*/
50const uint32 kScsiTimeout = 1000000;
51
52//! SCSI "READ TOC/PMA/ATIP" command struct
53typedef struct {
54	uint8 command;		//!< 0x43 == READ TOC/PMA/ATIP
55	uint8 reserved2:1,
56	      msf:1,		//!< addressing format: 0 == LBA, 1 == MSF; try lba first, then msf if that fails
57	      reserved1:3,
58	      reserved0:3;
59	uint8 format:4,     //!< sub-command: 0x0 == "TOC", 0x1 == "Session Info", 0x2 == "Full TOC", ...
60	      reserved3:4;
61	uint8 reserved4;
62	uint8 reserved5;
63	uint8 reserved6;
64	uint8 number;		//!< track/session number
65	uint16 length;		//!< length of data buffer passed in raw_device_command.data; BIG-ENDIAN!!!
66	uint8 control;		//!< control codes; 0x0 should be fine
67} __attribute__((packed)) scsi_table_of_contents_command;
68
69// Some of the possible "READ TOC/PMA/ATIP" formats
70const uint8 kTableOfContentsFormat = 0x00;
71const uint8 kSessionFormat = 0x01;
72const uint8 kFullTableOfContentsFormat = 0x02;	//!< "READ TOC/PMA/ATIP" format of interest
73
74/*! \brief Minutes:Seconds:Frames format address
75
76	- Each msf frame corresponds to one logical block.
77	- Each msf second corresponds to 75 msf frames
78	- Each msf minute corresponds to 60 msf seconds
79	- Logical block 0 is at msf address 00:02:00
80*/
81typedef struct {
82	uint8 reserved;
83	uint8 minutes;
84	uint8 seconds;
85	uint8 frames;
86} msf_address;
87
88#define CDROM_FRAMES_PER_SECOND (75)
89#define CDROM_FRAMES_PER_MINUTE (CDROM_FRAMES_PER_SECOND*60)
90
91/*! \brief Returns an initialized \c msf_address struct
92*/
93static
94inline
95msf_address
96make_msf_address(uint8 minutes, uint8 seconds, uint8 frames)
97{
98	msf_address result;
99	result.reserved = 0;
100	result.minutes = minutes;
101	result.seconds = seconds;
102	result.frames = frames;
103	return result;
104}
105
106/*! \brief Converts the given msf address to lba format
107*/
108static
109inline
110off_t
111msf_to_lba(msf_address msf)
112{
113	return (CDROM_FRAMES_PER_MINUTE * msf.minutes)
114	       + (CDROM_FRAMES_PER_SECOND * msf.seconds)
115	       + msf.frames - 150;
116}
117
118/*! \brief Header for data returned by all formats of SCSI
119    "READ TOC/PMA/ATIP" command.
120*/
121typedef struct {
122	uint16 length;	//!< Length of data in reply (not including these 2 bytes); BIG ENDIAN!!!
123	uint8 first;	//!< First track/session in reply
124	uint8 last;		//!< Last track/session in reply
125} cdrom_table_of_contents_header;
126
127/*! \brief Type of entries returned by "READ TOC/PMA/ATIP" when called with format
128    \c kTableOfContentsFormat == 0x00
129*/
130typedef struct {
131	uint8 reserved0;
132	uint8 control:4,
133	      adr:4;
134	uint8 track_number;
135	uint8 reserved1;
136	uint32 address;
137} cdrom_table_of_contents_entry;
138
139/*! \brief Type of entries returned by "READ TOC/PMA/ATIP" when called with format
140    \c kFullTableOfContentsFormat == 0x02
141*/
142typedef struct {
143	uint8 session;
144	uint8 control:4,
145	      adr:4;
146	uint8 tno;
147	uint8 point;
148	uint8 minutes;
149	uint8 seconds;
150	uint8 frames;
151	uint8 zero;
152	uint8 pminutes;
153	uint8 pseconds;
154	uint8 pframes;
155} cdrom_full_table_of_contents_entry;
156
157/*! \brief Bitflags for control entries
158*/
159enum {
160	kControlDataTrack = 0x4,
161	kControlCopyPermitted = 0x2,
162};
163
164#endif	// _SCSI_MMC_H
165