12#include "accdvd_internal.h"
33 tmout_v2 =
acd->c_tmout;
39 done(
acd,
acd->c_arg, ret);
44static void acd_atapi_done(
acAtapiT atapi,
void *arg,
int ret)
49 acd_done((
struct acd *)atapi, argt, ret);
53acd_request_in(
struct acd *
acd,
int flag,
acAtapiPacketT packet,
void *buffer,
int size, acAtapiDone done,
char *name)
66 if ( (Acdc.status & 1) == 0 )
76 acd->c_thid = GetThreadId();
78 acAtapiSetup(&
acd->c_atapi, done ? done : acd_atapi_done, &Acdc, ret);
92 status = acAtapiRequest(&
acd->c_atapi, v16, packet, buffer, size);
98 if ( Acdc.active < 0 )
111 status_v14 = SleepThread();
112 if ( status_v14 == -418 )
124 ret_v15 =
acd->c_thid;
125 acd->c_tmout = tmout;
129 acd->c_tmout = tmout;
137 acd_done((
struct acd *)atapi, arg, ret);
140int acd_read(
struct acd *
acd, acd_lsn_t lsn,
void *buf,
int sectors)
165 memset(&u, 0,
sizeof(u));
171 u.lba[0] = (lsn & 0xFF000000) >> 24;
172 u.lba[1] = (lsn & 0xFF0000) >> 16;
173 u.lba[2] = (lsn & 0xFF00) >> 8;
175 u.len[0] = (sectors & 0xFF00) >> 8;
176 u.len[1] = sectors & 0xFF;
177 return acd_request_in(
acd, flag, &u.pkt, buf, sectors << 11, (acAtapiDone)acd_read_done,
"read");
180int acd_readtoc(
struct acd *
acd,
void *buf,
int size)
188 memset(&v4, 0,
sizeof(v4));
191 v4.u_b[7] = (size & 0xFF00) >> 8;
193 v4.u_w[2] = size & 0xFF;
194 return acd_request_in(
acd, 2, &v4, buf, size, 0,
"readtoc");
197int acd_seek(
struct acd *
acd, acd_lsn_t lsn)
203 memset(&v3, 0,
sizeof(v3));
205 v3.u_b[2] = (lsn & 0xFF000000) >> 24;
206 v3.u_b[3] = (lsn & 0xFF0000) >> 16;
207 v3.u_w[1] = (lsn & 0xFF00) >> 8;
210 return acd_request_in(
acd, 2, &v3, 0, 0, 0,
"seek");
220 arg->status = (arg->status | 6) ^ 4;
223 acd_done((
struct acd *)atapi, arg, ret);
233 arg->status = (arg->status | 6) ^ 2;
236 acd_done((
struct acd *)atapi, arg, ret);
239int acd_ioctl(
struct acd *
acd,
int cmd)
260 memset(&u, 0,
sizeof(u));
265 name =
"ioctl:seek+start";
267 else if ( (cmd & 5) != 0 )
270 u.imm = (cmd & 0x80) != 0;
272 if ( (cmd & 2) != 0 )
274 done = (acAtapiDone)acd_opentray_done;
275 if ( (cmd & 1) != 0 )
276 done = (acAtapiDone)acd_closetray_done;
278 name =
"ioctl:startstop";
284 return acd_request_in(
acd, 2, &u.pkt, 0, 0, done, name);
287static int acd_mode_sense(
struct acd *
acd,
int pgcode,
void *buffer,
int size, acAtapiDone done,
char *name)
291 memset(&v7, 0,
sizeof(v7));
294 v7.u_b[7] = (size & 0xFF00) >> 8;
295 v7.u_w[2] = size & 0xFF;
296 return acd_request_in(
acd, 2, &v7, buffer, size, done, name);
299static int acd_mode_select(
struct acd *
acd,
void *buffer,
int size, acAtapiDone done,
char *name)
303 memset(&v6, 0,
sizeof(v6));
306 v6.u_b[7] = (size & 0xFF00) >> 8;
307 v6.u_w[2] = size & 0xFF;
308 return acd_request_in(
acd, 6, &v6, buffer, size, done, name);
323 h_mtype = arg->retry.me_h.h_mtype;
324 status = arg->status | 6;
325 arg->medium = h_mtype;
326 if ( h_mtype == 113 )
330 arg->status = v7 | 0xA00;
333 acd_done((
struct acd *)atapi, arg, h_mtype);
336int acd_getmedium(
struct acd *
acd)
342 return acd_mode_sense(
acd, 1, &Acdc.retry, 20, (acAtapiDone)acd_getmedium_done,
"getmedium");
345 if ( (Acdc.status & 0x800) != 0 )
364 h_mtype = arg->retry.me_h.h_mtype;
365 status = arg->status | 6;
366 arg->medium = h_mtype;
367 if ( h_mtype == 113 )
371 arg->status = v8 | 0xA00;
372 me_rretry = arg->retry.me_rretry;
375 acd_done((
struct acd *)atapi, arg, me_rretry);
378int acd_getretry(
struct acd *
acd)
382 return acd_mode_sense(
acd, 1, &Acdc.retry, 20, (acAtapiDone)acd_retry_done,
"getretry");
385int acd_setretry(
struct acd *
acd,
int rretry)
394 if ( (Acdc.status & 0x200) == 0 )
400 if ( rretry != Acdc.retry.me_rretry )
402 Acdc.retry.me_rretry = rretry;
403 size = (Acdc.retry.me_h.h_len[0] << 8) + Acdc.retry.me_h.h_len[1] + 2;
408 return acd_mode_select(
acd, &Acdc.retry, size, (acAtapiDone)acd_retry_done,
"setretry");
424 speed = arg->speed.mc_h.h_mtype;
425 v4 = (arg->speed.mc_speed[0] << 8) + arg->speed.mc_speed[1];
426 status = arg->status | 6;
432 arg->status = v8 | 0xC00;
435 acd_done((
struct acd *)atapi, arg, v4);
451 speed = arg->speed.mc_h.h_mtype;
452 v4 = (arg->speed.mc_maxspeed[0] << 8) + arg->speed.mc_maxspeed[1];
453 status = arg->status | 6;
459 arg->status = v8 | 0xC00;
462 acd_done((
struct acd *)atapi, arg, v4);
465int acd_getspeed(
struct acd *
acd,
int maxspeed)
473 done = (acAtapiDone)acd_getspeed_done;
475 done = (acAtapiDone)acd_getmaxspeed_done;
476 return acd_mode_sense(
acd, 42, &Acdc.speed, 28, done,
"getspeed");
479int acd_setspeed(
struct acd *
acd,
int speed)
501 if ( (Acdc.status & 0x400) != 0 )
502 ospeed = (Acdc.speed.mc_speed[0] << 8) + Acdc.speed.mc_speed[1];
510 memset(&u, 0,
sizeof(u));
513 u.speed[0] = (v3 & 0xFF00) >> 8;
515 return acd_request_in(
acd, 2, &u.pkt, 0, 0, 0,
"setspeed");
531 h_mtype = arg->timer.md_h.h_mtype;
532 status = arg->status | 6;
533 arg->medium = h_mtype;
534 if ( h_mtype == 113 )
535 status_v3 = status ^ 4;
537 status_v3 = status ^ 2;
538 arg->status = status_v3 | 0x900;
539 v4 = arg->timer.md_timer & 0xF;
542 acd_done((
struct acd *)atapi, arg, v4);
545int acd_gettimer(
struct acd *
acd)
549 return acd_mode_sense(
acd, 13, &Acdc.timer, 16, (acAtapiDone)acd_timer_done,
"gettimer");
552int acd_settimer(
struct acd *
acd,
int time)
563 if ( (Acdc.status & 0x100) == 0 )
568 Acdc.timer.md_timer = v3 & 0xF;
569 acdc = ((Acdc.timer.md_h.h_len[0] << 8) + Acdc.timer.md_h.h_len[1] + 2);
571 return acd_mode_select(
acd, &Acdc.timer, acdc, (acAtapiDone)acd_timer_done,
"settimer");
574int acd_ready(
struct acd *
acd)
580 memset(&v2, 0,
sizeof(v2));
581 return acd_request_in(
acd, 2, &v2, 0, 0, 0,
"ready");
584int acd_readcapacity()
596 acUint8 padding1[10];
601 acd_setup(&acd_data, 0, 0, 5000000);
602 memset(&u, 0,
sizeof(u));
605 ret = acd_request_in(&acd_data, 2, &u.pkt, &capacity, 8, 0,
"readcapacity");
610 val = *(
unsigned int *)capacity.lba;
611 return (val << 24) + ((val & 0xFF00) << 8) + ((val >> 8) & 0xFF00) + ((val >> 24) & 0xFF);
623 SysClock2USec(&t, &s, &us);
626 return 1000000 * (13 - s) - us;
634acCdvdsifId acd_gettray()
636 if ( (Acdc.status & 8) != 0 )
638 if ( (Acdc.status & 2) != 0 )
640 return (Acdc.status >> 1) & 2;
643struct acd *acd_setup(
struct acd *
acd, acd_done_t done,
void *arg,
int tmout)
650 acd->c_tmout = tmout;
652 acd->c_tmout = 5000000;
657int acd_sync(
struct acd *
acd,
int nblocking,
int *resultp)
668 v7 = acAtapiStatus(&
acd->c_atapi);
673 acd->c_thid = GetThreadId();
681 if ( !(ret | nblocking) )
686 if ( ret > 0 && resultp )
688 *resultp =
acd->c_thid;
693static void acd_ata_done(
acAtaT ata,
void *arg,
int ret)
699 acdata = (
struct acd_ata *)ata;
700 thid = acdata->a_thid;
701 acdata->a_result = ret;
706int acd_ata_request(
int flag, acAtaCommandT cmd,
int items, acAtaDone done,
char *name)
712 acAtaSetup(&acdata.a_ata, done ? done : acd_ata_done, 0, 0x4C4B40u);
714 acdata.a_thid = GetThreadId();
716 ret = acAtaRequest(&acdata.a_ata, flag, cmd, items, 0, 0);
722 return acdata.a_result;
725static void acd_getstatus_done(
acAtaT ata,
void *arg,
int ret)
730 acdata = (
struct acd_ata *)ata;
732 ret = *(acUint8 *)acAtaReply(&acdata->a_ata);
733 thid = acdata->a_thid;
734 acdata->a_result = ret;
741 acAtaCommandData v1[4];
743 v1[1] = ATA_C_CHECK_POWER_MODE | 0x700;
744 v1[0] = (Acdc.drive & 0xFF) | 0x2600;
745 return acd_ata_request(Acdc.drive | 2, v1, 2, acd_getstatus_done,
"getstatus");
748static int acd_setfeatures(
int feature,
int value)
750 acAtaCommandData v3[4];
752 v3[2] = (value & 0xFF) | 0x200;
753 v3[1] = (feature & 0xFF) | 0x100;
755 v3[0] = (Acdc.drive & 0xFF) | 0x600;
756 return acd_ata_request(Acdc.drive | 2, v3, 4, 0,
"setfeatures");
759int acd_setdma(acCdvdsifId dma)
770 Acdc.dma = AC_CDVDSIF_ID_NOP;
779 if ( (Acdc.dmamap & ret_v3) != 0 )
788 if ( (Acdc.dmamap & (1 << v1)) == 0 )
792 if ( (
unsigned int)v1 < AC_CDVDSIF_ID_PAUSES )
794 if ( (
unsigned int)v1 < AC_CDVDSIF_ID_STOP )
796 if ( (
unsigned int)v1 >= AC_CDVDSIF_ID_PAUSE )
808 ret = acd_setfeatures(3, mode);
813 ret = acd_setfeatures(102, 0);
822acCdvdsifId acd_getdma()
827static int acd_identify(
int drive)
833 acAtaCommandData cmd[2];
835 flag = 16 * (drive != 0);
836 cmd[0] = flag | 0x600;
837 cmd[1] = ATA_C_IDENTIFY_PACKET_DEVICE | 0x700;
838 acAtaSetup(&acdata.a_ata, acd_ata_done, 0, 0x4C4B40u);
840 acdata.a_thid = GetThreadId();
842 ret = acAtaRequest(&acdata.a_ata, flag | 2, cmd, 2, ident, 512);
846 ret = acdata.a_result;
852 if ( (ident[0] & 0xFF00) != 0x8500 )
854 return ((ident[62] & 0xFF) << 8) | ((ident[63] & 0xFF) << 16) | ((ident[88] & 0xFF) << 24);
857static int acd_softreset(
int drive)
864int acd_module_status()
871 if ( (Acdc.status & 1) != 0 )
874 if ( Acdc.active > 0 )
881int acd_module_start(
int argc,
char **argv)
889 ret = acd_module_status();
897 acd_softreset(drive);
898 ret_v2 = acd_identify(drive);
912 Acdc.dmamap = ret_v2;
913 acd_setdma((acCdvdsifId)32);
921 ret = acd_module_status();
930int acd_module_restart(
int argc,
char **argv)
int CpuResumeIntr(int state)
int CpuSuspendIntr(int *state)