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