27#define MODNAME "hdcombo_driver"
30#define M_PRINTF(format, args...) \
31 printf(MODNAME ": " format, ##args)
33#define BANNER "ATA device driver for HD Pro Kit %s\n"
36#define ATA_XFER_MODE_PIO 0x08
38#define ATA_EV_TIMEOUT 1
39#define ATA_EV_COMPLETE 2
44#define HDPROreg_IO8 (*(vu8 *)0xBFC00000)
45#define HDPROreg_IO32 (*(vu32 *)0xBFC00000)
47#define CDVDreg_STATUS (*(vu8 *)0xBF40200A)
50#define ATAreg_CONTROL_RD 0x68
51#define ATAreg_SELECT_RD 0x70
52#define ATAreg_STATUS_RD 0xf0
53#define ATAreg_ERROR_RD 0x90
54#define ATAreg_NSECTOR_RD 0x50
55#define ATAreg_SECTOR_RD 0xd0
56#define ATAreg_LCYL_RD 0x30
57#define ATAreg_HCYL_RD 0xb0
58#define ATAreg_DATA_RD 0x41
61#define ATAreg_CONTROL_WR 0x6a
62#define ATAreg_SELECT_WR 0x72
63#define ATAreg_COMMAND_WR 0xf2
64#define ATAreg_FEATURE_WR 0x92
65#define ATAreg_NSECTOR_WR 0x52
66#define ATAreg_SECTOR_WR 0xd2
67#define ATAreg_LCYL_WR 0x32
68#define ATAreg_HCYL_WR 0xb2
69#define ATAreg_DATA_WR 0x12
71static int ata_devinfo_init = 0;
72static int ata_evflg = -1;
79static u16 ata_param[256];
91 {ATA_C_CFA_REQUEST_EXTENDED_ERROR_CODE, 1},
92 {ATA_C_DEVICE_RESET, 5},
93 {ATA_C_READ_SECTOR, 2},
94 {ATA_C_READ_SECTOR_EXT, 0x82},
95 {ATA_C_WRITE_SECTOR, 3},
96 {ATA_C_WRITE_LONG, 8},
97 {ATA_C_WRITE_SECTOR_EXT, 0x83},
98 {ATA_C_CFA_WRITE_SECTORS_WITHOUT_ERASE, 3},
99 {ATA_C_READ_VERIFY_SECTOR, 1},
100 {ATA_C_READ_VERIFY_SECTOR_EXT, 0x81},
102 {ATA_C_CFA_TRANSLATE_SECTOR, 2},
103 {ATA_C_SCE_SECURITY_CONTROL, 7},
104 {ATA_C_EXECUTE_DEVICE_DIAGNOSTIC, 6},
105 {ATA_C_INITIALIZE_DEVICE_PARAMETERS, 1},
106 {ATA_C_DOWNLOAD_MICROCODE, 3},
107 {ATA_C_IDENTIFY_PACKET_DEVICE, 2},
109 {ATA_C_CFA_ERASE_SECTORS, 1},
110 {ATA_C_READ_MULTIPLE, 2},
111 {ATA_C_WRITE_MULTIPLE, 3},
112 {ATA_C_SET_MULTIPLE_MODE, 1},
113 {ATA_C_CFA_WRITE_MULTIPLE_WITHOUT_ERASE, 3},
114 {ATA_C_GET_MEDIA_STATUS, 1},
115 {ATA_C_MEDIA_LOCK, 1},
116 {ATA_C_MEDIA_UNLOCK, 1},
117 {ATA_C_STANDBY_IMMEDIATE, 1},
118 {ATA_C_IDLE_IMMEDIATE, 1},
121 {ATA_C_READ_BUFFER, 2},
122 {ATA_C_CHECK_POWER_MODE, 1},
124 {ATA_C_FLUSH_CACHE, 1},
125 {ATA_C_WRITE_BUFFER, 3},
126 {ATA_C_FLUSH_CACHE_EXT, 1},
127 {ATA_C_IDENTIFY_DEVICE, 2},
128 {ATA_C_MEDIA_EJECT, 1},
129 {ATA_C_SET_FEATURES, 1},
130 {ATA_C_SECURITY_SET_PASSWORD, 3},
131 {ATA_C_SECURITY_UNLOCK, 3},
132 {ATA_C_SECURITY_ERASE_PREPARE, 1},
133 {ATA_C_SECURITY_ERASE_UNIT, 3},
134 {ATA_C_SECURITY_FREEZE_LOCK, 1},
135 {ATA_C_SECURITY_DISABLE_PASSWORD, 3},
136 {ATA_C_READ_NATIVE_MAX_ADDRESS, 1},
137 {ATA_C_SET_MAX_ADDRESS, 1}};
138#define ATA_CMD_TABLE_SIZE (sizeof ata_cmd_table / sizeof(ata_cmd_info_t))
141 {ATA_S_SMART_READ_DATA, 2},
142 {ATA_S_SMART_ENABLE_DISABLE_AUTOSAVE, 1},
143 {ATA_S_SMART_SAVE_ATTRIBUTE_VALUES, 1},
144 {ATA_S_SMART_EXECUTE_OFF_LINE, 1},
145 {ATA_S_SMART_READ_LOG, 2},
146 {ATA_S_SMART_WRITE_LOG, 3},
147 {ATA_S_SMART_ENABLE_OPERATIONS, 1},
148 {ATA_S_SMART_DISABLE_OPERATIONS, 1},
149 {ATA_S_SMART_RETURN_STATUS, 1}};
150#define SMART_CMD_TABLE_SIZE (sizeof smart_cmd_table / sizeof(ata_cmd_info_t))
167static int hdpro_io_active = 0;
168static int intr_suspended = 0;
169static int intr_state;
171static int hdpro_io_start(
void);
172static int hdpro_io_finish(
void);
173static void hdpro_io_write(u8 cmd, u16 val);
174static int hdpro_io_read(u8 cmd);
175static int ata_bus_reset(
void);
177static int gen_ata_wait_busy(
int bits);
181static unsigned int ata_alarm_cb(
void *unused)
185 iSetEventFlag(ata_evflg, ATA_EV_TIMEOUT);
189static void suspend_intr(
void)
191 if (!intr_suspended) {
198static void resume_intr(
void)
200 if (intr_suspended) {
207static int ata_create_event_flag(
void)
213 return CreateEventFlag(&
event);
216int _start(
int argc,
char *argv[])
218 int res = MODULE_NO_RESIDENT_END;
223 printf(BANNER, VERSION);
225 if (!hdpro_io_start()) {
226 M_PRINTF(
"Failed to detect HD Pro, exiting.\n");
232 if ((ata_evflg = ata_create_event_flag()) < 0) {
233 M_PRINTF(
"Couldn't create event flag, exiting.\n");
237 if (RegisterLibraryEntries(&_exp_atad) != 0) {
238 M_PRINTF(
"Library is already registered, exiting.\n");
242 res = MODULE_RESIDENT_END;
243 M_PRINTF(
"Driver loaded.\n");
255int sceAtaGetError(
void)
257 return hdpro_io_read(ATAreg_ERROR_RD) & 0xff;
260#define ATA_WAIT_BUSY 0x80
261#define ATA_WAIT_BUSBUSY 0x88
263#define ata_wait_busy() gen_ata_wait_busy(ATA_WAIT_BUSY)
264#define ata_wait_bus_busy() gen_ata_wait_busy(ATA_WAIT_BUSBUSY)
268static int gen_ata_wait_busy(
int bits)
273 for (i = 0; i < 80; i++) {
277 u16 r_control = hdpro_io_read(ATAreg_CONTROL_RD);
281 if (r_control == 0xffff)
282 return ATA_RES_ERR_TIMEOUT;
284 if (!(r_control & bits))
310 res = ATA_RES_ERR_TIMEOUT;
311 M_PRINTF(
"Timeout while waiting on busy (0x%02x).\n", bits);
320static int hdpro_io_start(
void)
336 unsigned int res = HDPROreg_IO8;
342 if ((res & 0xff) == 0xe7)
345 return hdpro_io_active;
349static int hdpro_io_finish(
void)
351 if (!hdpro_io_active)
364 if (HDPROreg_IO32 == 0x401a7800)
367 return hdpro_io_active ^ 1;
370static void hdpro_io_write(u8 cmd, u16 val)
379 HDPROreg_IO8 = (val & 0xffff) >> 8;
385static int hdpro_io_read(u8 cmd)
392 unsigned int res0 = HDPROreg_IO8;
394 unsigned int res1 = HDPROreg_IO8;
396 res0 = (res0 & 0xff) | (res1 << 8);
400 return res0 & 0xffff;
404static int ata_bus_reset(
void)
429 return ata_wait_busy();
432static int ata_device_select(
int device)
436 if ((res = ata_wait_bus_busy()) < 0)
440 if (((hdpro_io_read(ATAreg_SELECT_RD) >> 4) & 1) == device)
444 hdpro_io_write(ATAreg_SELECT_WR, (device & 1) << 4);
445 (void)(hdpro_io_read(ATAreg_CONTROL_RD));
447 return ata_wait_bus_busy();
451int sceAtaExecCmd(
void *buf, u32 blkcount, u16 feature, u16 nsector, u16 sector, u16 lcyl, u16 hcyl, u16 select, u16 command)
455 int i, res, type, cmd_table_size;
456 int using_timeout, device = (select >> 4) & 1;
459 ClearEventFlag(ata_evflg, 0);
461 if (!atad_devinfo[device].exists)
462 return ATA_RES_ERR_NODEV;
464 if ((res = ata_device_select(device)) != 0)
469 if (command == ATA_C_SMART) {
470 cmd_table = smart_cmd_table;
471 cmd_table_size = SMART_CMD_TABLE_SIZE;
474 cmd_table = ata_cmd_table;
475 cmd_table_size = ATA_CMD_TABLE_SIZE;
476 searchcmd = command & 0xff;
480 for (i = 0; i < cmd_table_size; i++) {
481 if (searchcmd == cmd_table[i].command) {
482 type = cmd_table[i].type;
487 if (!(atad_cmd_state.type = type & 0x7F))
488 return ATA_RES_ERR_CMD;
490 atad_cmd_state.buf = buf;
491 atad_cmd_state.blkcount = blkcount;
494 if (!(hdpro_io_read(ATAreg_CONTROL_RD) & 0x40)) {
496 case ATA_C_DEVICE_RESET:
497 case ATA_C_EXECUTE_DEVICE_DIAGNOSTIC:
498 case ATA_C_INITIALIZE_DEVICE_PARAMETERS:
500 case ATA_C_IDENTIFY_PACKET_DEVICE:
503 M_PRINTF(
"Error: Device %d is not ready.\n", device);
504 return ATA_RES_ERR_NOTREADY;
510 switch (type & 0x7F) {
519 cmd_timeout.lo = 0x41eb0000;
522 if ((res = SetAlarm(&cmd_timeout, &ata_alarm_cb, NULL)) < 0)
530 (void)(HDPROreg_IO8);
535 hdpro_io_write(ATAreg_CONTROL_WR, (using_timeout == 0) << 1);
542 hdpro_io_write(ATAreg_FEATURE_WR, (feature & 0xffff) >> 8);
543 hdpro_io_write(ATAreg_NSECTOR_WR, (nsector & 0xffff) >> 8);
544 hdpro_io_write(ATAreg_SECTOR_WR, (sector & 0xffff) >> 8);
545 hdpro_io_write(ATAreg_LCYL_WR, (lcyl & 0xffff) >> 8);
546 hdpro_io_write(ATAreg_HCYL_WR, (hcyl & 0xffff) >> 8);
549 hdpro_io_write(ATAreg_FEATURE_WR, feature & 0xff);
550 hdpro_io_write(ATAreg_NSECTOR_WR, nsector & 0xff);
551 hdpro_io_write(ATAreg_SECTOR_WR, sector & 0xff);
552 hdpro_io_write(ATAreg_LCYL_WR, lcyl & 0xff);
553 hdpro_io_write(ATAreg_HCYL_WR, hcyl & 0xff);
555 hdpro_io_write(ATAreg_SELECT_WR, (select | ATA_SEL_LBA) & 0xff);
556 hdpro_io_write(ATAreg_COMMAND_WR, command & 0xff);
566 int res = 0, chk = 0;
567 u16 status = hdpro_io_read(ATAreg_STATUS_RD);
569 if (status & ATA_STAT_ERR) {
570 M_PRINTF(
"Error: Command error: status 0x%02x, error 0x%02x.\n", status, sceAtaGetError());
571 return ATA_RES_ERR_IO;
575 if (!(status & ATA_STAT_DRQ))
576 return ATA_RES_ERR_NODATA;
578 type = cmd_state->type;
580 if (type == 3 || type == 8) {
582 buf16 = cmd_state->buf16;
587 for (i = 0; i < 256; i++) {
589 hdpro_io_write(ATAreg_DATA_WR, r_data);
591 cmd_state->buf = ++buf16;
594 u16 out = hdpro_io_read(ATAreg_DATA_RD) & 0xffff;
595 if (out != (chk & 0xffff))
596 return ATA_RES_ERR_IO;
598 if (cmd_state->type == 8) {
601 buf8 = cmd_state->buf8;
602 for (i = 0; i < 4; i++) {
603 hdpro_io_write(ATAreg_DATA_WR, *buf8);
604 cmd_state->buf = ++buf8;
608 }
else if (type == 2) {
610 buf16 = cmd_state->buf16;
618 for (i = 0; i < 256; i++) {
620 unsigned int res0 = HDPROreg_IO8;
622 unsigned int res1 = HDPROreg_IO8;
625 res0 = (res0 & 0xff) | (res1 << 8);
628 *buf16 = res0 & 0xffff;
629 cmd_state->buf16 = ++buf16;
638 u16 r_data = hdpro_io_read(ATAreg_DATA_RD) & 0xffff;
639 if (r_data != (chk & 0xffff))
640 return ATA_RES_ERR_IO;
647int sceAtaSoftReset(
void)
649 if (hdpro_io_read(ATAreg_CONTROL_RD) & 0x80)
650 return ATA_RES_ERR_NOTREADY;
653 hdpro_io_write(ATAreg_CONTROL_WR, 6);
657 hdpro_io_write(ATAreg_CONTROL_WR, 2);
660 return ata_wait_busy();
664int sceAtaSecurityUnLock(
int device,
void *password)
673 u16 nsector, lcyl, hcyl, sector;
678 if (hdpro_io_read(ATAreg_CONTROL_RD) & 0x88)
681 nsector = hdpro_io_read(ATAreg_NSECTOR_RD) & 0xff;
682 sector = hdpro_io_read(ATAreg_SECTOR_RD) & 0xff;
683 lcyl = hdpro_io_read(ATAreg_LCYL_RD) & 0xff;
684 hcyl = hdpro_io_read(ATAreg_HCYL_RD) & 0xff;
685 (void)(hdpro_io_read(ATAreg_SELECT_RD) & 0xff);
690 if ((nsector != 1) || (sector != 1))
694 if ((lcyl == 0x00) && (hcyl == 0x00))
696 else if ((lcyl == 0x14) && (hcyl == 0xeb))
701 hdpro_io_write(ATAreg_LCYL_WR, 0x55);
702 hdpro_io_write(ATAreg_HCYL_WR, 0xaa);
703 lcyl = hdpro_io_read(ATAreg_LCYL_RD) & 0xff;
704 hcyl = hdpro_io_read(ATAreg_HCYL_RD) & 0xff;
706 if ((lcyl != 0x55) || (hcyl != 0xaa))
711int sceAtaFlushCache(
int device)
715 if (!hdpro_io_start())
718 if (!(res = sceAtaExecCmd(NULL, 1, 0, 0, 0, 0, 0, (device << 4) & 0xffff, atad_devinfo[device].lba48 ? ATA_C_FLUSH_CACHE_EXT : ATA_C_FLUSH_CACHE)))
719 res = sceAtaWaitResult();
721 if (!hdpro_io_finish())
728int ata_device_idle(
int device,
int period)
732 res = sceAtaExecCmd(NULL, 1, 0, period & 0xff, 0, 0, 0, (device << 4) & 0xffff, ATA_C_IDLE);
736 return sceAtaWaitResult();
740static int ata_device_set_transfer_mode(
int device,
int type,
int mode)
744 res = sceAtaExecCmd(NULL, 1, 3, (type | mode) & 0xff, 0, 0, 0, (device << 4) & 0xffff, ATA_C_SET_FEATURES);
748 res = sceAtaWaitResult();
755static int ata_device_identify(
int device,
void *
info)
759 res = sceAtaExecCmd(
info, 1, 0, 0, 0, 0, 0, (device << 4) & 0xffff, ATA_C_IDENTIFY_DEVICE);
763 return sceAtaWaitResult();
766static int ata_device_smart_enable(
int device)
770 if (!(res = sceAtaExecCmd(NULL, 1, ATA_S_SMART_ENABLE_OPERATIONS, 0, 0, 0x4f, 0xc2, (device << 4) & 0xffff, ATA_C_SMART)))
771 res = sceAtaWaitResult();
780 if ((res = sceAtaSoftReset()) != 0)
783 ata_device_probe(&devinfo[0]);
784 if (!devinfo[0].exists) {
785 M_PRINTF(
"Error: Unable to detect HDD 0.\n");
787 return ATA_RES_ERR_NODEV;
791 if ((res = ata_device_select(1)) != 0)
793 if (hdpro_io_read(ATAreg_CONTROL_RD) & 0xff)
794 ata_device_probe(&devinfo[1]);
798 for (i = 0; i < 2; i++) {
799 if (!devinfo[i].exists)
804 if (!devinfo[i].has_packet) {
805 res = ata_device_identify(i, ata_param);
806 devinfo[i].
exists = (res == 0);
807 }
else if (devinfo[i].has_packet == 1) {
816 devinfo[i].
exists = (res == 0);
822 if (!devinfo[i].exists || devinfo[i].has_packet)
828 if (ata_param[ATA_ID_COMMAND_SETS_SUPPORTED] & 0x0400) {
829 atad_devinfo[i].
lba48 = 1;
831 if (ata_param[ATA_ID_48BIT_SECTOTAL_HI]) {
835 (ata_param[ATA_ID_48BIT_SECTOTAL_MI] << 16) |
836 ata_param[ATA_ID_48BIT_SECTOTAL_LO];
839 atad_devinfo[i].
lba48 = 0;
840 devinfo[i].
total_sectors = (ata_param[ATA_ID_SECTOTAL_HI] << 16) |
841 ata_param[ATA_ID_SECTOTAL_LO];
846 ata_device_set_transfer_mode(i, ATA_XFER_MODE_PIO, 0);
847 ata_device_smart_enable(i);
849 ata_device_idle(i, 0);
855int sceAtaWaitResult(
void)
859 int res = 0, type = cmd_state->type;
862 if (type == 1 || type == 6) {
870 unsigned int ret = HDPROreg_IO8;
875 if (((ret & 0xff) & 1) != 0) {
882 if (PollEventFlag(ata_evflg, ATA_EV_TIMEOUT | ATA_EV_COMPLETE, WEF_CLEAR | WEF_OR, &bits) == 0) {
883 if (bits & ATA_EV_TIMEOUT) {
884 M_PRINTF(
"Error: ATA timeout on a non-data command.\n");
885 return ATA_RES_ERR_TIMEOUT;
895 stat = hdpro_io_read(ATAreg_CONTROL_RD);
896 if ((res = ata_wait_busy()) < 0)
900 while ((
int)(--cmd_state->blkcount) != -1) {
901 if ((res = ata_pio_transfer(cmd_state)) < 0)
903 if ((res = ata_wait_busy()) < 0)
912 if (hdpro_io_read(ATAreg_STATUS_RD) & ATA_STAT_BUSY)
913 res = ata_wait_busy();
914 if ((stat = hdpro_io_read(ATAreg_STATUS_RD)) & ATA_STAT_ERR) {
915 M_PRINTF(
"Error: Command error: status 0x%02x, error 0x%02x.\n", stat, sceAtaGetError());
916 res = ATA_RES_ERR_IO;
921 CancelAlarm(&ata_alarm_cb, NULL);
927int sceAtaDmaTransfer(
int device,
void *buf, u32 lba, u32 nsectors,
int dir)
930 u16 sector, lcyl, hcyl, select, command, len;
932 if (!hdpro_io_start())
936 len = (nsectors > 256) ? 256 : nsectors;
939 lcyl = (lba >> 8) & 0xff;
940 hcyl = (lba >> 16) & 0xff;
942 if (atad_devinfo[device].lba48) {
945 sector = ((lba >> 16) & 0xff00) | (lba & 0xff);
947 select = (device << 4) & 0xffff;
948 command = (dir == 1) ? ATA_C_WRITE_SECTOR_EXT : ATA_C_READ_SECTOR_EXT;
953 select = ((device << 4) | ((lba >> 24) & 0xf)) & 0xffff;
954 command = (dir == 1) ? ATA_C_WRITE_SECTOR : ATA_C_READ_SECTOR;
958 if ((res = sceAtaExecCmd(buf, len, 0, len, sector, lcyl,
959 hcyl, select, command)) != 0)
961 if ((res = sceAtaWaitResult()) != 0)
964 buf = (
void *)((u8 *)buf + len * 512);
969 if (!hdpro_io_finish())
978 if (!ata_devinfo_init) {
979 ata_devinfo_init = 1;
981 if (!hdpro_io_start())
987 if ((ata_bus_reset() != 0) || (ata_init_devices(atad_devinfo) != 0) || (!hdpro_io_finish()))
991 return &atad_devinfo[device];
int CpuResumeIntr(int state)
int CpuSuspendIntr(int *state)