Previous 199869 Revisions Next

r25366 Tuesday 17th September, 2013 at 18:23:52 UTC by smf
Use virtual multiple inheritance to share command processing between SCSI & ATAPI instead of having a SCSI subdevice. This allows matsushita_cr589_device & gdrom_device to derive from atapi_cdrom_device. [smf]
[src/emu/machine]am53cf96.c atapicdr.c atapicdr.h atapihle.c atapihle.h cr589.c cr589.h machine.mak ncr539x.c scsicd.c scsicd.h scsihd.c scsihd.h scsihle.c scsihle.h t10mmc.c* t10mmc.h* t10sbc.c* t10sbc.h* t10spc.c* t10spc.h* wd33c93.c
[src/mame/drivers]firebeat.c ksys573.c
[src/mame/machine]gdrom.c gdrom.h
[src/mess/drivers]dccons.c
[src/mess/machine]acb4070.c acb4070.h d9060hd.c d9060hd.h fm_scsi.c mb89352.c ncr5380.c s1410.c s1410.h sa1403d.c sa1403d.h
[src/osd/windows]vconv.c

trunk/src/mame/drivers/firebeat.c
r25365r25366
17341734}
17351735
17361736static MACHINE_CONFIG_FRAGMENT( cdrom_config )
1737   MCFG_DEVICE_MODIFY("device:cdda")
1738   MCFG_SOUND_ROUTE(0, "^^^^^lspeaker", 1.0)
1739   MCFG_SOUND_ROUTE(1, "^^^^^rspeaker", 1.0)
1737   MCFG_DEVICE_MODIFY("cdda")
1738   MCFG_SOUND_ROUTE(0, "^^^^lspeaker", 1.0)
1739   MCFG_SOUND_ROUTE(1, "^^^^rspeaker", 1.0)
17401740MACHINE_CONFIG_END
17411741
17421742static MACHINE_CONFIG_START( firebeat, firebeat_state )
r25365r25366
17831783   MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
17841784   MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
17851785
1786//  TODO: Hookup cdrom audio
1787//  MCFG_SOUND_MODIFY("scsi1:cdda")
1788//  MCFG_SOUND_ROUTE(0, "^^lspeaker", 1.0)
1789//  MCFG_SOUND_ROUTE(1, "^^rspeaker", 1.0)
1790
17911786   MCFG_PC16552D_ADD("duart_com", firebeat_com0_interface, firebeat_com1_interface, XTAL_19_6608MHz) // pgmd to 9600baud
17921787   MCFG_PC16552D_ADD("duart_midi", firebeat_midi0_interface, firebeat_midi1_interface, XTAL_24MHz) // in all memory maps, pgmd to 31250baud
17931788MACHINE_CONFIG_END
r25365r25366
20662061   ROM_REGION(0xc0, "user2", 0)    // Security dongle
20672062   ROM_LOAD("gq977-ja", 0x00, 0xc0, BAD_DUMP CRC(55b5abdb) SHA1(d8da5bac005235480a1815bd0a79c3e8a63ebad1))
20682063
2069   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2064   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
20702065   DISK_IMAGE_READONLY( "977jaa01", 0, BAD_DUMP SHA1(59c03d8eb366167feef741d42d9d8b54bfeb3c1e) )
20712066
2072   DISK_REGION( "ata:1:cdrom:device" ) // audio CD-ROM
2067   DISK_REGION( "ata:1:cdrom" ) // audio CD-ROM
20732068   DISK_IMAGE_READONLY( "977jaa02", 0, SHA1(bd07c25ee3e1edc962997f6a5bb1700897231fb2) )
20742069ROM_END
20752070
r25365r25366
20802075   ROM_REGION(0xc0, "user2", 0)    // Security dongle
20812076   ROM_LOAD( "gqa11-ja",     0x000000, 0x0000c0, CRC(2ed8e2ae) SHA1(b8c3410dab643111b2d2027068175ba018a0a67e) )
20822077
2083   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2078   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
20842079   DISK_IMAGE_READONLY( "a11jaa01", 0, SHA1(539ec6f1c1d198b0d6ce5543eadcbb4d9917fa42) )
20852080
2086   DISK_REGION( "ata:1:cdrom:device" ) // audio CD-ROM
2081   DISK_REGION( "ata:1:cdrom" ) // audio CD-ROM
20872082   DISK_IMAGE_READONLY( "a11jaa02", 0, SHA1(575069570cb4a2b58b199a1329d45b189a20fcc9) )
20882083ROM_END
20892084
r25365r25366
20942089   ROM_REGION(0xc0, "user2", ROMREGION_ERASE00)    // Security dongle
20952090   ROM_LOAD("gq974-ja", 0x00, 0xc0, BAD_DUMP CRC(4578f29b) SHA1(faaeaf6357c1e86e898e7017566cfd2fc7ee3d6f))
20962091
2097   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2092   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
20982093   DISK_IMAGE_READONLY( "974jac01", 0, BAD_DUMP SHA1(c6145d7090e44c87f71ba626620d2ae2596a75ca) )
20992094
2100   DISK_REGION( "ata:1:cdrom:device" ) // audio CD-ROM
2095   DISK_REGION( "ata:1:cdrom" ) // audio CD-ROM
21012096   DISK_IMAGE_READONLY( "974jaa02", 1, BAD_DUMP SHA1(3b9946083239eb5687f66a49df24568bffa4fbbd) )
21022097ROM_END
21032098
r25365r25366
21082103   ROM_REGION(0xc0, "user2", ROMREGION_ERASE00)    // Security dongle
21092104   ROM_LOAD("gca01-ja", 0x00, 0xc0, BAD_DUMP CRC(2bda339d) SHA1(031cb3f44e7a89cd62a9ba948f3d19d53a325abd))
21102105
2111   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2106   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
21122107   DISK_IMAGE_READONLY( "a01jaa01", 0, BAD_DUMP SHA1(37bc3879719b3d3c6bc8a5691abd7aa4aec87d45) )
21132108
2114   DISK_REGION( "ata:1:cdrom:device" ) // audio CD-ROM
2109   DISK_REGION( "ata:1:cdrom" ) // audio CD-ROM
21152110   DISK_IMAGE_READONLY( "a01jaa02", 1, BAD_DUMP SHA1(a3fdeee0f85a7a9718c0fb1cc642ac22d3eff8db) )
21162111ROM_END
21172112
r25365r25366
21222117   ROM_REGION(0xc0, "user2", 0)    // Security dongle
21232118   ROM_LOAD("gca12-ja", 0x00, 0xc0, BAD_DUMP CRC(cf01dc15) SHA1(da8d208233487ebe65a0a9826fc72f1f459baa26))
21242119
2125   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2120   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
21262121   DISK_IMAGE_READONLY( "a12jaa01", 0, BAD_DUMP SHA1(10f2284248e51b1adf0fde173df72ad97fe0e5c8) )
21272122
2128   DISK_REGION( "ata:1:cdrom:device" ) // audio CD-ROM
2123   DISK_REGION( "ata:1:cdrom" ) // audio CD-ROM
21292124   DISK_IMAGE_READONLY( "a12jaa02", 1, BAD_DUMP SHA1(1256ce9d71350d355a256f83c7b319f0e6e84525) )
21302125ROM_END
21312126
r25365r25366
21392134   ROM_REGION(0x80000, "audiocpu", 0)          // SPU 68K program
21402135   ROM_LOAD16_WORD_SWAP("a02jaa04.3q", 0x00000, 0x80000, CRC(8c6000dd) SHA1(94ab2a66879839411eac6c673b25143d15836683))
21412136
2142   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2137   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
21432138   DISK_IMAGE_READONLY( "gq986jaa01", 0, SHA1(e5368ac029b0bdf29943ae66677b5521ae1176e1) )
21442139
2145   DISK_REGION( "ata:1:cdrom:device" ) // data DVD-ROM
2140   DISK_REGION( "ata:1:cdrom" ) // data DVD-ROM
21462141   DISK_IMAGE( "gq986jaa02", 1, SHA1(53367d3d5f91422fe386c42716492a0ae4332390) )
21472142ROM_END
21482143
r25365r25366
21562151   ROM_REGION(0x80000, "audiocpu", 0)          // SPU 68K program
21572152   ROM_LOAD16_WORD_SWAP( "a02jaa04.3q",  0x000000, 0x080000, CRC(8c6000dd) SHA1(94ab2a66879839411eac6c673b25143d15836683) )
21582153
2159   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2154   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
21602155   DISK_IMAGE_READONLY( "a04jaa01", 0, SHA1(87136ddad1d786b4d5f04381fcbf679ab666e6c9) )
21612156
2162   DISK_REGION( "ata:1:cdrom:device" ) // data DVD-ROM
2157   DISK_REGION( "ata:1:cdrom" ) // data DVD-ROM
21632158   DISK_IMAGE_READONLY( "a04jaa02", 1, SHA1(49a017dde76f84829f6e99a678524c40665c3bfd) )
21642159ROM_END
21652160
r25365r25366
21732168   ROM_REGION(0x80000, "audiocpu", 0)          // SPU 68K program
21742169   ROM_LOAD16_WORD_SWAP("a02jaa04.3q", 0x00000, 0x80000, CRC(8c6000dd) SHA1(94ab2a66879839411eac6c673b25143d15836683))
21752170
2176   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2171   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
21772172   DISK_IMAGE_READONLY( "gqa16jaa01", 0, SHA1(7a7e475d06c74a273f821fdfde0743b33d566e4c) )
21782173
2179   DISK_REGION( "ata:1:cdrom:device" ) // data DVD-ROM
2174   DISK_REGION( "ata:1:cdrom" ) // data DVD-ROM
21802175   DISK_IMAGE( "gqa16jaa02", 1, SHA1(e39067300e9440ff19cb98c1abc234fa3d5b26d1) )
21812176ROM_END
21822177
r25365r25366
21902185   ROM_REGION(0x80000, "audiocpu", 0)          // SPU 68K program
21912186   ROM_LOAD16_WORD_SWAP("a02jaa04.3q", 0x00000, 0x80000, CRC(8c6000dd) SHA1(94ab2a66879839411eac6c673b25143d15836683))
21922187
2193   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2188   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
21942189   DISK_IMAGE_READONLY( "b00jab01", 0, SHA1(259c733ca4d30281205b46b7bf8d60c9d01aa818) )
21952190
2196   DISK_REGION( "ata:1:cdrom:device" ) // data DVD-ROM
2191   DISK_REGION( "ata:1:cdrom" ) // data DVD-ROM
21972192   DISK_IMAGE_READONLY( "b00jaa02", 1, SHA1(c8ce2f8ee6aeeedef9c110a59e68fcec7b669ad6) )
21982193ROM_END
21992194
r25365r25366
22072202   ROM_REGION(0x80000, "audiocpu", 0)          // SPU 68K program
22082203   ROM_LOAD16_WORD_SWAP("a02jaa04.3q", 0x00000, 0x80000, CRC(8c6000dd) SHA1(94ab2a66879839411eac6c673b25143d15836683))
22092204
2210   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2205   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
22112206   DISK_IMAGE_READONLY( "gqb30jaa01", 0, SHA1(0ff3e40e3717ce23337b3a2438bdaca01cba9e30) )
22122207
2213   DISK_REGION( "ata:1:cdrom:device" ) // data DVD-ROM
2208   DISK_REGION( "ata:1:cdrom" ) // data DVD-ROM
22142209   DISK_IMAGE_READONLY( "gqb30jaa02", 1, SHA1(f067d502c23efe0267aada5706f5bc7a54605942) )
22152210ROM_END
22162211
r25365r25366
22242219   ROM_REGION(0x80000, "audiocpu", 0)          // SPU 68K program
22252220   ROM_LOAD16_WORD_SWAP("a02jaa04.3q", 0x00000, 0x80000, CRC(8c6000dd) SHA1(94ab2a66879839411eac6c673b25143d15836683))
22262221
2227   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2222   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
22282223   DISK_IMAGE_READONLY( "gea02jaa01", 0, SHA1(e81203b6812336c4d00476377193340031ef11b1) )
22292224
2230   DISK_REGION( "ata:1:cdrom:device" ) // data DVD-ROM
2225   DISK_REGION( "ata:1:cdrom" ) // data DVD-ROM
22312226   DISK_IMAGE_READONLY( "gea02jaa02", 1, SHA1(7212e399779f37a5dcb8317a8f635a3b3f620aa9) )
22322227ROM_END
22332228
r25365r25366
22382233   ROM_REGION(0xc0, "user2", ROMREGION_ERASE00)    // Security dongle
22392234   ROM_LOAD("gq977-ko", 0x00, 0xc0, BAD_DUMP CRC(ee743323) SHA1(2042e45879795557ad3cc21b37962f6bf54da60d))
22402235
2241   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2236   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
22422237   DISK_IMAGE_READONLY( "977kaa01", 0, BAD_DUMP SHA1(7af9f4949ffa10ea5fc18b6c88c2abc710df3cf9) )
22432238
2244   DISK_REGION( "ata:1:cdrom:device" ) // audio CD-ROM
2239   DISK_REGION( "ata:1:cdrom" ) // audio CD-ROM
22452240   DISK_IMAGE_READONLY( "977kaa02", 1, SHA1(0feb5ac56269ad4a8401fcfe3bb98b01a0169177) )
22462241ROM_END
22472242
r25365r25366
22522247   ROM_REGION(0xc0, "user2", ROMREGION_ERASE00)    // Security dongle
22532248   ROM_LOAD("gq977-ja", 0x00, 0xc0, BAD_DUMP CRC(55b5abdb) SHA1(d8da5bac005235480a1815bd0a79c3e8a63ebad1))
22542249
2255   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2250   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
22562251   DISK_IMAGE_READONLY( "gc977jaa01", 0, SHA1(7ed1f4b55105c93fec74468436bfb1d540bce944) )
22572252
2258   DISK_REGION( "ata:1:cdrom:device" ) // audio CD-ROM
2253   DISK_REGION( "ata:1:cdrom" ) // audio CD-ROM
22592254   DISK_IMAGE_READONLY( "gc977jaa02", 1, SHA1(74ce8c90575fd562807def7d561392d0f91f2bc6) )
22602255ROM_END
22612256
r25365r25366
22702265   ROM_REGION(0x80000, "audiocpu", 0)          // SPU 68K program
22712266   ROM_LOAD16_WORD_SWAP("a02jaa04.3q", 0x00000, 0x80000, BAD_DUMP CRC(8c6000dd) SHA1(94ab2a66879839411eac6c673b25143d15836683))
22722267
2273   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2268   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
22742269   DISK_IMAGE_READONLY( "gcb07jca01", 0, SHA1(f906379bdebee314e2ca97c7756259c8c25897fd) )
22752270
22762271   DISK_REGION( "ata:1:hdd:image" ) // data HDD
r25365r25366
22872282   ROM_REGION(0x80000, "audiocpu", 0)          // SPU 68K program
22882283   ROM_LOAD16_WORD_SWAP("a02jaa04.3q", 0x00000, 0x80000, BAD_DUMP CRC(8c6000dd) SHA1(94ab2a66879839411eac6c673b25143d15836683))
22892284
2290   DISK_REGION( "ata:0:cdrom:device" ) // program CD-ROM
2285   DISK_REGION( "ata:0:cdrom" ) // program CD-ROM
22912286   DISK_IMAGE_READONLY( "gcc01jca01", 0, SHA1(3e7af83670d791591ad838823422959987f7aab9) )
22922287
22932288   DISK_REGION( "ata:1:hdd:image" ) // data HDD
trunk/src/mame/drivers/ksys573.c
r25365r25366
829829      new_cdrom = m_available_cdroms[ 0 ];
830830   }
831831
832   scsihle_device *image = machine().device<scsihle_device>("ata:0:cr589:device");
832   atapi_hle_device *image = machine().device<atapi_hle_device>("ata:0:cr589");
833833   if (image != NULL)
834834   {
835835      void *current_cdrom = NULL;
r25365r25366
21042104SLOT_INTERFACE_END
21052105
21062106static MACHINE_CONFIG_FRAGMENT( cr589_config )
2107   MCFG_DEVICE_MODIFY("device:cdda")
2108   MCFG_SOUND_ROUTE(0, "^^^^^lspeaker", 1.0)
2109   MCFG_SOUND_ROUTE(1, "^^^^^rspeaker", 1.0)
2107   MCFG_DEVICE_MODIFY("cdda")
2108   MCFG_SOUND_ROUTE(0, "^^^^lspeaker", 1.0)
2109   MCFG_SOUND_ROUTE(1, "^^^^rspeaker", 1.0)
21102110MACHINE_CONFIG_END
21112111
21122112static MACHINE_CONFIG_START( konami573, ksys573_state )
trunk/src/mame/machine/gdrom.c
r25365r25366
44
55***************************************************************************/
66
7#include "emu.h"
8#include "machine/scsihle.h"
9#include "cdrom.h"
10#include "imagedev/chd_cd.h"
117#include "gdrom.h"
12#include "debugger.h"
138
149#define GDROM_BUSY_STATE    0x00
1510#define GDROM_PAUSE_STATE   0x01
r25365r25366
9186};
9287
9388
94static void phys_frame_to_msf(int phys_frame, int *m, int *s, int *f)
89void gdrom_device::device_reset()
9590{
96   *m = phys_frame / (60*75);
97   phys_frame -= (*m * 60 * 75);
98   *s = phys_frame / 75;
99   *f = phys_frame % 75;
100}
101
102// device type definition
103const device_type SCSI_GDROM = &device_creator<scsi_gdrom_device>;
104
105scsi_gdrom_device::scsi_gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
106   : scsihle_device(mconfig, SCSI_GDROM, "SCSI GDROM", tag, owner, clock, "scsi_gdrom", __FILE__),
107      m_cdda(*this, "cdda")
108{
109}
110
111void scsi_gdrom_device::device_start()
112{
113   save_item( NAME( lba ) );
114   save_item( NAME( blocks ) );
115   save_item( NAME( last_lba ) );
116   save_item( NAME( bytes_per_sector ) );
117   save_item( NAME( num_subblocks ) );
118   save_item( NAME( cur_subblock ) );
119   save_item( NAME( play_err_flag ) );
120}
121
122void scsi_gdrom_device::device_reset()
123{
124   scsihle_device::device_reset();
125
12691   static const UINT8 GDROM_Def_Cmd11_Reply[32] =
12792   {
12893      0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x19, 0x00, 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
r25365r25366
13297   for(int i = 0;i<32;i++)
13398      GDROM_Cmd11_Reply[i] = GDROM_Def_Cmd11_Reply[i];
13499
135   is_file = TRUE;
136   cdrom = subdevice<cdrom_image_device>("image")->get_cdrom_file();
137   if( !cdrom )
138   {
139      // try to locate the CHD from a DISK_REGION
140      chd_file *chd = get_disk_handle( machine(), tag() );
141      if( chd != NULL )
142      {
143         is_file = FALSE;
144         cdrom = cdrom_open( chd );
145      }
146   }
147
148   if (!cdrom)
149   {
150      logerror("GDROM: no CD found!\n");
151   }
152
153   lba = 0;
154   blocks = 0;
155   last_lba = 0;
156   bytes_per_sector = 2048;
157   num_subblocks = 1;
158   cur_subblock = 0;
159   play_err_flag = 0;
100   atapi_cdrom_device::device_reset();
160101}
161102
162void scsi_gdrom_device::device_stop()
163{
164   if (!is_file)
165   {
166      if( cdrom )
167      {
168         cdrom_close( cdrom );
169      }
170   }
171}
172
173cdrom_interface scsi_gdrom_device::cd_intf = { 0, 0 };
174
175static MACHINE_CONFIG_FRAGMENT(scsi_cdrom)
176   MCFG_CDROM_ADD("image", scsi_gdrom_device::cd_intf)
177   MCFG_SOUND_ADD("cdda", CDDA, 0)
178MACHINE_CONFIG_END
179
180machine_config_constructor scsi_gdrom_device::device_mconfig_additions() const
181{
182   return MACHINE_CONFIG_NAME(scsi_cdrom);
183}
184
185103// scsicd_exec_command
186104//
187105// Execute a SCSI command.
188106
189void scsi_gdrom_device::ExecCommand( int *transferLength )
107void gdrom_device::ExecCommand()
190108{
191   int trk;
192
193109   switch ( command[0] )
194110   {
195      case 0x03: // REQUEST SENSE
196         SetPhase( SCSI_PHASE_DATAIN );
197         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
198         break;
199
200111      case 0x11: // REQ_MODE
201         SetPhase( SCSI_PHASE_DATAIN );
112         m_phase = SCSI_PHASE_DATAIN;
202113         printf("REQ_MODE %02x %02x %02x %02x %02x %02x\n",
203114            command[0], command[1],
204115            command[2], command[3],
205116            command[4], command[5]);
206117//          if (SCSILengthFromUINT8( &command[ 4 ] ) < 32) return -1;
207118         transferOffset = command[2];
208         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
119         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
209120         break;
210121
211122      case 0x12: // INQUIRY
212123         logerror("GDROM: REQUEST SENSE\n");
213         SetPhase( SCSI_PHASE_DATAOUT );
124         m_phase = SCSI_PHASE_DATAOUT;
214125         //transferOffset = command[2];
215         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
126         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
216127         printf("SET_MODE %02x %02x\n",command[2],command[4]);
217128         break;
218129
219      case 0x15: // MODE SELECT(6)
220         logerror("GDROM: MODE SELECT(6) length %x control %x\n", command[4], command[5]);
221         SetPhase( SCSI_PHASE_DATAOUT );
222         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
223         break;
224
225      case 0x1a: // MODE SENSE(6)
226         SetPhase( SCSI_PHASE_DATAIN );
227         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
228         break;
229
230      case 0x1b: // START STOP UNIT
231         if (m_cdda != NULL)
232         {
233            m_cdda->stop_audio();
234         }
235         SetPhase( SCSI_PHASE_STATUS );
236         *transferLength = 0;
237         break;
238
239      case 0x1e: // PREVENT ALLOW MEDIUM REMOVAL
240         SetPhase( SCSI_PHASE_STATUS );
241         *transferLength = 0;
242         break;
243
244      case 0x25: // READ CAPACITY
245         SetPhase( SCSI_PHASE_DATAIN );
246         *transferLength = 8;
247         break;
248
249      case 0x28: // READ(10)
250
251         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
252         blocks = SCSILengthFromUINT16( &command[7] );
253
254         logerror("GDROM: READ(10) at LBA %x for %d blocks (%d bytes)\n", lba, blocks, blocks * bytes_per_sector);
255
256         if (num_subblocks > 1)
257         {
258            cur_subblock = lba % num_subblocks;
259            lba /= num_subblocks;
260         }
261         else
262         {
263            cur_subblock = 0;
264         }
265
266         if (m_cdda != NULL)
267         {
268            m_cdda->stop_audio();
269         }
270
271         SetPhase( SCSI_PHASE_DATAIN );
272         *transferLength = blocks * bytes_per_sector;
273         break;
274
275130      case 0x30: // CD_READ
276131         if (command[1] & 1)
277132         {
278133            fatalerror("GDROM: MSF mode used for CD_READ, unsupported\n");
279            *transferLength = 0;
134            m_transfer_length = 0;
280135         }
281136         else
282137         {
r25365r25366
296151               fatalerror("GDROM: Unhandled data_select %d\n", data_select);
297152            }
298153
299            printf("GDROM: CD_READ at LBA %x for %d blocks (%d bytes, read type %d, data select %d)\n", lba, blocks, blocks * bytes_per_sector, read_type, data_select);
154            printf("GDROM: CD_READ at LBA %x for %d blocks (%d bytes, read type %d, data select %d)\n", lba, blocks, blocks * m_sector_bytes, read_type, data_select);
300155
301156            if (num_subblocks > 1)
302157            {
r25365r25366
313168               m_cdda->stop_audio();
314169            }
315170
316            SetPhase( SCSI_PHASE_DATAIN );
317            *transferLength = blocks * bytes_per_sector;
171            m_phase = SCSI_PHASE_DATAIN;
172            m_transfer_length = blocks * m_sector_bytes;
318173         }
319174         break;
320175
321      case 0x42: // READ SUB-CHANNEL
322//                      logerror("GDROM: READ SUB-CHANNEL type %d\n", command[3]);
323         SetPhase( SCSI_PHASE_DATAIN );
324         *transferLength = SCSILengthFromUINT16( &command[ 7 ] );
325         break;
326
327      case 0x43: // READ TOC
328      {
329         int start_trk = command[6];
330         int end_trk = cdrom_get_last_track(cdrom);
331         int length;
332         int allocation_length = SCSILengthFromUINT16( &command[ 7 ] );
333
334         if( start_trk == 0 )
335         {
336            start_trk = 1;
337         }
338         if( start_trk == 0xaa )
339         {
340            end_trk = start_trk;
341         }
342
343         length = 4 + ( 8 * ( ( end_trk - start_trk ) + 1 ) );
344         if( length > allocation_length )
345         {
346            length = allocation_length;
347         }
348         else if( length < 4 )
349         {
350            length = 4;
351         }
352
353         if (m_cdda != NULL)
354         {
355            m_cdda->stop_audio();
356         }
357
358         SetPhase( SCSI_PHASE_DATAIN );
359         *transferLength = length;
360         //debugger_break(machine());
361         break;
362      }
363
364176      // READ TOC (GD-ROM ver.)
365177      case 0x14:
366178      {
r25365r25366
393205            m_cdda->stop_audio();
394206         }
395207
396         SetPhase( SCSI_PHASE_DATAIN );
397         *transferLength = length;
208         m_phase = SCSI_PHASE_DATAIN;
209         m_transfer_length = length;
398210         break;
399211      }
400212
401      case 0x45: // PLAY AUDIO(10)
402         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
403         blocks = SCSILengthFromUINT16( &command[7] );
404
405         // special cases: lba of 0 means MSF of 00:02:00
406         if (lba == 0)
407         {
408            lba = 150;
409         }
410         else if (lba == 0xffffffff)
411         {
412            logerror("GDROM: play audio from current not implemented!\n");
413         }
414
415         logerror("GDROM: PLAY AUDIO(10) at LBA %x for %x blocks\n", lba, blocks);
416
417         trk = cdrom_get_track(cdrom, lba);
418
419         if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
420         {
421            play_err_flag = 0;
422            if (m_cdda != NULL)
423               m_cdda->start_audio(lba, blocks);
424         }
425         else
426         {
427            logerror("GDROM: track is NOT audio!\n");
428            play_err_flag = 1;
429         }
430
431         SetPhase( SCSI_PHASE_STATUS );
432         *transferLength = 0;
433         break;
434
435      case 0x48: // PLAY AUDIO TRACK/INDEX
436         // be careful: tracks here are zero-based, but the SCSI command
437         // uses the real CD track number which is 1-based!
438         lba = cdrom_get_track_start(cdrom, command[4]-1);
439         blocks = cdrom_get_track_start(cdrom, command[7]-1) - lba;
440         if (command[4] > command[7])
441         {
442            blocks = 0;
443         }
444
445         if (command[4] == command[7])
446         {
447            blocks = cdrom_get_track_start(cdrom, command[4]) - lba;
448         }
449
450         if (blocks && cdrom)
451         {
452            if (m_cdda != NULL)
453               m_cdda->start_audio(lba, blocks);
454         }
455
456         logerror("GDROM: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], blocks);
457         SetPhase( SCSI_PHASE_STATUS );
458         *transferLength = 0;
459         break;
460
461      case 0x4b: // PAUSE/RESUME
462         if (cdrom)
463         {
464            if (m_cdda != NULL)
465               m_cdda->pause_audio((command[8] & 0x01) ^ 0x01);
466         }
467
468         logerror("GDROM: PAUSE/RESUME: %s\n", command[8]&1 ? "RESUME" : "PAUSE");
469         SetPhase( SCSI_PHASE_STATUS );
470         *transferLength = 0;
471         break;
472
473      case 0x55: // MODE SELECT(10)
474         logerror("GDROM: MODE SELECT length %x control %x\n", command[7]<<8 | command[8], command[1]);
475         SetPhase( SCSI_PHASE_DATAOUT );
476         *transferLength = SCSILengthFromUINT16( &command[ 7 ] );
477         break;
478
479      case 0x5a: // MODE SENSE(10)
480         SetPhase( SCSI_PHASE_DATAIN );
481         *transferLength = SCSILengthFromUINT16( &command[ 7 ] );
482         break;
483
484      case 0xa5: // PLAY AUDIO(12)
485         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
486         blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
487
488         // special cases: lba of 0 means MSF of 00:02:00
489         if (lba == 0)
490         {
491            lba = 150;
492         }
493         else if (lba == 0xffffffff)
494         {
495            logerror("GDROM: play audio from current not implemented!\n");
496         }
497
498         logerror("GDROM: PLAY AUDIO(12) at LBA %x for %x blocks\n", lba, blocks);
499
500         trk = cdrom_get_track(cdrom, lba);
501
502         if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
503         {
504            play_err_flag = 0;
505            if (m_cdda != NULL)
506               m_cdda->start_audio(lba, blocks);
507         }
508         else
509         {
510            logerror("GDROM: track is NOT audio!\n");
511            play_err_flag = 1;
512         }
513         SetPhase( SCSI_PHASE_STATUS );
514         *transferLength = 0;
515         break;
516
517      case 0xa8: // READ(12)
518         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
519         blocks = command[7]<<16 | command[8]<<8 | command[9];
520
521         logerror("GDROM: READ(12) at LBA %x for %x blocks (%x bytes)\n", lba, blocks, blocks * bytes_per_sector);
522
523         if (num_subblocks > 1)
524         {
525            cur_subblock = lba % num_subblocks;
526            lba /= num_subblocks;
527         }
528         else
529         {
530            cur_subblock = 0;
531         }
532
533         if (m_cdda != NULL)
534         {
535            m_cdda->stop_audio();
536         }
537
538         SetPhase( SCSI_PHASE_DATAIN );
539         *transferLength = blocks * bytes_per_sector;
540         break;
541
542      case 0xbb: // SET CD SPEED
543         logerror("GDROM: SET CD SPEED to %d kbytes/sec.\n", command[2]<<8 | command[3]);
544         SetPhase( SCSI_PHASE_STATUS );
545         *transferLength = 0;
546         break;
547
548213      case 0x70:
549         SetPhase( SCSI_PHASE_STATUS );
550         *transferLength = 0;
214         m_phase = SCSI_PHASE_STATUS;
215         m_transfer_length = 0;
551216         break;
552217
553218      case 0x71:
554         SetPhase( SCSI_PHASE_DATAIN );
555         *transferLength = sizeof(GDROM_Cmd71_Reply);
219         m_phase = SCSI_PHASE_DATAIN;
220         m_transfer_length = sizeof(GDROM_Cmd71_Reply);
556221         break;
557222
558223      case 0x40:
559224         if(command[1] & 0xf)
560225         {
561            SetPhase( SCSI_PHASE_DATAIN );
562            *transferLength = 0xe;
226            m_phase = SCSI_PHASE_DATAIN;
227            m_transfer_length = 0xe;
563228         }
564229         else
565230         {
r25365r25366
568233         break;
569234
570235      default:
571         scsihle_device::ExecCommand( transferLength );
236         t10mmc::ExecCommand();
572237         break;
573238   }
574239}
r25365r25366
577242//
578243// Read data from the device resulting from the execution of a command
579244
580void scsi_gdrom_device::ReadData( UINT8 *data, int dataLength )
245void gdrom_device::ReadData( UINT8 *data, int dataLength )
581246{
582247   int i;
583   UINT32 last_phys_frame;
584   UINT32 temp;
585248   UINT8 tmp_buffer[2048];
586249
587250   switch ( command[0] )
588251   {
589      case 0x03: // REQUEST SENSE
590         logerror("GDROM: Reading REQUEST SENSE data\n");
591
592         memset( data, 0, dataLength );
593
594         data[0] = 0x71; // deferred error
595
596         if (m_cdda != NULL && m_cdda->audio_active())
597         {
598            data[12] = 0x00;
599            data[13] = 0x11;    // AUDIO PLAY OPERATION IN PROGRESS
600         }
601         else if (play_err_flag)
602         {
603            play_err_flag = 0;
604            data[12] = 0x64;    // ILLEGAL MODE FOR THIS TRACK
605            data[13] = 0x00;
606         }
607         // (else 00/00 means no error to report)
608         break;
609
610252      case 0x11: // REQ_MODE
611253         printf("REQ_MODE: dataLength %d\n", dataLength);
612254         memcpy(data, &GDROM_Cmd11_Reply[transferOffset], (dataLength >= 32-transferOffset) ? 32-transferOffset : dataLength);
613255         break;
614256
615      case 0x25: // READ CAPACITY
616         logerror("GDROM: READ CAPACITY\n");
617
618         temp = cdrom_get_track_start(cdrom, 0xaa);
619         temp--; // return the last used block on the disc
620
621         data[0] = (temp>>24) & 0xff;
622         data[1] = (temp>>16) & 0xff;
623         data[2] = (temp>>8) & 0xff;
624         data[3] = (temp & 0xff);
625         data[4] = 0;
626         data[5] = 0;
627         data[6] = (bytes_per_sector>>8)&0xff;
628         data[7] = (bytes_per_sector & 0xff);
629         break;
630
631      case 0x28: // READ(10)
632      case 0xa8: // READ(12)
633         logerror("GDROM: read %x dataLength, \n", dataLength);
634         if ((cdrom) && (blocks))
635         {
636            while (dataLength > 0)
637            {
638               if (!cdrom_read_data(cdrom, lba, tmp_buffer, CD_TRACK_MODE1))
639               {
640                  logerror("GDROM: CD read error!\n");
641               }
642
643               logerror("True LBA: %d, buffer half: %d\n", lba, cur_subblock * bytes_per_sector);
644
645               memcpy(data, &tmp_buffer[cur_subblock * bytes_per_sector], bytes_per_sector);
646
647               cur_subblock++;
648               if (cur_subblock >= num_subblocks)
649               {
650                  cur_subblock = 0;
651
652                  lba++;
653                  blocks--;
654               }
655
656               last_lba = lba;
657               dataLength -= bytes_per_sector;
658               data += bytes_per_sector;
659            }
660         }
661         break;
662
663257      case 0x30: // CD_READ
664258         logerror("GDROM: read %x dataLength, \n", dataLength);
665259         if ((cdrom) && (blocks))
r25365r25366
671265                  logerror("GDROM: CD read error!\n");
672266               }
673267
674               logerror("True LBA: %d, buffer half: %d\n", lba, cur_subblock * bytes_per_sector);
268               logerror("True LBA: %d, buffer half: %d\n", lba, cur_subblock * m_sector_bytes);
675269
676               memcpy(data, &tmp_buffer[cur_subblock * bytes_per_sector], bytes_per_sector);
270               memcpy(data, &tmp_buffer[cur_subblock * m_sector_bytes], m_sector_bytes);
677271
678272               cur_subblock++;
679273               if (cur_subblock >= num_subblocks)
r25365r25366
685279               }
686280
687281               last_lba = lba;
688               dataLength -= bytes_per_sector;
689               data += bytes_per_sector;
282               dataLength -= m_sector_bytes;
283               data += m_sector_bytes;
690284            }
691285         }
692
693      case 0x42: // READ SUB-CHANNEL
694         switch (command[3])
695         {
696            case 1: // return current position
697            {
698               int audio_active;
699               int msf;
700
701               if (!cdrom)
702               {
703                  return;
704               }
705
706               logerror("GDROM: READ SUB-CHANNEL Time = %x, SUBQ = %x\n", command[1], command[2]);
707
708               msf = command[1] & 0x2;
709
710               audio_active = m_cdda != NULL && m_cdda->audio_active();
711               if (audio_active)
712               {
713                  if (m_cdda->audio_paused())
714                  {
715                     data[1] = 0x12;     // audio is paused
716                  }
717                  else
718                  {
719                     data[1] = 0x11;     // audio in progress
720                  }
721               }
722               else
723               {
724                  if (m_cdda != NULL && m_cdda->audio_ended())
725                  {
726                     data[1] = 0x13; // ended successfully
727                  }
728                  else
729                  {
730//                          data[1] = 0x14;    // stopped due to error
731                     data[1] = 0x15; // No current audio status to return
732                  }
733               }
734
735               // if audio is playing, get the latest LBA from the CDROM layer
736               if (audio_active)
737               {
738                  last_lba = m_cdda->get_audio_lba();
739               }
740               else
741               {
742                  last_lba = 0;
743               }
744
745               data[2] = 0;
746               data[3] = 12;       // data length
747               data[4] = 0x01; // sub-channel format code
748               data[5] = 0x10 | (audio_active ? 0 : 4);
749               data[6] = cdrom_get_track(cdrom, last_lba) + 1; // track
750               data[7] = 0;    // index
751
752               last_phys_frame = last_lba;
753
754               if (msf)
755               {
756                  int m,s,f;
757                  phys_frame_to_msf(last_phys_frame, &m, &s, &f);
758                  data[8] = 0;
759                  data[9] = m;
760                  data[10] = s;
761                  data[11] = f;
762               }
763               else
764               {
765                  data[8] = last_phys_frame>>24;
766                  data[9] = (last_phys_frame>>16)&0xff;
767                  data[10] = (last_phys_frame>>8)&0xff;
768                  data[11] = last_phys_frame&0xff;
769               }
770
771               last_phys_frame -= cdrom_get_track_start(cdrom, data[6] - 1);
772
773               if (msf)
774               {
775                  int m,s,f;
776                  phys_frame_to_msf(last_phys_frame, &m, &s, &f);
777                  data[12] = 0;
778                  data[13] = m;
779                  data[14] = s;
780                  data[15] = f;
781               }
782               else
783               {
784                  data[12] = last_phys_frame>>24;
785                  data[13] = (last_phys_frame>>16)&0xff;
786                  data[14] = (last_phys_frame>>8)&0xff;
787                  data[15] = last_phys_frame&0xff;
788               }
789               break;
790            }
791            default:
792               logerror("GDROM: Unknown subchannel type %d requested\n", command[3]);
793         }
794286         break;
795287
796      case 0x43: // READ TOC
797         /*
798             Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out.
799             That makes sense in terms of how real-world CDs are referred to, but
800             our internal routines for tracks use "0" as track 1.  That probably
801             should be fixed...
802         */
803         logerror("GDROM: READ TOC, format = %d time=%d\n", command[2]&0xf,(command[1]>>1)&1);
804         switch (command[2] & 0x0f)
805         {
806            case 0:     // normal
807               {
808                  int start_trk;
809                  int end_trk;
810                  int len;
811                  int in_len;
812                  int dptr;
813                  UINT32 tstart;
814
815                  start_trk = command[6];
816                  if( start_trk == 0 )
817                  {
818                     start_trk = 1;
819                  }
820
821                  end_trk = cdrom_get_last_track(cdrom);
822                  len = (end_trk * 8) + 2;
823
824                  // the returned TOC DATA LENGTH must be the full amount,
825                  // regardless of how much we're able to pass back due to in_len
826                  dptr = 0;
827                  data[dptr++] = (len>>8) & 0xff;
828                  data[dptr++] = (len & 0xff);
829                  data[dptr++] = 1;
830                  data[dptr++] = end_trk;
831
832                  if( start_trk == 0xaa )
833                  {
834                     end_trk = 0xaa;
835                  }
836
837                  in_len = command[7]<<8 | command[8];
838
839                  for (i = start_trk; i <= end_trk; i++)
840                  {
841                     int cdrom_track = i;
842                     if( cdrom_track != 0xaa )
843                     {
844                        cdrom_track--;
845                     }
846
847                     if( dptr >= in_len )
848                     {
849                        break;
850                     }
851
852                     data[dptr++] = 0;
853                     data[dptr++] = cdrom_get_adr_control(cdrom, cdrom_track);
854                     data[dptr++] = i;
855                     data[dptr++] = 0;
856
857                     tstart = cdrom_get_track_start(cdrom, cdrom_track);
858                     if ((command[1]&2)>>1)
859                        tstart = lba_to_msf(tstart);
860                     data[dptr++] = (tstart>>24) & 0xff;
861                     data[dptr++] = (tstart>>16) & 0xff;
862                     data[dptr++] = (tstart>>8) & 0xff;
863                     data[dptr++] = (tstart & 0xff);
864                  }
865               }
866               break;
867            default:
868               logerror("GDROM: Unhandled READ TOC format %d\n", command[2]&0xf);
869               break;
870         }
871         break;
872
873288      case 0x14: // READ TOC (GD-ROM ver.)
874289         /*
875290             Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out.
r25365r25366
947362         }
948363         break;
949364
950      case 0x1a: // MODE SENSE(6)
951      case 0x5a: // MODE SENSE(10)
952         logerror("GDROM: MODE SENSE page code = %x, PC = %x\n", command[2] & 0x3f, (command[2]&0xc0)>>6);
953
954         switch (command[2] & 0x3f)
955         {
956            case 0xe:   // CD Audio control page
957               data[0] = 0x8e; // page E, parameter is savable
958               data[1] = 0x0e; // page length
959               data[2] = 0x04; // IMMED = 1, SOTC = 0
960               data[3] = data[4] = data[5] = data[6] = data[7] = 0; // reserved
961
962               // connect each audio channel to 1 output port
963               data[8] = 1;
964               data[10] = 2;
965               data[12] = 4;
966               data[14] = 8;
967
968               // indicate max volume
969               data[9] = data[11] = data[13] = data[15] = 0xff;
970               break;
971
972            default:
973               logerror("GDROM: MODE SENSE unknown page %x\n", command[2] & 0x3f);
974               break;
975         }
976         break;
977
978365      case 0x71:
979366         memcpy(data, &GDROM_Cmd71_Reply[0], sizeof(GDROM_Cmd71_Reply));
980367         break;
r25365r25366
997384         break;
998385
999386      default:
1000         scsihle_device::ReadData( data, dataLength );
387         t10mmc::ReadData( data, dataLength );
1001388         break;
1002389   }
1003390}
r25365r25366
1006393//
1007394// Write data to the CD-ROM device as part of the execution of a command
1008395
1009void scsi_gdrom_device::WriteData( UINT8 *data, int dataLength )
396void gdrom_device::WriteData( UINT8 *data, int dataLength )
1010397{
1011398   switch (command[ 0 ])
1012399   {
1013      case 0x15: // MODE SELECT(6)
1014      case 0x55: // MODE SELECT(10)
1015         logerror("GDROM: MODE SELECT page %x\n", data[0] & 0x3f);
1016
1017         switch (data[0] & 0x3f)
1018         {
1019            case 0x0:   // vendor-specific
1020               // check for SGI extension to force 512-byte blocks
1021               if ((data[3] == 8) && (data[10] == 2))
1022               {
1023                  logerror("GDROM: Experimental SGI 512-byte block extension enabled\n");
1024
1025                  bytes_per_sector = 512;
1026                  num_subblocks = 4;
1027               }
1028               else
1029               {
1030                  logerror("GDROM: Unknown vendor-specific page!\n");
1031               }
1032               break;
1033
1034            case 0xe:   // audio page
1035               logerror("Ch 0 route: %x vol: %x\n", data[8], data[9]);
1036               logerror("Ch 1 route: %x vol: %x\n", data[10], data[11]);
1037               logerror("Ch 2 route: %x vol: %x\n", data[12], data[13]);
1038               logerror("Ch 3 route: %x vol: %x\n", data[14], data[15]);
1039               break;
1040         }
1041         break;
1042
1043400      case 0x12:
1044401         memcpy(&GDROM_Cmd11_Reply[transferOffset], data, (dataLength >= 32-transferOffset) ? 32-transferOffset : dataLength);
1045402         break;
1046403
1047404      default:
1048         scsihle_device::WriteData( data, dataLength );
405         t10mmc::WriteData( data, dataLength );
1049406         break;
1050407   }
1051408}
1052409
1053void scsi_gdrom_device::GetDevice( void **_cdrom )
1054{
1055   *(cdrom_file **)_cdrom = cdrom;
1056}
1057
1058void scsi_gdrom_device::SetDevice( void *_cdrom )
1059{
1060   cdrom = (cdrom_file *) _cdrom;
1061}
1062
1063int scsi_gdrom_device::GetSectorBytes()
1064{
1065   return bytes_per_sector;
1066}
1067
1068410// device type definition
1069411const device_type GDROM = &device_creator<gdrom_device>;
1070412
1071gdrom_device::gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
1072   : atapi_hle_device(mconfig, GDROM, "GDROM", tag, owner, clock, "gdrom", __FILE__)
413gdrom_device::gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
414   atapi_cdrom_device(mconfig, GDROM, "GDROM", tag, owner, clock, "gdrom", __FILE__)
1073415{
1074416}
1075417
1076static MACHINE_CONFIG_FRAGMENT( gdrom )
1077   MCFG_DEVICE_ADD("device", SCSI_GDROM, 0)
1078MACHINE_CONFIG_END
1079
1080//-------------------------------------------------
1081//  machine_config_additions - device-specific
1082//  machine configurations
1083//-------------------------------------------------
1084
1085machine_config_constructor gdrom_device::device_mconfig_additions() const
1086{
1087   return MACHINE_CONFIG_NAME( gdrom );
1088}
1089
1090418void gdrom_device::device_start()
1091419{
420   save_item(NAME(read_type));
421   save_item(NAME(data_select));
422   save_item(NAME(transferOffset));
423
424   /// TODO: split identify buffer into another method as device_start() should be called after it's filled in, but the atapi_cdrom_device has it's own.
425   atapi_cdrom_device::device_start();
426
1092427   memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
1093428
1094429   m_identify_buffer[0] = 0x8600; // ATAPI device, cmd set 6 compliant, DRQ within 3 ms of PACKET command
r25365r25366
1123458
1124459   m_identify_buffer[63]=7; // multi word dma mode 0-2 supported
1125460   m_identify_buffer[64]=1; // PIO mode 3 supported
1126
1127   atapi_hle_device::device_start();
1128461}
1129462
1130void gdrom_device::perform_diagnostic()
1131{
1132   m_error = IDE_ERROR_DIAGNOSTIC_PASSED;
1133}
1134
1135463void gdrom_device::process_buffer()
1136464{
1137465   atapi_hle_device::process_buffer();
1138466   m_sector_number = 0x80 | GDROM_PAUSE_STATE; /// HACK: find out when this should be updated
1139467}
1140
1141void gdrom_device::identify_packet_device()
1142{
1143}
trunk/src/mame/machine/gdrom.h
r25365r25366
77#ifndef _GDROM_H_
88#define _GDROM_H_
99
10#include "machine/atapihle.h"
11#include "machine/scsihle.h"
12#include "sound/cdda.h"
13#include "cdrom.h"
10#include "machine/atapicdr.h"
1411
15// Sega GD-ROM handler
16class scsi_gdrom_device : public scsihle_device
12class gdrom_device : public atapi_cdrom_device
1713{
1814public:
19   // construction/destruction
20   scsi_gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
21   virtual machine_config_constructor device_mconfig_additions() const;
15   gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
2216
23   virtual void SetDevice( void *device );
24   virtual void GetDevice( void **device );
25   virtual void ExecCommand( int *transferLength );
17   // Sega GD-ROM handler
18
19   virtual void ExecCommand();
2620   virtual void WriteData( UINT8 *data, int dataLength );
2721   virtual void ReadData( UINT8 *data, int dataLength );
28   virtual int GetSectorBytes();
2922
30   static struct cdrom_interface cd_intf;
31
3223protected:
24   virtual void process_buffer();
25
3326   // device-level overrides
3427   virtual void device_start();
3528   virtual void device_reset();
36   virtual void device_stop();
3729
3830private:
39   UINT32 lba;
40   UINT32 blocks;
41   UINT32 last_lba;
42   UINT32 bytes_per_sector;
43   UINT32 num_subblocks;
44   UINT32 cur_subblock;
45   UINT32 play_err_flag;
31   UINT8 GDROM_Cmd11_Reply[32];
4632   UINT32 read_type;   // for command 0x30 only
4733   UINT32 data_select; // for command 0x30 only
4834   UINT32 transferOffset;
49   cdrom_file *cdrom;
50   required_device<cdda_device> m_cdda;
51   bool is_file;
52   UINT8 GDROM_Cmd11_Reply[32];
5335};
5436
5537// device type definition
56extern const device_type SCSI_GDROM;
57
58class gdrom_device : public atapi_hle_device
59{
60public:
61   gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
62
63protected:
64   // device-level overrides
65   virtual machine_config_constructor device_mconfig_additions() const;
66   virtual void device_start();
67
68   virtual void perform_diagnostic();
69   virtual void identify_packet_device();
70   virtual void process_buffer();
71};
72
73// device type definition
7438extern const device_type GDROM;
7539
7640#endif
trunk/src/osd/windows/vconv.c
r25365r25366
103103   { 0,        "-fomit-frame-pointer",     "" },
104104   { 0,        "-Werror",                  "/WX" },
105105   //{ VS7,        "-Wall",                    "/Wall /W3 /wd4003 /wd4018 /wd4146 /wd4242 /wd4244 /wd4619 /wd4702 /wd4706 /wd4710 /wd4711 /wd4738 /wd4826" },
106   { VS7,      "-Wall",                    "/Wall /W4 /wd4003 /wd4018 /wd4146 /wd4242 /wd4244 /wd4619 /wd4702 /wd4706 /wd4710 /wd4711 /wd4738 /wd4826 /wd4820 /wd4514 /wd4668 /wd4127 /wd4625 /wd4626 /wd4512 /wd4100 /wd4310 /wd4571 /wd4061 /wd4131 /wd4255 /wd4510 /wd4610 /wd4505 /wd4324 /wd4611 /wd4201 /wd4189 /wd4296 /wd4986 /wd4347 /wd4987" },
106   { VS7,      "-Wall",                    "/Wall /W4 /wd4003 /wd4018 /wd4146 /wd4242 /wd4244 /wd4619 /wd4702 /wd4706 /wd4710 /wd4711 /wd4738 /wd4826 /wd4820 /wd4514 /wd4668 /wd4127 /wd4625 /wd4626 /wd4512 /wd4100 /wd4310 /wd4571 /wd4061 /wd4131 /wd4255 /wd4510 /wd4610 /wd4505 /wd4324 /wd4611 /wd4201 /wd4189 /wd4296 /wd4986 /wd4347 /wd4987 /wd4250 /wd4435" },
107107   { 0,        "-Wall",                    "/W0" },
108108   { VS7,      "-Wno-unused",              "/wd4100 /wd4101 /wd4102 /wd4505" },
109109   { 0,        "-Wno-sign-compare",        "/wd4365 /wd4389 /wd4245" },
trunk/src/emu/machine/scsicd.c
r25365r25366
11/***************************************************************************
22
3 scsicd.c - Implementation of a SCSI CD-ROM device, using MAME's cdrom.c primitives
3 scsicd.c - Implementation of a SCSI CD-ROM device
44
55***************************************************************************/
66
7#include "emu.h"
8#include "machine/scsihle.h"
9#include "cdrom.h"
10#include "imagedev/chd_cd.h"
117#include "scsicd.h"
128
13static void phys_frame_to_msf(int phys_frame, int *m, int *s, int *f)
14{
15   *m = phys_frame / (60*75);
16   phys_frame -= (*m * 60 * 75);
17   *s = phys_frame / 75;
18   *f = phys_frame % 75;
19}
20
219// device type definition
2210const device_type SCSICD = &device_creator<scsicd_device>;
2311
24scsicd_device::scsicd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
25   : scsihle_device(mconfig, SCSICD, "SCSICD", tag, owner, clock, "scsicd", __FILE__),
26   m_cdda(*this, "cdda")
12scsicd_device::scsicd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
13   scsihle_device(mconfig, SCSICD, "SCSICD", tag, owner, clock, "scsicd", __FILE__)
2714{
2815}
2916
3017scsicd_device::scsicd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
31   scsihle_device(mconfig, type, name, tag, owner, clock, shortname, source),
32   m_cdda(*this, "cdda")
18   scsihle_device(mconfig, type, name, tag, owner, clock, shortname, source)
3319{
3420}
3521
3622void scsicd_device::device_start()
3723{
38   scsihle_device::device_start();
24   m_image = subdevice<cdrom_image_device>("image");
25   m_cdda = subdevice<cdda_device>("cdda");
3926
40   save_item( NAME( lba ) );
41   save_item( NAME( blocks ) );
42   save_item( NAME( last_lba ) );
43   save_item( NAME( bytes_per_sector ) );
44   save_item( NAME( num_subblocks ) );
45   save_item( NAME( cur_subblock ) );
46   save_item( NAME( play_err_flag ) );
27   scsihle_device::device_start();
4728}
4829
49void scsicd_device::device_reset()
50{
51   scsihle_device::device_reset();
52
53   SetDevice( subdevice<cdrom_image_device>("image")->get_cdrom_file() );
54   if( !cdrom )
55   {
56      logerror( "SCSICD %s: no CD found!\n", tag() );
57   }
58
59   lba = 0;
60   blocks = 0;
61   last_lba = 0;
62   bytes_per_sector = 2048;
63   num_subblocks = 1;
64   cur_subblock = 0;
65   play_err_flag = 0;
66}
67
6830cdrom_interface scsicd_device::cd_intf = { "cdrom", NULL };
6931
7032static MACHINE_CONFIG_FRAGMENT(scsi_cdrom)
r25365r25366
7638{
7739   return MACHINE_CONFIG_NAME(scsi_cdrom);
7840}
79
80// scsicd_exec_command
81//
82// Execute a SCSI command.
83
84void scsicd_device::ExecCommand( int *transferLength )
85{
86   int trk;
87
88   switch ( command[0] )
89   {
90      case 0x03: // REQUEST SENSE
91         SetPhase( SCSI_PHASE_DATAIN );
92         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
93         break;
94
95      case 0x12: // INQUIRY
96         logerror("SCSICD: REQUEST SENSE\n");
97         SetPhase( SCSI_PHASE_DATAIN );
98         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
99         break;
100
101      case 0x15: // MODE SELECT(6)
102         logerror("SCSICD: MODE SELECT(6) length %x control %x\n", command[4], command[5]);
103         SetPhase( SCSI_PHASE_DATAOUT );
104         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
105         break;
106
107      case 0x1a: // MODE SENSE(6)
108         SetPhase( SCSI_PHASE_DATAIN );
109         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
110         break;
111
112      case 0x1b: // START STOP UNIT
113         m_cdda->stop_audio();
114         SetPhase( SCSI_PHASE_STATUS );
115         *transferLength = 0;
116         break;
117
118      case 0x1e: // PREVENT ALLOW MEDIUM REMOVAL
119         SetPhase( SCSI_PHASE_STATUS );
120         *transferLength = 0;
121         break;
122
123      case 0x25: // READ CAPACITY
124         SetPhase( SCSI_PHASE_DATAIN );
125         *transferLength = 8;
126         break;
127
128      case 0x28: // READ(10)
129
130         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
131         blocks = SCSILengthFromUINT16( &command[7] );
132
133         logerror("SCSICD: READ(10) at LBA %x for %d blocks (%d bytes)\n", lba, blocks, blocks * bytes_per_sector);
134
135         if (num_subblocks > 1)
136         {
137            cur_subblock = lba % num_subblocks;
138            lba /= num_subblocks;
139         }
140         else
141         {
142            cur_subblock = 0;
143         }
144
145         m_cdda->stop_audio();
146
147         SetPhase( SCSI_PHASE_DATAIN );
148         *transferLength = blocks * bytes_per_sector;
149         break;
150
151      case 0x42: // READ SUB-CHANNEL
152//                      logerror("SCSICD: READ SUB-CHANNEL type %d\n", command[3]);
153         SetPhase( SCSI_PHASE_DATAIN );
154         *transferLength = SCSILengthFromUINT16( &command[ 7 ] );
155         break;
156
157      case 0x43: // READ TOC
158      {
159         int start_trk = command[6];
160         int end_trk = cdrom_get_last_track(cdrom);
161         int length;
162         int allocation_length = SCSILengthFromUINT16( &command[ 7 ] );
163
164         if( start_trk == 0 )
165         {
166            start_trk = 1;
167         }
168         if( start_trk == 0xaa )
169         {
170            end_trk = start_trk;
171         }
172
173         length = 4 + ( 8 * ( ( end_trk - start_trk ) + 1 ) );
174         if( length > allocation_length )
175         {
176            length = allocation_length;
177         }
178         else if( length < 4 )
179         {
180            length = 4;
181         }
182
183         m_cdda->stop_audio();
184
185         SetPhase( SCSI_PHASE_DATAIN );
186         *transferLength = length;
187         break;
188      }
189      case 0x45: // PLAY AUDIO(10)
190         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
191         blocks = SCSILengthFromUINT16( &command[7] );
192
193         // special cases: lba of 0 means MSF of 00:02:00
194         if (lba == 0)
195         {
196            lba = 150;
197         }
198         else if (lba == 0xffffffff)
199         {
200            logerror("SCSICD: play audio from current not implemented!\n");
201         }
202
203         logerror("SCSICD: PLAY AUDIO(10) at LBA %x for %x blocks\n", lba, blocks);
204
205         trk = cdrom_get_track(cdrom, lba);
206
207         if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
208         {
209            play_err_flag = 0;
210            m_cdda->start_audio(lba, blocks);
211         }
212         else
213         {
214            logerror("SCSICD: track is NOT audio!\n");
215            play_err_flag = 1;
216         }
217
218         SetPhase( SCSI_PHASE_STATUS );
219         *transferLength = 0;
220         break;
221
222      case 0x48: // PLAY AUDIO TRACK/INDEX
223         // be careful: tracks here are zero-based, but the SCSI command
224         // uses the real CD track number which is 1-based!
225         lba = cdrom_get_track_start(cdrom, command[4]-1);
226         blocks = cdrom_get_track_start(cdrom, command[7]-1) - lba;
227         if (command[4] > command[7])
228         {
229            blocks = 0;
230         }
231
232         if (command[4] == command[7])
233         {
234            blocks = cdrom_get_track_start(cdrom, command[4]) - lba;
235         }
236
237         if (blocks && cdrom)
238         {
239            m_cdda->start_audio(lba, blocks);
240         }
241
242         logerror("SCSICD: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], blocks);
243         SetPhase( SCSI_PHASE_STATUS );
244         *transferLength = 0;
245         break;
246
247      case 0x4b: // PAUSE/RESUME
248         if (cdrom)
249         {
250            m_cdda->pause_audio((command[8] & 0x01) ^ 0x01);
251         }
252
253         logerror("SCSICD: PAUSE/RESUME: %s\n", command[8]&1 ? "RESUME" : "PAUSE");
254         SetPhase( SCSI_PHASE_STATUS );
255         *transferLength = 0;
256         break;
257
258      case 0x4e: // STOP
259         if (cdrom)
260         {
261            m_cdda->stop_audio();
262         }
263
264         logerror("SCSICD: STOP_PLAY_SCAN\n");
265         SetPhase( SCSI_PHASE_STATUS );
266         *transferLength = 0;
267         break;
268
269      case 0x55: // MODE SELECT(10)
270         logerror("SCSICD: MODE SELECT length %x control %x\n", command[7]<<8 | command[8], command[1]);
271         SetPhase( SCSI_PHASE_DATAOUT );
272         *transferLength = SCSILengthFromUINT16( &command[ 7 ] );
273         break;
274
275      case 0x5a: // MODE SENSE(10)
276         SetPhase( SCSI_PHASE_DATAIN );
277         *transferLength = SCSILengthFromUINT16( &command[ 7 ] );
278         break;
279
280      case 0xa5: // PLAY AUDIO(12)
281         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
282         blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
283
284         // special cases: lba of 0 means MSF of 00:02:00
285         if (lba == 0)
286         {
287            lba = 150;
288         }
289         else if (lba == 0xffffffff)
290         {
291            logerror("SCSICD: play audio from current not implemented!\n");
292         }
293
294         logerror("SCSICD: PLAY AUDIO(12) at LBA %x for %x blocks\n", lba, blocks);
295
296         trk = cdrom_get_track(cdrom, lba);
297
298         if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
299         {
300            play_err_flag = 0;
301            m_cdda->start_audio(lba, blocks);
302         }
303         else
304         {
305            logerror("SCSICD: track is NOT audio!\n");
306            play_err_flag = 1;
307         }
308         SetPhase( SCSI_PHASE_STATUS );
309         *transferLength = 0;
310         break;
311
312      case 0xa8: // READ(12)
313         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
314         blocks = command[7]<<16 | command[8]<<8 | command[9];
315
316         logerror("SCSICD: READ(12) at LBA %x for %x blocks (%x bytes)\n", lba, blocks, blocks * bytes_per_sector);
317
318         if (num_subblocks > 1)
319         {
320            cur_subblock = lba % num_subblocks;
321            lba /= num_subblocks;
322         }
323         else
324         {
325            cur_subblock = 0;
326         }
327
328         m_cdda->stop_audio();
329
330         SetPhase( SCSI_PHASE_DATAIN );
331         *transferLength = blocks * bytes_per_sector;
332         break;
333
334      case 0xbb: // SET CD SPEED
335         logerror("SCSICD: SET CD SPEED to %d kbytes/sec.\n", command[2]<<8 | command[3]);
336         SetPhase( SCSI_PHASE_STATUS );
337         *transferLength = 0;
338         break;
339
340      default:
341         scsihle_device::ExecCommand( transferLength );
342   }
343}
344
345// scsicd_read_data
346//
347// Read data from the device resulting from the execution of a command
348
349void scsicd_device::ReadData( UINT8 *data, int dataLength )
350{
351   int i;
352   UINT32 last_phys_frame;
353   UINT32 temp;
354   UINT8 tmp_buffer[2048];
355
356   switch ( command[0] )
357   {
358      case 0x03: // REQUEST SENSE
359         logerror("SCSICD: Reading REQUEST SENSE data\n");
360
361         memset( data, 0, dataLength );
362
363         data[0] = 0x71; // deferred error
364
365         if (m_cdda->audio_active())
366         {
367            data[12] = 0x00;
368            data[13] = 0x11;    // AUDIO PLAY OPERATION IN PROGRESS
369         }
370         else if (play_err_flag)
371         {
372            play_err_flag = 0;
373            data[12] = 0x64;    // ILLEGAL MODE FOR THIS TRACK
374            data[13] = 0x00;
375         }
376         // (else 00/00 means no error to report)
377         break;
378
379      case 0x12: // INQUIRY
380         memset( data, 0, dataLength );
381         data[0] = 0x05; // device is present, device is CD/DVD (MMC-3)
382         data[1] = 0x80; // media is removable
383         data[2] = 0x05; // device complies with SPC-3 standard
384         data[3] = 0x02; // response data format = SPC-3 standard
385         // some Konami games freak out if this isn't "Sony", so we'll lie
386         // this is the actual drive on my Nagano '98 board
387         strcpy((char *)&data[8], "Sony");
388         strcpy((char *)&data[16], "CDU-76S");
389         strcpy((char *)&data[32], "1.0");
390         break;
391
392      case 0x25: // READ CAPACITY
393         logerror("SCSICD: READ CAPACITY\n");
394
395         temp = cdrom_get_track_start(cdrom, 0xaa);
396         temp--; // return the last used block on the disc
397
398         data[0] = (temp>>24) & 0xff;
399         data[1] = (temp>>16) & 0xff;
400         data[2] = (temp>>8) & 0xff;
401         data[3] = (temp & 0xff);
402         data[4] = 0;
403         data[5] = 0;
404         data[6] = (bytes_per_sector>>8)&0xff;
405         data[7] = (bytes_per_sector & 0xff);
406         break;
407
408      case 0x28: // READ(10)
409      case 0xa8: // READ(12)
410         logerror("SCSICD: read %x dataLength, \n", dataLength);
411         if ((cdrom) && (blocks))
412         {
413            while (dataLength > 0)
414            {
415               if (!cdrom_read_data(cdrom, lba, tmp_buffer, CD_TRACK_MODE1))
416               {
417                  logerror("SCSICD: CD read error!\n");
418               }
419
420               logerror("True LBA: %d, buffer half: %d\n", lba, cur_subblock * bytes_per_sector);
421
422               memcpy(data, &tmp_buffer[cur_subblock * bytes_per_sector], bytes_per_sector);
423
424               cur_subblock++;
425               if (cur_subblock >= num_subblocks)
426               {
427                  cur_subblock = 0;
428
429                  lba++;
430                  blocks--;
431               }
432
433               last_lba = lba;
434               dataLength -= bytes_per_sector;
435               data += bytes_per_sector;
436            }
437         }
438         break;
439
440      case 0x42: // READ SUB-CHANNEL
441         switch (command[3])
442         {
443            case 1: // return current position
444            {
445               int msf;
446
447               if (!cdrom)
448               {
449                  return;
450               }
451
452               logerror("SCSICD: READ SUB-CHANNEL Time = %x, SUBQ = %x\n", command[1], command[2]);
453
454               msf = command[1] & 0x2;
455
456               int audio_active = m_cdda->audio_active();
457               if (audio_active)
458               {
459                  // if audio is playing, get the latest LBA from the CDROM layer
460                  last_lba = m_cdda->get_audio_lba();
461                  if (m_cdda->audio_paused())
462                  {
463                     data[1] = 0x12;     // audio is paused
464                  }
465                  else
466                  {
467                     data[1] = 0x11;     // audio in progress
468                  }
469               }
470               else
471               {
472                  last_lba = 0;
473                  if (m_cdda->audio_ended())
474                  {
475                     data[1] = 0x13; // ended successfully
476                  }
477                  else
478                  {
479//                          data[1] = 0x14;    // stopped due to error
480                     data[1] = 0x15; // No current audio status to return
481                  }
482               }
483
484               data[2] = 0;
485               data[3] = 12;       // data length
486               data[4] = 0x01; // sub-channel format code
487               data[5] = 0x10 | (audio_active ? 0 : 4);
488               data[6] = cdrom_get_track(cdrom, last_lba) + 1; // track
489               data[7] = 0;    // index
490
491               last_phys_frame = last_lba;
492
493               if (msf)
494               {
495                  int m,s,f;
496                  phys_frame_to_msf(last_phys_frame, &m, &s, &f);
497                  data[8] = 0;
498                  data[9] = m;
499                  data[10] = s;
500                  data[11] = f;
501               }
502               else
503               {
504                  data[8] = last_phys_frame>>24;
505                  data[9] = (last_phys_frame>>16)&0xff;
506                  data[10] = (last_phys_frame>>8)&0xff;
507                  data[11] = last_phys_frame&0xff;
508               }
509
510               last_phys_frame -= cdrom_get_track_start(cdrom, data[6] - 1);
511
512               if (msf)
513               {
514                  int m,s,f;
515                  phys_frame_to_msf(last_phys_frame, &m, &s, &f);
516                  data[12] = 0;
517                  data[13] = m;
518                  data[14] = s;
519                  data[15] = f;
520               }
521               else
522               {
523                  data[12] = last_phys_frame>>24;
524                  data[13] = (last_phys_frame>>16)&0xff;
525                  data[14] = (last_phys_frame>>8)&0xff;
526                  data[15] = last_phys_frame&0xff;
527               }
528               break;
529            }
530            default:
531               logerror("SCSICD: Unknown subchannel type %d requested\n", command[3]);
532         }
533         break;
534
535      case 0x43: // READ TOC
536         /*
537             Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out.
538             That makes sense in terms of how real-world CDs are referred to, but
539             our internal routines for tracks use "0" as track 1.  That probably
540             should be fixed...
541         */
542         logerror("SCSICD: READ TOC, format = %d time=%d\n", command[2]&0xf,(command[1]>>1)&1);
543         switch (command[2] & 0x0f)
544         {
545            case 0:     // normal
546               {
547                  int start_trk;
548                  int end_trk;
549                  int len;
550                  int in_len;
551                  int dptr;
552                  UINT32 tstart;
553
554                  start_trk = command[6];
555                  if( start_trk == 0 )
556                  {
557                     start_trk = 1;
558                  }
559
560                  end_trk = cdrom_get_last_track(cdrom);
561                  len = (end_trk * 8) + 2;
562
563                  // the returned TOC DATA LENGTH must be the full amount,
564                  // regardless of how much we're able to pass back due to in_len
565                  dptr = 0;
566                  data[dptr++] = (len>>8) & 0xff;
567                  data[dptr++] = (len & 0xff);
568                  data[dptr++] = 1;
569                  data[dptr++] = end_trk;
570
571                  if( start_trk == 0xaa )
572                  {
573                     end_trk = 0xaa;
574                  }
575
576                  in_len = command[7]<<8 | command[8];
577
578                  for (i = start_trk; i <= end_trk; i++)
579                  {
580                     int cdrom_track = i;
581                     if( cdrom_track != 0xaa )
582                     {
583                        cdrom_track--;
584                     }
585
586                     if( dptr >= in_len )
587                     {
588                        break;
589                     }
590
591                     data[dptr++] = 0;
592                     data[dptr++] = cdrom_get_adr_control(cdrom, cdrom_track);
593                     data[dptr++] = i;
594                     data[dptr++] = 0;
595
596                     tstart = cdrom_get_track_start(cdrom, cdrom_track);
597                     if ((command[1]&2)>>1)
598                        tstart = lba_to_msf(tstart);
599                     data[dptr++] = (tstart>>24) & 0xff;
600                     data[dptr++] = (tstart>>16) & 0xff;
601                     data[dptr++] = (tstart>>8) & 0xff;
602                     data[dptr++] = (tstart & 0xff);
603                  }
604               }
605               break;
606            default:
607               logerror("SCSICD: Unhandled READ TOC format %d\n", command[2]&0xf);
608               break;
609         }
610         break;
611
612      case 0x1a: // MODE SENSE(6)
613      case 0x5a: // MODE SENSE(10)
614         logerror("SCSICD: MODE SENSE page code = %x, PC = %x\n", command[2] & 0x3f, (command[2]&0xc0)>>6);
615
616         switch (command[2] & 0x3f)
617         {
618            case 0xe:   // CD Audio control page
619               data[0] = 0x8e; // page E, parameter is savable
620               data[1] = 0x0e; // page length
621               data[2] = 0x04; // IMMED = 1, SOTC = 0
622               data[3] = data[4] = data[5] = data[6] = data[7] = 0; // reserved
623
624               // connect each audio channel to 1 output port
625               data[8] = 1;
626               data[10] = 2;
627               data[12] = 4;
628               data[14] = 8;
629
630               // indicate max volume
631               data[9] = data[11] = data[13] = data[15] = 0xff;
632               break;
633            case 0x2a:  // Page capabilities
634               data[0] = 0x2a;
635               data[1] = 0x14; // page length
636               data[2] = 0x00; data[3] = 0x00; // CD-R only
637               data[4] = 0x01; // can play audio
638               data[5] = 0;
639               data[6] = 0;
640               data[7] = 0;
641               data[8] = 0x02; data[9] = 0xc0; // 4x speed
642               data[10] = 0;
643               data[11] = 2; // two volumen levels
644               data[12] = 0x00; data[13] = 0x00; // buffer
645               data[14] = 0x02; data[15] = 0xc0; // 4x read speed
646               data[16] = 0;
647               data[17] = 0;
648               data[18] = 0;
649               data[19] = 0;
650               data[20] = 0;
651               data[21] = 0;
652               break;
653
654            default:
655               logerror("SCSICD: MODE SENSE unknown page %x\n", command[2] & 0x3f);
656               break;
657         }
658         break;
659
660      default:
661         scsihle_device::ReadData( data, dataLength );
662         break;
663   }
664}
665
666// scsicd_write_data
667//
668// Write data to the CD-ROM device as part of the execution of a command
669
670void scsicd_device::WriteData( UINT8 *data, int dataLength )
671{
672   switch (command[ 0 ])
673   {
674      case 0x15: // MODE SELECT(6)
675      case 0x55: // MODE SELECT(10)
676         logerror("SCSICD: MODE SELECT page %x\n", data[0] & 0x3f);
677
678         switch (data[0] & 0x3f)
679         {
680            case 0x0:   // vendor-specific
681               // check for SGI extension to force 512-byte blocks
682               if ((data[3] == 8) && (data[10] == 2))
683               {
684                  logerror("SCSICD: Experimental SGI 512-byte block extension enabled\n");
685
686                  bytes_per_sector = 512;
687                  num_subblocks = 4;
688               }
689               else
690               {
691                  logerror("SCSICD: Unknown vendor-specific page!\n");
692               }
693               break;
694
695            case 0xe:   // audio page
696               logerror("Ch 0 route: %x vol: %x\n", data[8], data[9]);
697               logerror("Ch 1 route: %x vol: %x\n", data[10], data[11]);
698               logerror("Ch 2 route: %x vol: %x\n", data[12], data[13]);
699               logerror("Ch 3 route: %x vol: %x\n", data[14], data[15]);
700               break;
701         }
702         break;
703
704      default:
705         scsihle_device::WriteData( data, dataLength );
706         break;
707   }
708}
709
710void scsicd_device::GetDevice( void **_cdrom )
711{
712   *(cdrom_file **)_cdrom = cdrom;
713}
714
715void scsicd_device::SetDevice( void *_cdrom )
716{
717   cdrom = (cdrom_file *)_cdrom;
718   m_cdda->set_cdrom(cdrom);
719}
720
721int scsicd_device::GetSectorBytes()
722{
723   return bytes_per_sector;
724}
trunk/src/emu/machine/scsicd.h
r25365r25366
88#define _SCSICD_H_
99
1010#include "machine/scsihle.h"
11#include "sound/cdda.h"
12#include "cdrom.h"
11#include "machine/t10mmc.h"
1312
14class scsicd_device : public scsihle_device
13class scsicd_device : public scsihle_device,
14   public t10mmc
1515{
1616public:
1717   // construction/destruction
r25365r25366
1919   scsicd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
2020   virtual machine_config_constructor device_mconfig_additions() const;
2121
22   virtual void SetDevice( void *device );
23   virtual void GetDevice( void **device );
24   virtual void ExecCommand( int *transferLength );
25   virtual void WriteData( UINT8 *data, int dataLength );
26   virtual void ReadData( UINT8 *data, int dataLength );
27   virtual int GetSectorBytes();
28
2922   static struct cdrom_interface cd_intf;
3023
3124protected:
32   // device-level overrides
3325   virtual void device_start();
34   virtual void device_reset();
35
36private:
37   required_device<cdda_device> m_cdda;
38   UINT32 lba;
39   UINT32 blocks;
40   UINT32 last_lba;
41   UINT32 bytes_per_sector;
42   UINT32 num_subblocks;
43   UINT32 cur_subblock;
44   UINT32 play_err_flag;
45   cdrom_file *cdrom;
4626};
4727
4828// device type definition
trunk/src/emu/machine/cr589.c
r25365r25366
11#include "cr589.h"
2#include "scsicd.h"
3#include "machine/cr589.h"
42
5// device type definition
6const device_type SCSI_CR589 = &device_creator<scsi_cr589_device>;
73
8scsi_cr589_device::scsi_cr589_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
9   : scsicd_device(mconfig, SCSI_CR589, "SCSI CR589", tag, owner, clock, "scsi_cr589", __FILE__),
10   device_nvram_interface(mconfig, *this)
11{
12}
13
144static const int identity_offset = 0x3ab;
155static const char download_identity[] = "MATSHITA CD98Q4 DOWNLOADGS0N";
166
17void scsi_cr589_device::device_start()
18{
19   scsicd_device::device_start();
20
21   download = 0;
22
23   save_item(NAME(download));
24   save_item(NAME(buffer));
25   save_item(NAME(bufferOffset));
26}
27
28
29
307//-------------------------------------------------
318//  nvram_default - called to initialize NVRAM to
329//  its default state
3310//-------------------------------------------------
3411
35void scsi_cr589_device::nvram_default()
12void matsushita_cr589_device::nvram_default()
3613{
3714   memset( buffer, 0, sizeof(buffer));
3815   memcpy( &buffer[ identity_offset ], "MATSHITACD-ROM CR-589   GS0N", 28 );
r25365r25366
4522//  .nv file
4623//-------------------------------------------------
4724
48void scsi_cr589_device::nvram_read(emu_file &file)
25void matsushita_cr589_device::nvram_read(emu_file &file)
4926{
5027   file.read(buffer, sizeof(buffer));
5128}
r25365r25366
5734//  .nv file
5835//-------------------------------------------------
5936
60void scsi_cr589_device::nvram_write(emu_file &file)
37void matsushita_cr589_device::nvram_write(emu_file &file)
6138{
6239   file.write(buffer, sizeof(buffer));
6340}
6441
6542
6643
67void scsi_cr589_device::ExecCommand( int *transferLength )
44void matsushita_cr589_device::ExecCommand()
6845{
6946   switch( command[ 0 ] )
7047   {
7148      case 0x3b: // WRITE BUFFER
7249         bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
73         SetPhase( SCSI_PHASE_DATAOUT );
74         *transferLength = ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
50         m_phase = SCSI_PHASE_DATAOUT;
51         m_transfer_length = ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
7552         break;
7653
7754      case 0x3c: // READ BUFFER
7855         bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
79         SetPhase( SCSI_PHASE_DATAIN );
80         *transferLength = ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
56         m_phase = SCSI_PHASE_DATAIN;
57         m_transfer_length = ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
8158         break;
8259
8360      case 0xcc: // FIRMWARE DOWNLOAD ENABLE
84         SetPhase( SCSI_PHASE_DATAOUT );
85         *transferLength = SCSILengthFromUINT16( &command[7] );
61         m_phase = SCSI_PHASE_DATAOUT;
62         m_transfer_length = SCSILengthFromUINT16( &command[7] );
8663         break;
8764
8865      default:
89         scsicd_device::ExecCommand( transferLength );
66         t10mmc::ExecCommand();
9067   }
9168}
9269
93void scsi_cr589_device::ReadData( UINT8 *data, int dataLength )
70void matsushita_cr589_device::ReadData( UINT8 *data, int dataLength )
9471{
9572   switch( command[ 0 ] )
9673   {
9774      case 0x12: // INQUIRY
98         scsicd_device::ReadData( data, dataLength );
75         t10mmc::ReadData( data, dataLength );
9976
10077         if( download )
10178         {
r25365r25366
11390         break;
11491
11592      default:
116         scsicd_device::ReadData( data, dataLength );
93         t10mmc::ReadData( data, dataLength );
11794         break;
11895   }
11996}
12097
121void scsi_cr589_device::WriteData( UINT8 *data, int dataLength )
98void matsushita_cr589_device::WriteData( UINT8 *data, int dataLength )
12299{
123100   switch( command[ 0 ] )
124101   {
r25365r25366
139116         break;
140117
141118      default:
142         scsicd_device::WriteData( data, dataLength );
119         t10mmc::WriteData( data, dataLength );
143120         break;
144121   }
145122}
r25365r25366
147124// device type definition
148125const device_type CR589 = &device_creator<matsushita_cr589_device>;
149126
150matsushita_cr589_device::matsushita_cr589_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
151   : atapi_hle_device(mconfig, CR589, "Matsushita CR589", tag, owner, clock, "cr589", __FILE__)
127matsushita_cr589_device::matsushita_cr589_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
128   atapi_cdrom_device(mconfig, CR589, "Matsushita CR589", tag, owner, clock, "cr589", __FILE__),
129   device_nvram_interface(mconfig, *this)
152130{
153131}
154132
155static MACHINE_CONFIG_FRAGMENT( cr589 )
156   MCFG_DEVICE_ADD("device", SCSI_CR589, 0)
157MACHINE_CONFIG_END
158
159//-------------------------------------------------
160//  machine_config_additions - device-specific
161//  machine configurations
162//-------------------------------------------------
163
164machine_config_constructor matsushita_cr589_device::device_mconfig_additions() const
165{
166   return MACHINE_CONFIG_NAME( cr589 );
167}
168
169133void matsushita_cr589_device::device_start()
170134{
135   save_item(NAME(download));
136   save_item(NAME(buffer));
137   save_item(NAME(bufferOffset));
138
139   atapi_cdrom_device::device_start();
140
141   /// TODO: split identify buffer into another method as device_start() should be called after it's filled in, but the atapi_cdrom_device has it's own.
171142   memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
172143
173144   m_identify_buffer[ 0 ] = 0x8500; // ATAPI device, cmd set 5 compliant, DRQ within 3 ms of PACKET command
r25365r25366
199170   m_identify_buffer[ 46 ] = (' ' << 8) | ' ';
200171
201172   m_identify_buffer[ 49 ] = 0x0400; // IORDY may be disabled
202
203   atapi_hle_device::device_start();
204173}
205174
206void matsushita_cr589_device::perform_diagnostic()
175void matsushita_cr589_device::device_reset()
207176{
208   m_error = IDE_ERROR_DIAGNOSTIC_PASSED;
209}
177   atapi_cdrom_device::device_reset();
210178
211void matsushita_cr589_device::identify_packet_device()
212{
179   download = 0;
180   bufferOffset = 0;
213181}
trunk/src/emu/machine/cr589.h
r25365r25366
1414#ifndef __CR589_H__
1515#define __CR589_H__
1616
17#include "atapihle.h"
18#include "scsicd.h"
17#include "atapicdr.h"
18#include "t10mmc.h"
1919
20class scsi_cr589_device : public scsicd_device,
20class matsushita_cr589_device : public atapi_cdrom_device,
2121   public device_nvram_interface
2222{
2323public:
24   // construction/destruction
25   scsi_cr589_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
24   matsushita_cr589_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
2625
27   virtual void ExecCommand( int *transferLength );
26   virtual void ExecCommand();
2827   virtual void WriteData( UINT8 *data, int dataLength );
2928   virtual void ReadData( UINT8 *data, int dataLength );
3029
3130protected:
3231   // device-level overrides
3332   virtual void device_start();
33   virtual void device_reset();
3434
3535   // device_nvram_interface overrides
3636   virtual void nvram_default();
r25365r25366
4444};
4545
4646// device type definition
47extern const device_type SCSI_CR589;
48
49class matsushita_cr589_device : public atapi_hle_device
50{
51public:
52   matsushita_cr589_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
53
54protected:
55   // device-level overrides
56   virtual machine_config_constructor device_mconfig_additions() const;
57   virtual void device_start();
58
59   virtual void perform_diagnostic();
60   virtual void identify_packet_device();
61};
62
63// device type definition
6447extern const device_type CR589;
6548
6649#endif
trunk/src/emu/machine/t10mmc.c
r0r25366
1#include "t10mmc.h"
2
3static void phys_frame_to_msf(int phys_frame, int *m, int *s, int *f)
4{
5   *m = phys_frame / (60*75);
6   phys_frame -= (*m * 60 * 75);
7   *s = phys_frame / 75;
8   *f = phys_frame % 75;
9}
10
11void t10mmc::t10_start(device_t &device)
12{
13   t10spc::t10_start(device);
14
15   device.save_item(NAME(lba));
16   device.save_item(NAME(blocks));
17   device.save_item(NAME(last_lba));
18   device.save_item(NAME(num_subblocks));
19   device.save_item(NAME(cur_subblock));
20   device.save_item(NAME(play_err_flag));
21}
22
23void t10mmc::t10_reset()
24{
25   t10spc::t10_reset();
26
27   SetDevice( m_image->get_cdrom_file() );
28   if( !cdrom )
29   {
30      logerror( "T10MMC %s: no CD found!\n", m_image->tag() );
31   }
32
33   lba = 0;
34   blocks = 0;
35   last_lba = 0;
36   m_sector_bytes = 2048;
37   num_subblocks = 1;
38   cur_subblock = 0;
39   play_err_flag = 0;
40}
41
42// scsicd_exec_command
43//
44// Execute a SCSI command.
45
46void t10mmc::ExecCommand()
47{
48   int trk;
49
50   switch ( command[0] )
51   {
52      case 0x03: // REQUEST SENSE
53         m_phase = SCSI_PHASE_DATAIN;
54         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
55         break;
56
57      case 0x12: // INQUIRY
58         logerror("T10MMC: REQUEST SENSE\n");
59         m_phase = SCSI_PHASE_DATAIN;
60         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
61         break;
62
63      case 0x15: // MODE SELECT(6)
64         logerror("T10MMC: MODE SELECT(6) length %x control %x\n", command[4], command[5]);
65         m_phase = SCSI_PHASE_DATAOUT;
66         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
67         break;
68
69      case 0x1a: // MODE SENSE(6)
70         m_phase = SCSI_PHASE_DATAIN;
71         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
72         break;
73
74      case 0x1b: // START STOP UNIT
75         m_cdda->stop_audio();
76         m_phase = SCSI_PHASE_STATUS;
77         m_transfer_length = 0;
78         break;
79
80      case 0x1e: // PREVENT ALLOW MEDIUM REMOVAL
81         m_phase = SCSI_PHASE_STATUS;
82         m_transfer_length = 0;
83         break;
84
85      case 0x25: // READ CAPACITY
86         m_phase = SCSI_PHASE_DATAIN;
87         m_transfer_length = 8;
88         break;
89
90      case 0x28: // READ(10)
91
92         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
93         blocks = SCSILengthFromUINT16( &command[7] );
94
95         logerror("T10MMC: READ(10) at LBA %x for %d blocks (%d bytes)\n", lba, blocks, blocks * m_sector_bytes);
96
97         if (num_subblocks > 1)
98         {
99            cur_subblock = lba % num_subblocks;
100            lba /= num_subblocks;
101         }
102         else
103         {
104            cur_subblock = 0;
105         }
106
107         m_cdda->stop_audio();
108
109         m_phase = SCSI_PHASE_DATAIN;
110         m_transfer_length = blocks * m_sector_bytes;
111         break;
112
113      case 0x42: // READ SUB-CHANNEL
114//                      logerror("T10MMC: READ SUB-CHANNEL type %d\n", command[3]);
115         m_phase = SCSI_PHASE_DATAIN;
116         m_transfer_length = SCSILengthFromUINT16( &command[ 7 ] );
117         break;
118
119      case 0x43: // READ TOC
120      {
121         int start_trk = command[6];
122         int end_trk = cdrom_get_last_track(cdrom);
123         int length;
124         int allocation_length = SCSILengthFromUINT16( &command[ 7 ] );
125
126         if( start_trk == 0 )
127         {
128            start_trk = 1;
129         }
130         if( start_trk == 0xaa )
131         {
132            end_trk = start_trk;
133         }
134
135         length = 4 + ( 8 * ( ( end_trk - start_trk ) + 1 ) );
136         if( length > allocation_length )
137         {
138            length = allocation_length;
139         }
140         else if( length < 4 )
141         {
142            length = 4;
143         }
144
145         m_cdda->stop_audio();
146
147         m_phase = SCSI_PHASE_DATAIN;
148         m_transfer_length = length;
149         break;
150      }
151      case 0x45: // PLAY AUDIO(10)
152         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
153         blocks = SCSILengthFromUINT16( &command[7] );
154
155         // special cases: lba of 0 means MSF of 00:02:00
156         if (lba == 0)
157         {
158            lba = 150;
159         }
160         else if (lba == 0xffffffff)
161         {
162            logerror("T10MMC: play audio from current not implemented!\n");
163         }
164
165         logerror("T10MMC: PLAY AUDIO(10) at LBA %x for %x blocks\n", lba, blocks);
166
167         trk = cdrom_get_track(cdrom, lba);
168
169         if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
170         {
171            play_err_flag = 0;
172            m_cdda->start_audio(lba, blocks);
173         }
174         else
175         {
176            logerror("T10MMC: track is NOT audio!\n");
177            play_err_flag = 1;
178         }
179
180         m_phase = SCSI_PHASE_STATUS;
181         m_transfer_length = 0;
182         break;
183
184      case 0x48: // PLAY AUDIO TRACK/INDEX
185         // be careful: tracks here are zero-based, but the SCSI command
186         // uses the real CD track number which is 1-based!
187         lba = cdrom_get_track_start(cdrom, command[4]-1);
188         blocks = cdrom_get_track_start(cdrom, command[7]-1) - lba;
189         if (command[4] > command[7])
190         {
191            blocks = 0;
192         }
193
194         if (command[4] == command[7])
195         {
196            blocks = cdrom_get_track_start(cdrom, command[4]) - lba;
197         }
198
199         if (blocks && cdrom)
200         {
201            m_cdda->start_audio(lba, blocks);
202         }
203
204         logerror("T10MMC: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], blocks);
205         m_phase = SCSI_PHASE_STATUS;
206         m_transfer_length = 0;
207         break;
208
209      case 0x4b: // PAUSE/RESUME
210         if (cdrom)
211         {
212            m_cdda->pause_audio((command[8] & 0x01) ^ 0x01);
213         }
214
215         logerror("T10MMC: PAUSE/RESUME: %s\n", command[8]&1 ? "RESUME" : "PAUSE");
216         m_phase = SCSI_PHASE_STATUS;
217         m_transfer_length = 0;
218         break;
219
220      case 0x4e: // STOP
221         if (cdrom)
222         {
223            m_cdda->stop_audio();
224         }
225
226         logerror("T10MMC: STOP_PLAY_SCAN\n");
227         m_phase = SCSI_PHASE_STATUS;
228         m_transfer_length = 0;
229         break;
230
231      case 0x55: // MODE SELECT(10)
232         logerror("T10MMC: MODE SELECT length %x control %x\n", command[7]<<8 | command[8], command[1]);
233         m_phase = SCSI_PHASE_DATAOUT;
234         m_transfer_length = SCSILengthFromUINT16( &command[ 7 ] );
235         break;
236
237      case 0x5a: // MODE SENSE(10)
238         m_phase = SCSI_PHASE_DATAIN;
239         m_transfer_length = SCSILengthFromUINT16( &command[ 7 ] );
240         break;
241
242      case 0xa5: // PLAY AUDIO(12)
243         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
244         blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
245
246         // special cases: lba of 0 means MSF of 00:02:00
247         if (lba == 0)
248         {
249            lba = 150;
250         }
251         else if (lba == 0xffffffff)
252         {
253            logerror("T10MMC: play audio from current not implemented!\n");
254         }
255
256         logerror("T10MMC: PLAY AUDIO(12) at LBA %x for %x blocks\n", lba, blocks);
257
258         trk = cdrom_get_track(cdrom, lba);
259
260         if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
261         {
262            play_err_flag = 0;
263            m_cdda->start_audio(lba, blocks);
264         }
265         else
266         {
267            logerror("T10MMC: track is NOT audio!\n");
268            play_err_flag = 1;
269         }
270         m_phase = SCSI_PHASE_STATUS;
271         m_transfer_length = 0;
272         break;
273
274      case 0xa8: // READ(12)
275         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
276         blocks = command[7]<<16 | command[8]<<8 | command[9];
277
278         logerror("T10MMC: READ(12) at LBA %x for %x blocks (%x bytes)\n", lba, blocks, blocks * m_sector_bytes);
279
280         if (num_subblocks > 1)
281         {
282            cur_subblock = lba % num_subblocks;
283            lba /= num_subblocks;
284         }
285         else
286         {
287            cur_subblock = 0;
288         }
289
290         m_cdda->stop_audio();
291
292         m_phase = SCSI_PHASE_DATAIN;
293         m_transfer_length = blocks * m_sector_bytes;
294         break;
295
296      case 0xbb: // SET CD SPEED
297         logerror("T10MMC: SET CD SPEED to %d kbytes/sec.\n", command[2]<<8 | command[3]);
298         m_phase = SCSI_PHASE_STATUS;
299         m_transfer_length = 0;
300         break;
301
302      default:
303         t10spc::ExecCommand();
304   }
305}
306
307// scsicd_read_data
308//
309// Read data from the device resulting from the execution of a command
310
311void t10mmc::ReadData( UINT8 *data, int dataLength )
312{
313   int i;
314   UINT32 last_phys_frame;
315   UINT32 temp;
316   UINT8 tmp_buffer[2048];
317
318   switch ( command[0] )
319   {
320      case 0x03: // REQUEST SENSE
321         logerror("T10MMC: Reading REQUEST SENSE data\n");
322
323         memset( data, 0, dataLength );
324
325         data[0] = 0x71; // deferred error
326
327         if (m_cdda->audio_active())
328         {
329            data[12] = 0x00;
330            data[13] = 0x11;    // AUDIO PLAY OPERATION IN PROGRESS
331         }
332         else if (play_err_flag)
333         {
334            play_err_flag = 0;
335            data[12] = 0x64;    // ILLEGAL MODE FOR THIS TRACK
336            data[13] = 0x00;
337         }
338         // (else 00/00 means no error to report)
339         break;
340
341      case 0x12: // INQUIRY
342         memset( data, 0, dataLength );
343         data[0] = 0x05; // device is present, device is CD/DVD (MMC-3)
344         data[1] = 0x80; // media is removable
345         data[2] = 0x05; // device complies with SPC-3 standard
346         data[3] = 0x02; // response data format = SPC-3 standard
347         // some Konami games freak out if this isn't "Sony", so we'll lie
348         // this is the actual drive on my Nagano '98 board
349         strcpy((char *)&data[8], "Sony");
350         strcpy((char *)&data[16], "CDU-76S");
351         strcpy((char *)&data[32], "1.0");
352         break;
353
354      case 0x25: // READ CAPACITY
355         logerror("T10MMC: READ CAPACITY\n");
356
357         temp = cdrom_get_track_start(cdrom, 0xaa);
358         temp--; // return the last used block on the disc
359
360         data[0] = (temp>>24) & 0xff;
361         data[1] = (temp>>16) & 0xff;
362         data[2] = (temp>>8) & 0xff;
363         data[3] = (temp & 0xff);
364         data[4] = 0;
365         data[5] = 0;
366         data[6] = (m_sector_bytes>>8)&0xff;
367         data[7] = (m_sector_bytes & 0xff);
368         break;
369
370      case 0x28: // READ(10)
371      case 0xa8: // READ(12)
372         logerror("T10MMC: read %x dataLength, \n", dataLength);
373         if ((cdrom) && (blocks))
374         {
375            while (dataLength > 0)
376            {
377               if (!cdrom_read_data(cdrom, lba, tmp_buffer, CD_TRACK_MODE1))
378               {
379                  logerror("T10MMC: CD read error!\n");
380               }
381
382               logerror("True LBA: %d, buffer half: %d\n", lba, cur_subblock * m_sector_bytes);
383
384               memcpy(data, &tmp_buffer[cur_subblock * m_sector_bytes], m_sector_bytes);
385
386               cur_subblock++;
387               if (cur_subblock >= num_subblocks)
388               {
389                  cur_subblock = 0;
390
391                  lba++;
392                  blocks--;
393               }
394
395               last_lba = lba;
396               dataLength -= m_sector_bytes;
397               data += m_sector_bytes;
398            }
399         }
400         break;
401
402      case 0x42: // READ SUB-CHANNEL
403         switch (command[3])
404         {
405            case 1: // return current position
406            {
407               int msf;
408
409               if (!cdrom)
410               {
411                  return;
412               }
413
414               logerror("T10MMC: READ SUB-CHANNEL Time = %x, SUBQ = %x\n", command[1], command[2]);
415
416               msf = command[1] & 0x2;
417
418               int audio_active = m_cdda->audio_active();
419               if (audio_active)
420               {
421                  // if audio is playing, get the latest LBA from the CDROM layer
422                  last_lba = m_cdda->get_audio_lba();
423                  if (m_cdda->audio_paused())
424                  {
425                     data[1] = 0x12;     // audio is paused
426                  }
427                  else
428                  {
429                     data[1] = 0x11;     // audio in progress
430                  }
431               }
432               else
433               {
434                  last_lba = 0;
435                  if (m_cdda->audio_ended())
436                  {
437                     data[1] = 0x13; // ended successfully
438                  }
439                  else
440                  {
441//                          data[1] = 0x14;    // stopped due to error
442                     data[1] = 0x15; // No current audio status to return
443                  }
444               }
445
446               data[2] = 0;
447               data[3] = 12;       // data length
448               data[4] = 0x01; // sub-channel format code
449               data[5] = 0x10 | (audio_active ? 0 : 4);
450               data[6] = cdrom_get_track(cdrom, last_lba) + 1; // track
451               data[7] = 0;    // index
452
453               last_phys_frame = last_lba;
454
455               if (msf)
456               {
457                  int m,s,f;
458                  phys_frame_to_msf(last_phys_frame, &m, &s, &f);
459                  data[8] = 0;
460                  data[9] = m;
461                  data[10] = s;
462                  data[11] = f;
463               }
464               else
465               {
466                  data[8] = last_phys_frame>>24;
467                  data[9] = (last_phys_frame>>16)&0xff;
468                  data[10] = (last_phys_frame>>8)&0xff;
469                  data[11] = last_phys_frame&0xff;
470               }
471
472               last_phys_frame -= cdrom_get_track_start(cdrom, data[6] - 1);
473
474               if (msf)
475               {
476                  int m,s,f;
477                  phys_frame_to_msf(last_phys_frame, &m, &s, &f);
478                  data[12] = 0;
479                  data[13] = m;
480                  data[14] = s;
481                  data[15] = f;
482               }
483               else
484               {
485                  data[12] = last_phys_frame>>24;
486                  data[13] = (last_phys_frame>>16)&0xff;
487                  data[14] = (last_phys_frame>>8)&0xff;
488                  data[15] = last_phys_frame&0xff;
489               }
490               break;
491            }
492            default:
493               logerror("T10MMC: Unknown subchannel type %d requested\n", command[3]);
494         }
495         break;
496
497      case 0x43: // READ TOC
498         /*
499             Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out.
500             That makes sense in terms of how real-world CDs are referred to, but
501             our internal routines for tracks use "0" as track 1.  That probably
502             should be fixed...
503         */
504         logerror("T10MMC: READ TOC, format = %d time=%d\n", command[2]&0xf,(command[1]>>1)&1);
505         switch (command[2] & 0x0f)
506         {
507            case 0:     // normal
508               {
509                  int start_trk;
510                  int end_trk;
511                  int len;
512                  int in_len;
513                  int dptr;
514                  UINT32 tstart;
515
516                  start_trk = command[6];
517                  if( start_trk == 0 )
518                  {
519                     start_trk = 1;
520                  }
521
522                  end_trk = cdrom_get_last_track(cdrom);
523                  len = (end_trk * 8) + 2;
524
525                  // the returned TOC DATA LENGTH must be the full amount,
526                  // regardless of how much we're able to pass back due to in_len
527                  dptr = 0;
528                  data[dptr++] = (len>>8) & 0xff;
529                  data[dptr++] = (len & 0xff);
530                  data[dptr++] = 1;
531                  data[dptr++] = end_trk;
532
533                  if( start_trk == 0xaa )
534                  {
535                     end_trk = 0xaa;
536                  }
537
538                  in_len = command[7]<<8 | command[8];
539
540                  for (i = start_trk; i <= end_trk; i++)
541                  {
542                     int cdrom_track = i;
543                     if( cdrom_track != 0xaa )
544                     {
545                        cdrom_track--;
546                     }
547
548                     if( dptr >= in_len )
549                     {
550                        break;
551                     }
552
553                     data[dptr++] = 0;
554                     data[dptr++] = cdrom_get_adr_control(cdrom, cdrom_track);
555                     data[dptr++] = i;
556                     data[dptr++] = 0;
557
558                     tstart = cdrom_get_track_start(cdrom, cdrom_track);
559                     if ((command[1]&2)>>1)
560                        tstart = lba_to_msf(tstart);
561                     data[dptr++] = (tstart>>24) & 0xff;
562                     data[dptr++] = (tstart>>16) & 0xff;
563                     data[dptr++] = (tstart>>8) & 0xff;
564                     data[dptr++] = (tstart & 0xff);
565                  }
566               }
567               break;
568            default:
569               logerror("T10MMC: Unhandled READ TOC format %d\n", command[2]&0xf);
570               break;
571         }
572         break;
573
574      case 0x1a: // MODE SENSE(6)
575      case 0x5a: // MODE SENSE(10)
576         logerror("T10MMC: MODE SENSE page code = %x, PC = %x\n", command[2] & 0x3f, (command[2]&0xc0)>>6);
577
578         memset(data, 0, SCSILengthFromUINT16( &command[ 7 ] ));
579
580         switch (command[2] & 0x3f)
581         {
582            case 0xe:   // CD Audio control page
583               data[0] = 0x8e; // page E, parameter is savable
584               data[1] = 0x0e; // page length
585               data[2] = 0x04; // IMMED = 1, SOTC = 0
586               data[3] = data[4] = data[5] = data[6] = data[7] = 0; // reserved
587
588               // connect each audio channel to 1 output port
589               data[8] = 1;
590               data[10] = 2;
591               data[12] = 4;
592               data[14] = 8;
593
594               // indicate max volume
595               data[9] = data[11] = data[13] = data[15] = 0xff;
596               break;
597            case 0x2a:  // Page capabilities
598               data[0] = 0x2a;
599               data[1] = 0x14; // page length
600               data[2] = 0x00; data[3] = 0x00; // CD-R only
601               data[4] = 0x01; // can play audio
602               data[5] = 0;
603               data[6] = 0;
604               data[7] = 0;
605               data[8] = 0x02; data[9] = 0xc0; // 4x speed
606               data[10] = 0;
607               data[11] = 2; // two volumen levels
608               data[12] = 0x00; data[13] = 0x00; // buffer
609               data[14] = 0x02; data[15] = 0xc0; // 4x read speed
610               data[16] = 0;
611               data[17] = 0;
612               data[18] = 0;
613               data[19] = 0;
614               data[20] = 0;
615               data[21] = 0;
616               break;
617
618            default:
619               logerror("T10MMC: MODE SENSE unknown page %x\n", command[2] & 0x3f);
620               break;
621         }
622         break;
623
624      default:
625         t10spc::ReadData( data, dataLength );
626         break;
627   }
628}
629
630// scsicd_write_data
631//
632// Write data to the CD-ROM device as part of the execution of a command
633
634void t10mmc::WriteData( UINT8 *data, int dataLength )
635{
636   switch (command[ 0 ])
637   {
638      case 0x15: // MODE SELECT(6)
639      case 0x55: // MODE SELECT(10)
640         logerror("T10MMC: MODE SELECT page %x\n", data[0] & 0x3f);
641
642         switch (data[0] & 0x3f)
643         {
644            case 0x0:   // vendor-specific
645               // check for SGI extension to force 512-byte blocks
646               if ((data[3] == 8) && (data[10] == 2))
647               {
648                  logerror("T10MMC: Experimental SGI 512-byte block extension enabled\n");
649
650                  m_sector_bytes = 512;
651                  num_subblocks = 4;
652               }
653               else
654               {
655                  logerror("T10MMC: Unknown vendor-specific page!\n");
656               }
657               break;
658
659            case 0xe:   // audio page
660               logerror("Ch 0 route: %x vol: %x\n", data[8], data[9]);
661               logerror("Ch 1 route: %x vol: %x\n", data[10], data[11]);
662               logerror("Ch 2 route: %x vol: %x\n", data[12], data[13]);
663               logerror("Ch 3 route: %x vol: %x\n", data[14], data[15]);
664               break;
665         }
666         break;
667
668      default:
669         t10spc::WriteData( data, dataLength );
670         break;
671   }
672}
673
674void t10mmc::GetDevice( void **_cdrom )
675{
676   *(cdrom_file **)_cdrom = cdrom;
677}
678
679void t10mmc::SetDevice( void *_cdrom )
680{
681   cdrom = (cdrom_file *)_cdrom;
682   m_cdda->set_cdrom(cdrom);
683}
Property changes on: trunk/src/emu/machine/t10mmc.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/t10mmc.h
r0r25366
1/***************************************************************************
2
3t10mmc.h
4
5***************************************************************************/
6
7#ifndef _T10MMC_H_
8#define _T10MMC_H_
9
10#include "t10spc.h"
11#include "imagedev/chd_cd.h"
12#include "sound/cdda.h"
13
14class t10mmc : public virtual t10spc
15{
16public:
17   virtual void SetDevice( void *device );
18   virtual void GetDevice( void **device );
19   virtual void ExecCommand();
20   virtual void WriteData( UINT8 *data, int dataLength );
21   virtual void ReadData( UINT8 *data, int dataLength );
22
23protected:
24   virtual void t10_start(device_t &device);
25   virtual void t10_reset();
26
27   cdrom_image_device *m_image;
28   cdda_device *m_cdda;
29   cdrom_file *cdrom;
30
31   UINT32 lba;
32   UINT32 blocks;
33   UINT32 last_lba;
34   UINT32 num_subblocks;
35   UINT32 cur_subblock;
36   UINT32 play_err_flag;
37};
38
39#endif
Property changes on: trunk/src/emu/machine/t10mmc.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/scsihle.c
r25365r25366
1616void scsihle_device::device_start()
1717{
1818   scsidev_device::device_start();
19   t10_start(*this);
1920
2021   req_timer = timer_alloc(0);
2122   sel_timer = timer_alloc(1);
2223   dataout_timer = timer_alloc(2);
23
24   save_item( NAME( command ) );
25   save_item( NAME( commandLength ) );
26   save_item( NAME( phase ) );
27
28   // Start with bus free
29   phase = SCSI_PHASE_BUS_FREE;
3024}
3125
32#define SCSI_SENSE_SIZE             4
33
34void scsihle_device::ExecCommand( int *transferLength )
26void scsihle_device::device_reset()
3527{
36   switch( command[ 0 ] )
37   {
38   case SCSI_CMD_TEST_UNIT_READY:
39      SetPhase( SCSI_PHASE_STATUS );
40      *transferLength = 0;
41      break;
42
43   case SCSI_CMD_RECALIBRATE:
44      SetPhase( SCSI_PHASE_STATUS );
45      *transferLength = 0;
46      break;
47
48   case SCSI_CMD_REQUEST_SENSE:
49      SetPhase( SCSI_PHASE_DATAOUT );
50      *transferLength = SCSI_SENSE_SIZE;
51      break;
52
53   case SCSI_CMD_SEND_DIAGNOSTIC:
54      SetPhase( SCSI_PHASE_DATAOUT );
55      *transferLength = ( command[ 3 ] << 8 ) + command[ 4 ];
56      break;
57
58   default:
59      logerror( "%s: SCSIDEV unknown command %02x\n", machine().describe_context(), command[ 0 ] );
60      *transferLength = 0;
61      break;
62   }
28   t10_reset();
6329}
6430
65void scsihle_device::ReadData( UINT8 *data, int dataLength )
66{
67   switch( command[ 0 ] )
68   {
69   case SCSI_CMD_REQUEST_SENSE:
70      data[ 0 ] = SCSI_SENSE_NO_SENSE;
71      data[ 1 ] = 0x00;
72      data[ 2 ] = 0x00;
73      data[ 3 ] = 0x00;
74      break;
75   default:
76      logerror( "%s: SCSIDEV unknown read %02x\n", machine().describe_context(), command[ 0 ] );
77      break;
78   }
79}
80
81void scsihle_device::WriteData( UINT8 *data, int dataLength )
82{
83   switch( command[ 0 ] )
84   {
85   case SCSI_CMD_SEND_DIAGNOSTIC:
86      break;
87
88   default:
89      logerror( "%s: SCSIDEV unknown write %02x\n", machine().describe_context(), command[ 0 ] );
90      break;
91   }
92}
93
94void scsihle_device::SetPhase( int _phase )
95{
96   phase = _phase;
97}
98
99void scsihle_device::GetPhase( int *_phase)
100{
101   *_phase = phase;
102}
103
104void scsihle_device::SetCommand( UINT8 *_command, int _commandLength )
105{
106   if( _commandLength > sizeof( command ) )
107   {
108      /// TODO: output an error.
109      return;
110   }
111
112   memcpy( command, _command, _commandLength );
113   commandLength = _commandLength;
114
115   SetPhase( SCSI_PHASE_COMMAND );
116}
117
11831int scsihle_device::GetDeviceID()
11932{
12033   return scsiID;
r25365r25366
12639   scsidev.scsiID = _scsiID;
12740}
12841
129int SCSILengthFromUINT8( UINT8 *length )
130{
131   if( *length == 0 )
132   {
133      return 256;
134   }
135
136   return *length;
137}
138
139int SCSILengthFromUINT16( UINT8 *length )
140{
141   return ( *(length) << 8 ) | *(length + 1 );
142}
143
14442#define BSY_DELAY_NS    50
14543#define REQ_DELAY_NS    90
14644
r25365r25366
16058
16159
16260#define IS_COMMAND(cmd)             (command[0]==cmd)
163#define IS_READ_COMMAND()           ((command[0]==0x08) || (command[0]==0x28) || (command[0]==0xa8))
164#define IS_WRITE_COMMAND()          ((command[0]==0x0a) || (command[0]==0x2a))
16561
16662#define FORMAT_UNIT_TIMEOUT         5
16763
r25365r25366
231127
232128void scsihle_device::scsibus_read_data()
233129{
234   data_last = (bytes_left >= sectorbytes) ? sectorbytes : bytes_left;
130   data_last = (bytes_left >= m_sector_bytes) ? m_sector_bytes : bytes_left;
235131
236132   LOG(2,"SCSIBUS:scsibus_read_data bytes_left=%04X, data_last=%04X\n",bytes_left,data_last);
237133
r25365r25366
284180void scsihle_device::scsibus_exec_command()
285181{
286182   int command_local = 0;
287   int newphase;
288183
289184   if(LOGLEVEL)
290185      dump_command_bytes();
r25365r25366
300195         LOG(1,"SCSIBUS: format unit command[1]=%02X & 0x10\n",(command[1] & 0x10));
301196         command_local=1;
302197         if((command[1] & 0x10)==0x10)
303            SetPhase(SCSI_PHASE_DATAOUT);
198            m_phase = SCSI_PHASE_DATAOUT;
304199         else
305            SetPhase(SCSI_PHASE_STATUS);
200            m_phase = SCSI_PHASE_STATUS;
306201
307202         bytes_left=4;
308203         dataout_timer->adjust(attotime::from_seconds(FORMAT_UNIT_TIMEOUT));
r25365r25366
312207         LOG(1,"SCSIBUS: Search_data_equaln");
313208         command_local=1;
314209         bytes_left=0;
315         SetPhase(SCSI_PHASE_STATUS);
210         m_phase = SCSI_PHASE_STATUS;
316211         break;
317212
318213      case SCSI_CMD_READ_DEFECT:
r25365r25366
325220         buffer[4] = 0x00; // defect list len lsb
326221
327222         bytes_left=4;
328         SetPhase(SCSI_PHASE_DATAIN);
223         m_phase = SCSI_PHASE_DATAIN;
329224         break;
330225
331226      // write buffer
r25365r25366
333228         LOG(1,"SCSIBUS: write_buffer\n");
334229         command_local=1;
335230         bytes_left=(command[7]<<8)+command[8];
336         SetPhase(SCSI_PHASE_DATAOUT);
231         m_phase = SCSI_PHASE_DATAOUT;
337232         break;
338233
339234      // read buffer
r25365r25366
341236         LOG(1,"SCSIBUS: read_buffer\n");
342237         command_local=1;
343238         bytes_left=(command[7]<<8)+command[8];
344         SetPhase(SCSI_PHASE_DATAIN);
239         m_phase = SCSI_PHASE_DATAIN;
345240         break;
346241   }
347242
r25365r25366
351246   if(!command_local)
352247   {
353248      SetCommand(command, cmd_idx);
354      ExecCommand(&bytes_left);
249      ExecCommand();
250      GetLength(&bytes_left);
355251      data_idx=0;
356252   }
357253
358   GetPhase(&newphase);
254   scsi_change_phase(m_phase);
359255
360   scsi_change_phase(newphase);
361
362256   LOG(1,"SCSIBUS:bytes_left=%02X data_idx=%02X\n",bytes_left,data_idx);
363257
364258   // This is correct as we need to read from disk for commands other than just read data
365   if ((phase == SCSI_PHASE_DATAIN) && (!command_local))
259   if ((m_phase == SCSI_PHASE_DATAIN) && (!command_local))
366260      scsibus_read_data();
367261}
368262
r25365r25366
384278
385279void scsihle_device::scsi_change_phase(UINT8 newphase)
386280{
387   LOG(1,"scsi_change_phase() from=%s, to=%s\n",phasenames[phase],phasenames[newphase]);
281   LOG(1,"scsi_change_phase() from=%s, to=%s\n",phasenames[m_phase],phasenames[newphase]);
388282
389   phase=newphase;
283   m_phase=newphase;
390284   cmd_idx=0;
391285   data_idx=0;
392286
393   switch(phase)
287   switch(m_phase)
394288   {
395289      case SCSI_PHASE_BUS_FREE:
396290         scsi_out( 0, SCSI_MASK_ALL );
r25365r25366
443337      return;
444338   }
445339
446   switch (phase)
340   switch (m_phase)
447341   {
448342      case SCSI_PHASE_BUS_FREE:
449343         // Note this assumes we only have one initiator and therefore
r25365r25366
458352            {
459353               if( ( data & SCSI_MASK_SEL ) == 0 )
460354               {
461                  sectorbytes = GetSectorBytes();
462355                  scsi_change_phase(SCSI_PHASE_COMMAND);
463356               }
464357               else
r25365r25366
500393            {
501394               // check to see if we have reached the end of the block buffer
502395               // and that there is more data to read from the scsi disk
503               if(data_idx==sectorbytes)
396               if(data_idx == m_sector_bytes)
504397               {
505398                  scsibus_read_data();
506399               }
r25365r25366
548441
549442               // If the data buffer is full flush it to the SCSI disk
550443
551               data_last = (bytes_left >= sectorbytes) ? sectorbytes : bytes_left;
444               data_last = (bytes_left >= m_sector_bytes) ? m_sector_bytes : bytes_left;
552445
553446               if(data_idx == data_last)
554447                  scsibus_write_data();
trunk/src/emu/machine/scsihle.h
r25365r25366
1111
1212#include "machine/scsibus.h"
1313#include "machine/scsidev.h"
14#include "machine/t10spc.h"
1415
15class scsihle_device : public scsidev_device
16class scsihle_device : public scsidev_device,
17   public virtual t10spc
1618{
1719public:
1820   // construction/destruction
1921   scsihle_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
2022
21   virtual void SetDevice( void *device ) = 0;
22   virtual void GetDevice( void **device ) = 0;
23   virtual void SetCommand( UINT8 *command, int commandLength );
24   virtual void ExecCommand( int *transferLength );
25   virtual void WriteData( UINT8 *data, int dataLength );
26   virtual void ReadData( UINT8 *data, int dataLength );
27   virtual void SetPhase( int phase );
28   virtual void GetPhase( int *phase );
2923   virtual int GetDeviceID();
30   virtual int GetSectorBytes() = 0;
3124
3225   virtual void scsi_in( UINT32 data, UINT32 mask );
3326
r25365r25366
3730protected:
3831   // device-level overrides
3932   virtual void device_start();
33   virtual void device_reset();
4034   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
4135
42   UINT8 command[ 32 ];
43   int commandLength;
44
4536private:
4637   void scsi_out_req_delay(UINT8 state);
4738   void scsi_change_phase(UINT8 newphase);
r25365r25366
6657   UINT16 data_idx;
6758   int bytes_left;
6859   int data_last;
69   int sectorbytes;
7060
71   int phase;
7261   int scsiID;
7362};
7463
75extern int SCSILengthFromUINT8( UINT8 *length );
76extern int SCSILengthFromUINT16( UINT8 *length );
77
78#define SCSI_PHASE_DATAOUT ( 0 )
79#define SCSI_PHASE_DATAIN ( 1 )
80#define SCSI_PHASE_COMMAND ( 2 )
81#define SCSI_PHASE_STATUS ( 3 )
82#define SCSI_PHASE_MESSAGE_OUT ( 6 )
83#define SCSI_PHASE_MESSAGE_IN ( 7 )
84#define SCSI_PHASE_BUS_FREE ( 8 )
85#define SCSI_PHASE_SELECT ( 9 )
86
87#define SCSI_CMD_TEST_UNIT_READY ( 0x00 )
88#define SCSI_CMD_RECALIBRATE ( 0x01 )
89#define SCSI_CMD_REQUEST_SENSE ( 0x03 )
90#define SCSI_CMD_MODE_SELECT ( 0x15 )
91#define SCSI_CMD_SEND_DIAGNOSTIC ( 0x1d )
92
9364//
9465// Status / Sense data taken from Adaptec ACB40x0 documentation.
9566//
r25365r25366
9970#define SCSI_STATUS_EQUAL           0x04
10071#define SCSI_STATUS_BUSY            0x08
10172
102#define SCSI_SENSE_ADDR_VALID       0x80
103#define SCSI_SENSE_NO_SENSE         0x00
104#define SCSI_SENSE_NO_INDEX         0x01
105#define SCSI_SENSE_SEEK_NOT_COMP    0x02
106#define SCSI_SENSE_WRITE_FAULT      0x03
107#define SCSI_SENSE_DRIVE_NOT_READY  0x04
108#define SCSI_SENSE_NO_TRACK0        0x06
109#define SCSI_SENSE_ID_CRC_ERROR     0x10
110#define SCSI_SENSE_UNCORRECTABLE    0x11
111#define SCSI_SENSE_ADDRESS_NF       0x12
112#define SCSI_SENSE_RECORD_NOT_FOUND 0x14
113#define SCSI_SENSE_SEEK_ERROR       0x15
114#define SCSI_SENSE_DATA_CHECK_RETRY 0x18
115#define SCSI_SENSE_ECC_VERIFY       0x19
116#define SCSI_SENSE_INTERLEAVE_ERROR 0x1A
117#define SCSI_SENSE_UNFORMATTED      0x1C
118#define SCSI_SENSE_ILLEGAL_COMMAND  0x20
119#define SCSI_SENSE_ILLEGAL_ADDRESS  0x21
120#define SCSI_SENSE_VOLUME_OVERFLOW  0x23
121#define SCSI_SENSE_BAD_ARGUMENT     0x24
122#define SCSI_SENSE_INVALID_LUN      0x25
123#define SCSI_SENSE_CART_CHANGED     0x28
124#define SCSI_SENSE_ERROR_OVERFLOW   0x2C
125
12673// SCSI IDs
12774enum
12875{
trunk/src/emu/machine/t10spc.c
r0r25366
1#include "t10spc.h"
2
3#define SCSI_SENSE_SIZE             4
4
5void t10spc::t10_start(device_t &device)
6{
7   device.save_item(NAME(command));
8   device.save_item(NAME(commandLength));
9   device.save_item(NAME(m_phase));
10   device.save_item(NAME(m_transfer_length));
11}
12
13void t10spc::t10_reset()
14{
15   m_phase = SCSI_PHASE_BUS_FREE;
16}
17
18void t10spc::ExecCommand()
19{
20   switch( command[ 0 ] )
21   {
22   case SCSI_CMD_TEST_UNIT_READY:
23      m_phase = SCSI_PHASE_STATUS;
24      m_transfer_length = 0;
25      break;
26
27   case SCSI_CMD_RECALIBRATE:
28      m_phase = SCSI_PHASE_STATUS;
29      m_transfer_length = 0;
30      break;
31
32   case SCSI_CMD_REQUEST_SENSE:
33      m_phase = SCSI_PHASE_DATAOUT;
34      m_transfer_length = SCSI_SENSE_SIZE;
35      break;
36
37   case SCSI_CMD_SEND_DIAGNOSTIC:
38      m_phase = SCSI_PHASE_DATAOUT;
39      m_transfer_length = SCSILengthFromUINT16(&command[3]);
40      break;
41
42   default:
43      logerror( "SCSIDEV unknown command %02x\n", command[ 0 ] );
44      m_transfer_length = 0;
45      break;
46   }
47}
48
49void t10spc::ReadData( UINT8 *data, int dataLength )
50{
51   switch( command[ 0 ] )
52   {
53   case SCSI_CMD_REQUEST_SENSE:
54      data[ 0 ] = SCSI_SENSE_NO_SENSE;
55      data[ 1 ] = 0x00;
56      data[ 2 ] = 0x00;
57      data[ 3 ] = 0x00;
58      break;
59   default:
60      logerror( "SCSIDEV unknown read %02x\n", command[ 0 ] );
61      break;
62   }
63}
64
65void t10spc::WriteData( UINT8 *data, int dataLength )
66{
67   switch( command[ 0 ] )
68   {
69   case SCSI_CMD_SEND_DIAGNOSTIC:
70      break;
71
72   default:
73      logerror( "SCSIDEV unknown write %02x\n", command[ 0 ] );
74      break;
75   }
76}
77
78void t10spc::SetCommand( UINT8 *_command, int _commandLength )
79{
80   if( _commandLength > sizeof( command ) )
81   {
82      /// TODO: output an error.
83      return;
84   }
85
86   memcpy( command, _command, _commandLength );
87   commandLength = _commandLength;
88
89   m_phase = SCSI_PHASE_COMMAND;
90}
Property changes on: trunk/src/emu/machine/t10spc.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/t10spc.h
r0r25366
1/***************************************************************************
2
3t10spc.h
4
5***************************************************************************/
6
7#ifndef _T10SPC_H_
8#define _T10SPC_H_
9
10#include "emu.h"
11
12class t10spc
13{
14public:
15   virtual void SetDevice( void *device ) = 0;
16   virtual void GetDevice( void **device ) = 0;
17
18   virtual void SetCommand( UINT8 *command, int commandLength );
19   virtual void ExecCommand();
20   virtual void WriteData( UINT8 *data, int dataLength );
21   virtual void ReadData( UINT8 *data, int dataLength );
22   void GetLength( int *transferLength ) { *transferLength = m_transfer_length; }
23   virtual void GetPhase( int *phase ) { *phase = m_phase; }
24
25protected:
26   virtual void t10_start(device_t &device);
27   virtual void t10_reset();
28
29   int SCSILengthFromUINT8( UINT8 *length ) { if( *length == 0 ) { return 256; } return *length; }
30   int SCSILengthFromUINT16( UINT8 *length ) { return ( *(length) << 8 ) | *(length + 1 ); }
31
32   UINT8 command[ 32 ];
33   int commandLength;
34   int m_transfer_length;
35   int m_phase;
36   int m_sector_bytes;
37   device_t *m_device;
38};
39
40#define SCSI_PHASE_DATAOUT ( 0 )
41#define SCSI_PHASE_DATAIN ( 1 )
42#define SCSI_PHASE_COMMAND ( 2 )
43#define SCSI_PHASE_STATUS ( 3 )
44#define SCSI_PHASE_MESSAGE_OUT ( 6 )
45#define SCSI_PHASE_MESSAGE_IN ( 7 )
46#define SCSI_PHASE_BUS_FREE ( 8 )
47#define SCSI_PHASE_SELECT ( 9 )
48
49#define SCSI_CMD_TEST_UNIT_READY ( 0x00 )
50#define SCSI_CMD_RECALIBRATE ( 0x01 )
51#define SCSI_CMD_REQUEST_SENSE ( 0x03 )
52#define SCSI_CMD_MODE_SELECT ( 0x15 )
53#define SCSI_CMD_SEND_DIAGNOSTIC ( 0x1d )
54
55#define SCSI_SENSE_ADDR_VALID       0x80
56#define SCSI_SENSE_NO_SENSE         0x00
57#define SCSI_SENSE_NO_INDEX         0x01
58#define SCSI_SENSE_SEEK_NOT_COMP    0x02
59#define SCSI_SENSE_WRITE_FAULT      0x03
60#define SCSI_SENSE_DRIVE_NOT_READY  0x04
61#define SCSI_SENSE_NO_TRACK0        0x06
62#define SCSI_SENSE_ID_CRC_ERROR     0x10
63#define SCSI_SENSE_UNCORRECTABLE    0x11
64#define SCSI_SENSE_ADDRESS_NF       0x12
65#define SCSI_SENSE_RECORD_NOT_FOUND 0x14
66#define SCSI_SENSE_SEEK_ERROR       0x15
67#define SCSI_SENSE_DATA_CHECK_RETRY 0x18
68#define SCSI_SENSE_ECC_VERIFY       0x19
69#define SCSI_SENSE_INTERLEAVE_ERROR 0x1A
70#define SCSI_SENSE_UNFORMATTED      0x1C
71#define SCSI_SENSE_ILLEGAL_COMMAND  0x20
72#define SCSI_SENSE_ILLEGAL_ADDRESS  0x21
73#define SCSI_SENSE_VOLUME_OVERFLOW  0x23
74#define SCSI_SENSE_BAD_ARGUMENT     0x24
75#define SCSI_SENSE_INVALID_LUN      0x25
76#define SCSI_SENSE_CART_CHANGED     0x28
77#define SCSI_SENSE_ERROR_OVERFLOW   0x2C
78
79#endif
Property changes on: trunk/src/emu/machine/t10spc.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/wd33c93.c
r25365r25366
331331
332332         /* do the request */
333333         devices[unit]->SetCommand( &regs[WD_CDB_1], 12 );
334         devices[unit]->ExecCommand( &xfercount );
334         devices[unit]->ExecCommand();
335         devices[unit]->GetLength( &xfercount );
335336         devices[unit]->GetPhase( &phase );
336337
337338         /* set transfer count */
r25365r25366
554555
555556                        /* Execute the command. Depending on the command, we'll move to data in or out */
556557                        devices[unit]->SetCommand( &fifo[0], 12 );
557                        devices[unit]->ExecCommand( &xfercount );
558                        devices[unit]->ExecCommand();
559                        devices[unit]->GetLength( &xfercount );
558560                        devices[unit]->GetPhase( &phase );
559561
560562                        /* reset fifo */
trunk/src/emu/machine/ncr539x.c
r25365r25366
776776   int length, phase;
777777
778778   m_scsi_devices[m_last_id]->SetCommand(&m_fifo[0], 12);
779   m_scsi_devices[m_last_id]->ExecCommand(&length);
779   m_scsi_devices[m_last_id]->ExecCommand();
780   m_scsi_devices[m_last_id]->GetLength(&length);
780781   m_scsi_devices[m_last_id]->GetPhase(&phase);
781782
782783   #if VERBOSE
trunk/src/emu/machine/machine.mak
r25365r25366
562562MACHINEOBJS += $(MACHINEOBJ)/idectrl.o
563563MACHINEOBJS += $(MACHINEOBJ)/idehd.o
564564MACHINEOBJS += $(MACHINEOBJ)/vt83c461.o
565MACHINES += T10
565566endif
566567
567568#-------------------------------------------------
r25365r25366
11931194MACHINEOBJS += $(MACHINEOBJ)/scsidev.o
11941195MACHINEOBJS += $(MACHINEOBJ)/scsihd.o
11951196MACHINEOBJS += $(MACHINEOBJ)/scsihle.o
1197MACHINES += T10
11961198endif
11971199
11981200#-------------------------------------------------
r25365r25366
12511253
12521254#-------------------------------------------------
12531255#
1256#-------------------------------------------------
1257
1258ifneq ($(filter T10,$(MACHINES)),)
1259MACHINEOBJS += $(MACHINEOBJ)/t10mmc.o
1260MACHINEOBJS += $(MACHINEOBJ)/t10sbc.o
1261MACHINEOBJS += $(MACHINEOBJ)/t10spc.o
1262MACHINES += T10
1263endif
1264
1265#-------------------------------------------------
1266#
12541267#@src/emu/machine/tc009xlvc.h,MACHINES += TC0091LVC
12551268#-------------------------------------------------
12561269
trunk/src/emu/machine/atapicdr.c
r25365r25366
11#include "atapicdr.h"
2#include "scsicd.h"
32
43// device type definition
54const device_type ATAPI_CDROM = &device_creator<atapi_cdrom_device>;
65
7atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
8   : atapi_hle_device(mconfig, ATAPI_CDROM, "ATAPI CDROM", tag, owner, clock, "cdrom", __FILE__)
6atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
7   atapi_hle_device(mconfig, ATAPI_CDROM, "ATAPI CDROM", tag, owner, clock, "cdrom", __FILE__)
98{
109}
1110
11atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
12   atapi_hle_device(mconfig, type, name, tag, owner, clock, shortname, source)
13{
14}
15
16cdrom_interface atapi_cdrom_device::cd_intf = { "cdrom", NULL };
17
1218static MACHINE_CONFIG_FRAGMENT( atapicdr )
13   MCFG_DEVICE_ADD("device", SCSICD, 0)
19   MCFG_CDROM_ADD("image", atapi_cdrom_device::cd_intf)
20   MCFG_SOUND_ADD("cdda", CDDA, 0)
1421MACHINE_CONFIG_END
1522
1623//-------------------------------------------------
r25365r25366
2532
2633void atapi_cdrom_device::device_start()
2734{
35   m_image = subdevice<cdrom_image_device>("image");
36   m_cdda = subdevice<cdda_device>("cdda");
37
2838   memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
2939
3040   m_identify_buffer[ 0 ] = 0x8500; // ATAPI device, cmd set 5 compliant, DRQ within 3 ms of PACKET command
trunk/src/emu/machine/atapicdr.h
r25365r25366
1515#define __ATAPICDR_H__
1616
1717#include "atapihle.h"
18#include "t10mmc.h"
1819
19class atapi_cdrom_device : public atapi_hle_device
20class atapi_cdrom_device : public atapi_hle_device,
21   public t10mmc
2022{
2123public:
2224   atapi_cdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
25   atapi_cdrom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,const char *shortname, const char *source);
2326
27   static struct cdrom_interface cd_intf;
28
2429protected:
2530   // device-level overrides
2631   virtual void device_start();
trunk/src/emu/machine/t10sbc.c
r0r25366
1#include "t10sbc.h"
2
3void t10sbc::t10_start(device_t &device)
4{
5   t10spc::t10_start(device);
6
7   device.save_item( NAME( lba ) );
8   device.save_item( NAME( blocks ) );
9}
10
11void t10sbc::t10_reset()
12{
13   t10spc::t10_reset();
14
15   disk = m_image->get_hard_disk_file();
16   if (!disk)
17   {
18      logerror("T10SBC %s: no HD found!\n", m_image->owner()->tag());
19   }
20   else
21   {
22      // get hard disk sector size from CHD metadata
23      const hard_disk_info *hdinfo = hard_disk_get_info(disk);
24      m_sector_bytes = hdinfo->sectorbytes;
25   }
26
27   lba = 0;
28   blocks = 0;
29   m_sector_bytes = 512;
30}
31
32// scsihd_exec_command
33void t10sbc::ExecCommand()
34{
35   switch ( command[0] )
36   {
37      case 0x03: // REQUEST SENSE
38         m_phase = SCSI_PHASE_DATAIN;
39         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
40         break;
41
42      case 0x04: // FORMAT UNIT
43         m_phase = SCSI_PHASE_STATUS;
44         m_transfer_length = 0;
45         break;
46
47      case 0x08: // READ(6)
48         lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
49         blocks = SCSILengthFromUINT8( &command[4] );
50
51         logerror("T10SBC: READ at LBA %x for %x blocks\n", lba, blocks);
52
53         m_phase = SCSI_PHASE_DATAIN;
54         m_transfer_length = blocks * m_sector_bytes;
55         break;
56
57      case 0x0a: // WRITE(6)
58         lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
59         blocks = SCSILengthFromUINT8( &command[4] );
60
61         logerror("T10SBC: WRITE to LBA %x for %x blocks\n", lba, blocks);
62
63         m_phase = SCSI_PHASE_DATAOUT;
64         m_transfer_length = blocks * m_sector_bytes;
65         break;
66
67      case 0x12: // INQUIRY
68         m_phase = SCSI_PHASE_DATAIN;
69         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
70         break;
71
72      case 0x15: // MODE SELECT (used to set CDDA volume)
73         logerror("T10SBC: MODE SELECT length %x control %x\n", command[4], command[5]);
74         m_phase = SCSI_PHASE_DATAOUT;
75         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
76         break;
77
78      case 0x1a: // MODE SENSE(6)
79         m_phase = SCSI_PHASE_DATAIN;
80         m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
81         break;
82
83      case 0x25: // READ CAPACITY
84         m_phase = SCSI_PHASE_DATAIN;
85         m_transfer_length = 8;
86         break;
87
88      case 0x28: // READ(10)
89         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
90         blocks = SCSILengthFromUINT16( &command[7] );
91
92         logerror("T10SBC: READ at LBA %x for %x blocks\n", lba, blocks);
93
94         m_phase = SCSI_PHASE_DATAIN;
95         m_transfer_length = blocks * m_sector_bytes;
96         break;
97
98      case 0x2a: // WRITE (10)
99         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
100         blocks = SCSILengthFromUINT16( &command[7] );
101
102         logerror("T10SBC: WRITE to LBA %x for %x blocks\n", lba, blocks);
103
104         m_phase = SCSI_PHASE_DATAOUT;
105         m_transfer_length = blocks * m_sector_bytes;
106         break;
107
108      case 0xa8: // READ(12)
109         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
110         blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
111
112         logerror("T10SBC: READ at LBA %x for %x blocks\n", lba, blocks);
113
114         m_phase = SCSI_PHASE_DATAIN;
115         m_transfer_length = blocks * m_sector_bytes;
116         break;
117
118      default:
119         t10spc::ExecCommand();
120         break;
121   }
122}
123
124void t10sbc::ReadData( UINT8 *data, int dataLength )
125{
126   int i;
127
128   // if we're a drive without a disk, return all zeroes
129   if (!disk)
130   {
131      memset(data, 0, dataLength);
132      return;
133   }
134
135   switch ( command[0] )
136   {
137      case 0x03:  // REQUEST SENSE
138         data[0] = 0x80; // valid sense
139         for (i = 1; i < 12; i++)
140         {
141            data[i] = 0;
142         }
143         break;
144
145      case 0x12:  // INQUIRY
146         memset( data, 0, dataLength );
147         data[0] = 0x00; // device is direct-access (e.g. hard disk)
148         data[1] = 0x00; // media is not removable
149         data[2] = 0x05; // device complies with SPC-3 standard
150         data[3] = 0x02; // response data format = SPC-3 standard
151         // Apple HD SC setup utility needs to see this
152         strcpy((char *)&data[8], " SEAGATE");
153         strcpy((char *)&data[16], "          ST225N");
154         strcpy((char *)&data[32], "1.0");
155         break;
156
157      case 0x1a:  // MODE SENSE (6 byte)
158         // special Apple ID page.  this is a vendor-specific page,
159         // so unless collisions occur there should be no need
160         // to change it.
161         if ((command[2] & 0x3f) == 0x30)
162         {
163            memset(data, 0, 40);
164            data[0] = 0x14;
165            strcpy((char *)&data[14], "APPLE COMPUTER, INC.");
166         }
167         break;
168
169      case 0x08: // READ(6)
170      case 0x28: // READ(10)
171      case 0xa8: // READ(12)
172         if ((disk) && (blocks))
173         {
174            while (dataLength > 0)
175            {
176               if (!hard_disk_read(disk, lba,  data))
177               {
178                  logerror("T10SBC: HD read error!\n");
179               }
180               lba++;
181               blocks--;
182               dataLength -= m_sector_bytes;
183               data += m_sector_bytes;
184            }
185         }
186         break;
187
188
189      case 0x25: // READ CAPACITY
190         {
191            hard_disk_info *info;
192            UINT32 temp;
193
194            info = hard_disk_get_info(disk);
195
196            logerror("T10SBC: READ CAPACITY\n");
197
198            // get # of sectors
199            temp = info->cylinders * info->heads * info->sectors;
200            temp--;
201
202            data[0] = (temp>>24) & 0xff;
203            data[1] = (temp>>16) & 0xff;
204            data[2] = (temp>>8) & 0xff;
205            data[3] = (temp & 0xff);
206            data[4] = (info->sectorbytes>>24)&0xff;
207            data[5] = (info->sectorbytes>>16)&0xff;
208            data[6] = (info->sectorbytes>>8)&0xff;
209            data[7] = (info->sectorbytes & 0xff);
210         }
211         break;
212
213      default:
214         t10spc::ReadData( data, dataLength );
215         break;
216   }
217}
218
219void t10sbc::WriteData( UINT8 *data, int dataLength )
220{
221   if (!disk)
222   {
223      return;
224   }
225
226   switch ( command[0] )
227   {
228      case 0x0a: // WRITE(6)
229      case 0x2a: // WRITE(10)
230         if ((disk) && (blocks))
231         {
232            while (dataLength > 0)
233            {
234               if (!hard_disk_write(disk, lba, data))
235               {
236                  logerror("T10SBC: HD write error!\n");
237               }
238               lba++;
239               blocks--;
240               dataLength -= m_sector_bytes;
241               data += m_sector_bytes;
242            }
243         }
244         break;
245
246      default:
247         t10spc::WriteData( data, dataLength );
248         break;
249   }
250}
251
252void t10sbc::GetDevice( void **_disk )
253{
254   *(hard_disk_file **)_disk = disk;
255}
256
257void t10sbc::SetDevice( void *_disk )
258{
259   disk = (hard_disk_file *)_disk;
260}
Property changes on: trunk/src/emu/machine/t10sbc.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/machine/t10sbc.h
r0r25366
1/***************************************************************************
2
3t10sbc.h
4
5***************************************************************************/
6
7#ifndef _T10SBC_H_
8#define _T10SBC_H_
9
10#include "t10spc.h"
11#include "imagedev/harddriv.h"
12
13class t10sbc : public virtual t10spc
14{
15public:
16   virtual void SetDevice( void *device );
17   virtual void GetDevice( void **device );
18   virtual void ExecCommand();
19   virtual void WriteData( UINT8 *data, int dataLength );
20   virtual void ReadData( UINT8 *data, int dataLength );
21
22protected:
23   virtual void t10_start(device_t &device);
24   virtual void t10_reset();
25
26   harddisk_image_device *m_image;
27
28private:
29   UINT32 lba;
30   UINT32 blocks;
31
32   hard_disk_file *disk;
33};
34
35#endif
Property changes on: trunk/src/emu/machine/t10sbc.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
trunk/src/emu/machine/atapihle.c
r25365r25366
33atapi_hle_device::atapi_hle_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,const char *shortname, const char *source)
44   : ata_hle_device(mconfig, type, name, tag, owner, clock, shortname, source),
55   m_packet(0),
6   m_data_size(0),
7   m_scsidev_device(*this, "device")
6   m_data_size(0)
87{
98}
109
10void atapi_hle_device::device_start()
11{
12   t10_start(*this);
13   ata_hle_device::device_start();
14}
15
16void atapi_hle_device::device_reset()
17{
18   t10_reset();
19   ata_hle_device::device_reset();
20}
21
1122void atapi_hle_device::process_buffer()
1223{
1324   if (m_packet)
1425   {
15      int phase;
16
1726      //printf( "atapi command %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
1827      //    m_buffer[0],m_buffer[1],m_buffer[2],m_buffer[3],
1928      //    m_buffer[4],m_buffer[5],m_buffer[6],m_buffer[7],
r25365r25366
2130
2231      m_error = 0; // HACK: This might not be the right place, but firebeat needs this cleared at some point
2332
24      m_scsidev_device->SetCommand( m_buffer, m_buffer_size );
25      m_scsidev_device->ExecCommand( &m_data_size );
26      m_scsidev_device->GetPhase( &phase );
33      SetCommand(m_buffer, m_buffer_size);
34      ExecCommand();
35      GetLength(&m_data_size);
2736
2837      m_buffer_size = (m_cylinder_high << 8) | m_cylinder_low;
2938      if (m_buffer_size == 0xffff)
r25365r25366
3948         printf( "ATAPI_FEATURES_FLAG_OVL not supported\n" );
4049      }
4150
42      switch (phase)
51      switch (m_phase)
4352      {
4453      case SCSI_PHASE_DATAOUT:
4554         wait_buffer();
r25365r25366
6574      switch (m_command)
6675      {
6776      case IDE_COMMAND_PACKET:
68         m_scsidev_device->WriteData( m_buffer, m_buffer_size );
77         WriteData( m_buffer, m_buffer_size );
6978         m_data_size -= m_buffer_size;
7079
7180         wait_buffer();
r25365r25366
93102
94103      if (m_buffer_size > 0)
95104      {
96         m_scsidev_device->ReadData( m_buffer, m_buffer_size );
105         ReadData( m_buffer, m_buffer_size );
97106         m_data_size -= m_buffer_size;
98107
99108         m_status |= IDE_STATUS_DRQ;
trunk/src/emu/machine/atapihle.h
r25365r25366
1717#include "atahle.h"
1818#include "scsihle.h"
1919
20class atapi_hle_device : public ata_hle_device
20class atapi_hle_device : public ata_hle_device,
21   public virtual t10spc
2122{
2223public:
2324   atapi_hle_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,const char *shortname, const char *source);
r25365r25366
5051   };
5152
5253protected:
54   virtual void device_start();
55   virtual void device_reset();
56
5357   virtual int sector_length() { return ATAPI_BUFFER_LENGTH; }
5458   virtual void process_buffer();
5559   virtual void fill_buffer();
r25365r25366
6872
6973   int m_packet;
7074   int m_data_size;
71   required_device<scsihle_device> m_scsidev_device;
7275
7376   static const int ATAPI_BUFFER_LENGTH = 0xf800;
7477};
trunk/src/emu/machine/am53cf96.c
r25365r25366
127127               int length;
128128
129129               devices[last_id]->SetCommand( &fifo[1], 12 );
130               devices[last_id]->ExecCommand( &length );
130               devices[last_id]->ExecCommand();
131               devices[last_id]->GetLength(&length);
131132            }
132133            else
133134            {
trunk/src/emu/machine/scsihd.c
r25365r25366
44
55***************************************************************************/
66
7#include "emu.h"
8#include "machine/scsihle.h"
9#include "harddisk.h"
10#include "imagedev/harddriv.h"
117#include "scsihd.h"
128
139// device type definition
r25365r25366
2521
2622void scsihd_device::device_start()
2723{
28   scsihle_device::device_start();
24   m_image = subdevice<harddisk_image_device>("image");
2925
30   save_item( NAME( lba ) );
31   save_item( NAME( blocks ) );
26   scsihle_device::device_start();
3227}
3328
34void scsihd_device::device_reset()
35{
36   scsihle_device::device_reset();
37
38   lba = 0;
39   blocks = 0;
40   sectorbytes = 512;
41
42   disk = subdevice<harddisk_image_device>("image")->get_hard_disk_file();
43   if (!disk)
44   {
45      logerror("%s SCSIHD: no HD found!\n", tag());
46   }
47   else
48   {
49      // get hard disk sector size from CHD metadata
50      const hard_disk_info *hdinfo = hard_disk_get_info(disk);
51      sectorbytes = hdinfo->sectorbytes;
52   }
53}
54
5529harddisk_interface scsihd_device::hd_intf = { NULL, NULL, "scsi_hdd", NULL };
5630
5731static MACHINE_CONFIG_FRAGMENT(scsi_harddisk)
r25365r25366
6236{
6337   return MACHINE_CONFIG_NAME(scsi_harddisk);
6438}
65
66// scsihd_exec_command
67void scsihd_device::ExecCommand( int *transferLength )
68{
69   switch ( command[0] )
70   {
71      case 0x03: // REQUEST SENSE
72         SetPhase( SCSI_PHASE_DATAIN );
73         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
74         break;
75
76      case 0x04: // FORMAT UNIT
77         SetPhase( SCSI_PHASE_STATUS );
78         *transferLength = 0;
79         break;
80
81      case 0x08: // READ(6)
82         lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
83         blocks = SCSILengthFromUINT8( &command[4] );
84
85         logerror("SCSIHD: READ at LBA %x for %x blocks\n", lba, blocks);
86
87         SetPhase( SCSI_PHASE_DATAIN );
88         *transferLength = blocks * sectorbytes;
89         break;
90
91      case 0x0a: // WRITE(6)
92         lba = (command[1]&0x1f)<<16 | command[2]<<8 | command[3];
93         blocks = SCSILengthFromUINT8( &command[4] );
94
95         logerror("SCSIHD: WRITE to LBA %x for %x blocks\n", lba, blocks);
96
97         SetPhase( SCSI_PHASE_DATAOUT );
98         *transferLength = blocks * sectorbytes;
99         break;
100
101      case 0x12: // INQUIRY
102         SetPhase( SCSI_PHASE_DATAIN );
103         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
104         break;
105
106      case 0x15: // MODE SELECT (used to set CDDA volume)
107         logerror("SCSIHD: MODE SELECT length %x control %x\n", command[4], command[5]);
108         SetPhase( SCSI_PHASE_DATAOUT );
109         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
110         break;
111
112      case 0x1a: // MODE SENSE(6)
113         SetPhase( SCSI_PHASE_DATAIN );
114         *transferLength = SCSILengthFromUINT8( &command[ 4 ] );
115         break;
116
117      case 0x25: // READ CAPACITY
118         SetPhase( SCSI_PHASE_DATAIN );
119         *transferLength = 8;
120         break;
121
122      case 0x28: // READ(10)
123         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
124         blocks = SCSILengthFromUINT16( &command[7] );
125
126         logerror("SCSIHD: READ at LBA %x for %x blocks\n", lba, blocks);
127
128         SetPhase( SCSI_PHASE_DATAIN );
129         *transferLength = blocks * sectorbytes;
130         break;
131
132      case 0x2a: // WRITE (10)
133         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
134         blocks = SCSILengthFromUINT16( &command[7] );
135
136         logerror("SCSIHD: WRITE to LBA %x for %x blocks\n", lba, blocks);
137
138         SetPhase( SCSI_PHASE_DATAOUT );
139
140         *transferLength = blocks * sectorbytes;
141         break;
142
143      case 0xa8: // READ(12)
144         lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
145         blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
146
147         logerror("SCSIHD: READ at LBA %x for %x blocks\n", lba, blocks);
148
149         SetPhase( SCSI_PHASE_DATAIN );
150         *transferLength = blocks * sectorbytes;
151         break;
152
153      default:
154         scsihle_device::ExecCommand( transferLength );
155         break;
156   }
157}
158
159void scsihd_device::ReadData( UINT8 *data, int dataLength )
160{
161   int i;
162
163   // if we're a drive without a disk, return all zeroes
164   if (!disk)
165   {
166      memset(data, 0, dataLength);
167      return;
168   }
169
170   switch ( command[0] )
171   {
172      case 0x03:  // REQUEST SENSE
173         data[0] = 0x80; // valid sense
174         for (i = 1; i < 12; i++)
175         {
176            data[i] = 0;
177         }
178         break;
179
180      case 0x12:  // INQUIRY
181         memset( data, 0, dataLength );
182         data[0] = 0x00; // device is direct-access (e.g. hard disk)
183         data[1] = 0x00; // media is not removable
184         data[2] = 0x05; // device complies with SPC-3 standard
185         data[3] = 0x02; // response data format = SPC-3 standard
186         // Apple HD SC setup utility needs to see this
187         strcpy((char *)&data[8], " SEAGATE");
188         strcpy((char *)&data[16], "          ST225N");
189         strcpy((char *)&data[32], "1.0");
190         break;
191
192      case 0x1a:  // MODE SENSE (6 byte)
193         // special Apple ID page.  this is a vendor-specific page,
194         // so unless collisions occur there should be no need
195         // to change it.
196         if ((command[2] & 0x3f) == 0x30)
197         {
198            memset(data, 0, 40);
199            data[0] = 0x14;
200            strcpy((char *)&data[14], "APPLE COMPUTER, INC.");
201         }
202         break;
203
204      case 0x08: // READ(6)
205      case 0x28: // READ(10)
206      case 0xa8: // READ(12)
207         if ((disk) && (blocks))
208         {
209            while (dataLength > 0)
210            {
211               if (!hard_disk_read(disk, lba,  data))
212               {
213                  logerror("SCSIHD: HD read error!\n");
214               }
215               lba++;
216               blocks--;
217               dataLength -= sectorbytes;
218               data += sectorbytes;
219            }
220         }
221         break;
222
223
224      case 0x25: // READ CAPACITY
225         {
226            hard_disk_info *info;
227            UINT32 temp;
228
229            info = hard_disk_get_info(disk);
230
231            logerror("SCSIHD: READ CAPACITY\n");
232
233            // get # of sectors
234            temp = info->cylinders * info->heads * info->sectors;
235            temp--;
236
237            data[0] = (temp>>24) & 0xff;
238            data[1] = (temp>>16) & 0xff;
239            data[2] = (temp>>8) & 0xff;
240            data[3] = (temp & 0xff);
241            data[4] = (info->sectorbytes>>24)&0xff;
242            data[5] = (info->sectorbytes>>16)&0xff;
243            data[6] = (info->sectorbytes>>8)&0xff;
244            data[7] = (info->sectorbytes & 0xff);
245         }
246         break;
247
248      default:
249         scsihle_device::ReadData( data, dataLength );
250         break;
251   }
252}
253
254void scsihd_device::WriteData( UINT8 *data, int dataLength )
255{
256   if (!disk)
257   {
258      return;
259   }
260
261   switch ( command[0] )
262   {
263      case 0x0a: // WRITE(6)
264      case 0x2a: // WRITE(10)
265         if ((disk) && (blocks))
266         {
267            while (dataLength > 0)
268            {
269               if (!hard_disk_write(disk, lba, data))
270               {
271                  logerror("SCSIHD: HD write error!\n");
272               }
273               lba++;
274               blocks--;
275               dataLength -= sectorbytes;
276               data += sectorbytes;
277            }
278         }
279         break;
280
281      default:
282         scsihle_device::WriteData( data, dataLength );
283         break;
284   }
285}
286
287
288void scsihd_device::GetDevice( void **_disk )
289{
290   *(hard_disk_file **)_disk = disk;
291}
292
293void scsihd_device::SetDevice( void *_disk )
294{
295   disk = (hard_disk_file *)_disk;
296}
297
298int scsihd_device::GetSectorBytes()
299{
300   return sectorbytes;
301}
trunk/src/emu/machine/scsihd.h
r25365r25366
88#define _SCSIHD_H_
99
1010#include "machine/scsihle.h"
11#include "harddisk.h"
11#include "machine/t10sbc.h"
1212
13class scsihd_device : public scsihle_device
13class scsihd_device : public scsihle_device,
14   public t10sbc
1415{
1516public:
1617   // construction/destruction
r25365r25366
1819   scsihd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
1920   virtual machine_config_constructor device_mconfig_additions() const;
2021
21   virtual void SetDevice( void *device );
22   virtual void GetDevice( void **device );
23   virtual void ExecCommand( int *transferLength );
24   virtual void WriteData( UINT8 *data, int dataLength );
25   virtual void ReadData( UINT8 *data, int dataLength );
26   virtual int GetSectorBytes();
27
2822   static struct harddisk_interface hd_intf;
2923
3024protected:
31   // device-level overrides
3225   virtual void device_start();
33   virtual void device_reset();
34
35private:
36   UINT32 lba;
37   UINT32 blocks;
38   int sectorbytes;
39   hard_disk_file *disk;
4026};
4127
4228// device type definition
trunk/src/mess/drivers/dccons.c
r25365r25366
609609SLOT_INTERFACE_END
610610
611611static MACHINE_CONFIG_FRAGMENT( gdrom_config )
612   MCFG_DEVICE_MODIFY("device:cdda")
613   MCFG_SOUND_ROUTE(0, "^^^^^lspeaker", 1.0)
614   MCFG_SOUND_ROUTE(1, "^^^^^rspeaker", 1.0)
612   MCFG_DEVICE_MODIFY("cdda")
613   MCFG_SOUND_ROUTE(0, "^^^^lspeaker", 1.0)
614   MCFG_SOUND_ROUTE(1, "^^^^rspeaker", 1.0)
615615MACHINE_CONFIG_END
616616
617617static MACHINE_CONFIG_START( dc, dc_cons_state )
trunk/src/mess/machine/d9060hd.c
r25365r25366
1717#define D9060HD_CMD_PHYSICAL_DEVICE_ID ( 0xc0 )
1818#define D9060HD_CMD_DRIVE_DIAGS ( 0xe3 )
1919
20void d9060hd_device::ExecCommand( int *transferLength )
20void d9060hd_device::ExecCommand()
2121{
2222   switch( command[ 0 ] )
2323   {
2424   case D9060HD_CMD_PHYSICAL_DEVICE_ID:
2525   case D9060HD_CMD_DRIVE_DIAGS:
26      SetPhase(SCSI_PHASE_STATUS);
27      *transferLength = 0;
26      m_phase = SCSI_PHASE_STATUS;
27      m_transfer_length = 0;
2828      break;
2929
3030   default:
31      scsihd_device::ExecCommand( transferLength );
31      scsihd_device::ExecCommand();
3232      break;
3333   }
3434}
trunk/src/mess/machine/d9060hd.h
r25365r25366
1111   // construction/destruction
1212   d9060hd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
1313
14   virtual void ExecCommand( int *transferLength );
14   virtual void ExecCommand();
1515};
1616
1717// device type definition
trunk/src/mess/machine/fm_scsi.c
r25365r25366
220220      {
221221         // command complete
222222         m_SCSIdevices[m_target]->SetCommand(m_command,m_command_index);
223         m_SCSIdevices[m_target]->ExecCommand(&m_result_length);
223         m_SCSIdevices[m_target]->ExecCommand();
224         m_SCSIdevices[m_target]->GetLength(&m_result_length);
224225         m_SCSIdevices[m_target]->GetPhase(&phase);
225226         if(m_command[0] == 1)  // rezero unit command - not implemented in SCSI code
226227            m_phase_timer->adjust(attotime::from_usec(800),SCSI_PHASE_STATUS);
trunk/src/mess/machine/sa1403d.c
r25365r25366
126126{
127127}
128128
129void sa1403d_device::ExecCommand( int *transferLength )
129void sa1403d_device::ExecCommand()
130130{
131131   switch( command[ 0 ] )
132132   {
133133   default:
134      scsihd_device::ExecCommand( transferLength );
134      scsihd_device::ExecCommand();
135135      break;
136136   }
137137}
trunk/src/mess/machine/sa1403d.h
r25365r25366
2727   virtual machine_config_constructor device_mconfig_additions() const;
2828   virtual ioport_constructor device_input_ports() const;
2929
30   virtual void ExecCommand( int *transferLength );
30   virtual void ExecCommand();
3131   virtual void WriteData( UINT8 *data, int dataLength );
3232};
3333
trunk/src/mess/machine/ncr5380.c
r25365r25366
337337                     logerror("NCR5380: Command (to ID %d): %x %x %x %x %x %x %x %x %x %x (PC %x)\n", m_last_id, m_5380_Command[0], m_5380_Command[1], m_5380_Command[2], m_5380_Command[3], m_5380_Command[4], m_5380_Command[5], m_5380_Command[6], m_5380_Command[7], m_5380_Command[8], m_5380_Command[9], machine().firstcpu->pc());
338338
339339                  m_scsi_devices[m_last_id]->SetCommand(&m_5380_Command[0], 16);
340                  m_scsi_devices[m_last_id]->ExecCommand(&m_d_limit);
340                  m_scsi_devices[m_last_id]->ExecCommand();
341                  m_scsi_devices[m_last_id]->GetLength(&m_d_limit);
341342
342343                  if (VERBOSE)
343344                     logerror("NCR5380: Command returned %d bytes\n",  m_d_limit);
trunk/src/mess/machine/s1410.c
r25365r25366
209209#define TRANSFERLENGTH_FORMAT_ALT_TRACK ( 0x03 )
210210#define TRANSFERLENGTH_SECTOR_BUFFER ( 0x0200 )
211211
212void s1410_device::ExecCommand( int *transferLength )
212void s1410_device::ExecCommand()
213213{
214214   switch( command[ 0 ] )
215215   {
216216   case S1410_CMD_INIT_DRIVE_PARAMS:
217      SetPhase(SCSI_PHASE_DATAOUT);
218      *transferLength = TRANSFERLENGTH_INIT_DRIVE_PARAMS;
217      m_phase = SCSI_PHASE_DATAOUT;
218      m_transfer_length = TRANSFERLENGTH_INIT_DRIVE_PARAMS;
219219      break;
220220
221221   case S1410_CMD_FORMAT_ALT_TRACK:
222      SetPhase(SCSI_PHASE_DATAOUT);
223      *transferLength = TRANSFERLENGTH_FORMAT_ALT_TRACK;
222      m_phase = SCSI_PHASE_DATAOUT;
223      m_transfer_length = TRANSFERLENGTH_FORMAT_ALT_TRACK;
224224      break;
225225
226226   case S1410_CMD_WRITE_SEC_BUFFER:
227      SetPhase(SCSI_PHASE_DATAOUT);
228      *transferLength = TRANSFERLENGTH_SECTOR_BUFFER;
227      m_phase = SCSI_PHASE_DATAOUT;
228      m_transfer_length = TRANSFERLENGTH_SECTOR_BUFFER;
229229      break;
230230
231231   case S1410_CMD_READ_SEC_BUFFER:
232      SetPhase(SCSI_PHASE_DATAIN);
233      *transferLength = TRANSFERLENGTH_SECTOR_BUFFER;
232      m_phase = SCSI_PHASE_DATAIN;
233      m_transfer_length = TRANSFERLENGTH_SECTOR_BUFFER;
234234      break;
235235
236236   case S1410_CMD_CHECK_TRACK_FORMAT:
237237   case S1410_CMD_RAM_DIAGS:
238238   case S1410_CMD_DRIVE_DIAGS:
239239   case S1410_CMD_CONTROLER_DIAGS:
240      SetPhase(SCSI_PHASE_STATUS);
241      *transferLength = 0;
240      m_phase = SCSI_PHASE_STATUS;
241      m_transfer_length = 0;
242242      break;
243243
244244   default:
245      scsihd_device::ExecCommand( transferLength );
245      scsihd_device::ExecCommand();
246246      break;
247247   }
248248}
r25365r25366
254254   case S1410_CMD_INIT_DRIVE_PARAMS:
255255      {
256256         int sectorsPerTrack = 0;
257         int bytesPerSector = GetSectorBytes();
258257
259         switch( bytesPerSector )
258         switch( m_sector_bytes )
260259         {
261260         case 256:
262261            sectorsPerTrack = 32;
r25365r25366
269268
270269         UINT16 tracks = ((data[0]<<8)+data[1]);
271270         UINT8 heads = data[2];
272         UINT32 capacity = tracks * heads * sectorsPerTrack * bytesPerSector;
271         UINT32 capacity = tracks * heads * sectorsPerTrack * m_sector_bytes;
273272
274273         logerror("S1410_CMD_INIT_DRIVE_PARAMS Tracks=%d, Heads=%d, Capacity=%d\n",tracks,heads,capacity);
275274      }
trunk/src/mess/machine/s1410.h
r25365r25366
2525   virtual const rom_entry *device_rom_region() const;
2626   virtual machine_config_constructor device_mconfig_additions() const;
2727
28   virtual void ExecCommand( int *transferLength );
28   virtual void ExecCommand();
2929   virtual void WriteData( UINT8 *data, int dataLength );
3030};
3131
trunk/src/mess/machine/mb89352.c
r25365r25366
518518               int phase;
519519               // execute SCSI command
520520               m_SCSIdevices[m_target]->SetCommand(m_command,m_command_index);
521               m_SCSIdevices[m_target]->ExecCommand(&m_result_length);
521               m_SCSIdevices[m_target]->ExecCommand();
522               m_SCSIdevices[m_target]->GetLength(&m_result_length);
522523               m_SCSIdevices[m_target]->GetPhase(&phase);
523524               if(m_command[0] == 1) // Rezero Unit - not implemented in SCSI code
524525                  set_phase(SCSI_PHASE_STATUS);
r25365r25366
583584            int phase;
584585            // execute SCSI command
585586            m_SCSIdevices[m_target]->SetCommand(m_command,m_command_index);
586            m_SCSIdevices[m_target]->ExecCommand(&m_result_length);
587            m_SCSIdevices[m_target]->ExecCommand();
588            m_SCSIdevices[m_target]->GetLength(&m_result_length);
587589            m_SCSIdevices[m_target]->GetPhase(&phase);
588590            if(m_command[0] == 1) // Rezero Unit - not implemented in SCSI code
589591               set_phase(SCSI_PHASE_STATUS);
trunk/src/mess/machine/acb4070.c
r25365r25366
1919
2020#define TRANSFERLENGTH_DATA_BUFFER  0x0400
2121
22void acb4070_device::ExecCommand( int *transferLength )
22void acb4070_device::ExecCommand()
2323{
2424   switch( command[ 0 ] )
2525   {
2626   case ACB4070_CMD_WRITE_DATA_BUFFER:
27      SetPhase( SCSI_PHASE_DATAOUT );
28      *transferLength = TRANSFERLENGTH_DATA_BUFFER;
27      m_phase = SCSI_PHASE_DATAOUT;
28      m_transfer_length = TRANSFERLENGTH_DATA_BUFFER;
2929      break;
3030
3131   case ACB4070_CMD_READ_DATA_BUFFER:
32      SetPhase( SCSI_PHASE_DATAIN );
33      *transferLength = TRANSFERLENGTH_DATA_BUFFER;
32      m_phase = SCSI_PHASE_DATAIN;
33      m_transfer_length = TRANSFERLENGTH_DATA_BUFFER;
3434      break;
3535
3636   default:
37      scsihd_device::ExecCommand( transferLength );
37      scsihd_device::ExecCommand();
3838      break;
3939   }
4040}
trunk/src/mess/machine/acb4070.h
r25365r25366
1111   // construction/destruction
1212   acb4070_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
1313
14   virtual void ExecCommand( int *transferLength );
14   virtual void ExecCommand();
1515};
1616
1717// device type definition

Previous 199869 Revisions Next


© 1997-2024 The MAME Team