leointerrupt.c (8612B)
1 #include "libultra_internal.h" 2 #include "PR/rcp.h" 3 #include "bstring.h" 4 #include "new_func.h" 5 #include "macros.h" 6 #include "piint.h" 7 #include "osint.h" 8 9 u8 leoDiskStack[OS_PIM_STACKSIZE]; // technically should have a OS_LEO_STACKSIZE or something.. 10 11 static void __osLeoResume(void); 12 static void __osLeoAbnormalResume(void); 13 14 s32 __osLeoInterrupt(void) { 15 u32 stat; 16 #ifdef VERSION_EU 17 u32 pi_stat; 18 #else // VERSION_SH 19 volatile u32 pi_stat; 20 #endif 21 u32 bm_stat; 22 __OSTranxInfo *info; 23 __OSBlockInfo *blockInfo; 24 25 #ifdef VERSION_EU 26 if (!osDDActive) { 27 return 0; 28 } 29 #else // VERSION_SH 30 stat = 0; 31 #endif 32 33 info = &__osDiskHandle->transferInfo; 34 blockInfo = &info->block[info->blockNum]; 35 pi_stat = IO_READ(PI_STATUS_REG); 36 if (pi_stat & PI_STATUS_DMA_BUSY) { 37 #ifdef VERSION_EU 38 IO_WRITE(PI_STATUS_REG, PI_STATUS_RESET | PI_STATUS_CLR_INTR); 39 WAIT_ON_LEO_IO_BUSY(pi_stat); 40 stat = IO_READ(LEO_STATUS); 41 if (stat & LEO_STATUS_MECHANIC_INTERRUPT) { 42 WAIT_ON_LEO_IO_BUSY(pi_stat); 43 IO_WRITE(LEO_BM_CTL, info->bmCtlShadow | LEO_BM_CTL_CLR_MECHANIC_INTR); 44 } 45 info->errStatus = LEO_ERROR_75; 46 __osLeoAbnormalResume(); 47 #else // VERSION_SH 48 __OSGlobalIntMask = __OSGlobalIntMask & ~SR_IBIT4; //cartridge interrupt 49 blockInfo->errStatus = LEO_ERROR_29; 50 __osLeoResume(); 51 #endif 52 return 1; 53 } 54 WAIT_ON_LEO_IO_BUSY(pi_stat); 55 stat = IO_READ(LEO_STATUS); 56 if (stat & LEO_STATUS_MECHANIC_INTERRUPT) { 57 WAIT_ON_LEO_IO_BUSY(pi_stat); 58 IO_WRITE(LEO_BM_CTL, info->bmCtlShadow | LEO_BM_CTL_CLR_MECHANIC_INTR); 59 #ifdef VERSION_EU 60 info->errStatus = LEO_ERROR_GOOD; 61 #else // VERSION_SH 62 blockInfo->errStatus = LEO_ERROR_GOOD; 63 #endif 64 return 0; 65 } 66 67 #ifdef VERSION_SH 68 if (info->cmdType == LEO_CMD_TYPE_2) { 69 return 1; 70 } 71 #endif 72 73 if (stat & LEO_STATUS_BUFFER_MANAGER_ERROR) { 74 #ifdef VERSION_EU 75 info->errStatus = LEO_ERROR_3; 76 __osLeoAbnormalResume(); 77 #else //VERSION_SH 78 WAIT_ON_LEO_IO_BUSY(pi_stat); 79 stat = IO_READ(LEO_STATUS); 80 blockInfo->errStatus = LEO_ERROR_22; 81 __osLeoResume(); 82 IO_WRITE(PI_STATUS_REG, PI_STATUS_CLR_INTR); 83 __OSGlobalIntMask |= OS_IM_PI; 84 #endif 85 return 1; 86 } 87 88 if (info->cmdType == LEO_CMD_TYPE_1) { 89 if ((stat & LEO_STATUS_DATA_REQUEST) == 0) { 90 if (info->sectorNum + 1 != info->transferMode * 85) { 91 #ifdef VERSION_EU 92 info->errStatus = LEO_ERROR_6; 93 #else // VERSION_SH 94 blockInfo->errStatus = LEO_ERROR_24; 95 #endif 96 __osLeoAbnormalResume(); 97 return 1; 98 } 99 IO_WRITE(PI_STATUS_REG, PI_STATUS_CLR_INTR); 100 __OSGlobalIntMask |= OS_IM_PI; 101 #ifdef VERSION_EU 102 info->errStatus = LEO_ERROR_GOOD; 103 #else // VERSION_SH 104 blockInfo->errStatus = LEO_ERROR_GOOD; 105 #endif 106 __osLeoResume(); 107 return 1; 108 } 109 blockInfo->dramAddr = (void *) ((u32)blockInfo->dramAddr + blockInfo->sectorSize); 110 info->sectorNum++; 111 osEPiRawStartDma(__osDiskHandle, OS_WRITE, LEO_SECTOR_BUFF, blockInfo->dramAddr, blockInfo->sectorSize); 112 return 1; 113 } 114 if (info->cmdType == LEO_CMD_TYPE_0) { 115 if (info->transferMode == LEO_SECTOR_MODE) { 116 if ((s32)blockInfo->C1ErrNum + 17 < info->sectorNum) { 117 #ifdef VERSION_EU 118 info->errStatus = LEO_ERROR_GOOD; 119 #else // VERSION_SH 120 blockInfo->errStatus = LEO_ERROR_GOOD; 121 #endif 122 __osLeoAbnormalResume(); 123 return 1; 124 } 125 if ((stat & LEO_STATUS_DATA_REQUEST) == 0) { 126 #ifdef VERSION_EU 127 info->errStatus = LEO_ERROR_17; 128 #else // VERSION_SH 129 blockInfo->errStatus = LEO_ERROR_23; 130 #endif 131 __osLeoAbnormalResume(); 132 return 1; 133 } 134 } else { 135 blockInfo->dramAddr = (void *)((u32)blockInfo->dramAddr + blockInfo->sectorSize); 136 } 137 bm_stat = IO_READ(LEO_BM_STATUS); 138 if ((bm_stat & LEO_BM_STATUS_C1SINGLE && bm_stat & LEO_BM_STATUS_C1DOUBLE) || bm_stat & LEO_BM_STATUS_MICRO) { 139 if (blockInfo->C1ErrNum > 3) { 140 if (info->transferMode != LEO_SECTOR_MODE || info->sectorNum > 0x52) { 141 #ifdef VERSION_EU 142 info->errStatus = LEO_ERROR_17; 143 #else // VERSION_SH 144 blockInfo->errStatus = LEO_ERROR_23; 145 #endif 146 __osLeoAbnormalResume(); 147 return 1; 148 } 149 } else { 150 s32 errNum = blockInfo->C1ErrNum; 151 blockInfo->C1ErrSector[errNum] = info->sectorNum + 1; 152 } 153 blockInfo->C1ErrNum++; 154 } 155 156 if (stat & LEO_STATUS_C2_TRANSFER) { 157 if (info->sectorNum != 87) { 158 #ifdef VERSION_EU 159 info->errStatus = LEO_ERROR_6; 160 #else // VERSION_SH 161 blockInfo->errStatus = LEO_ERROR_24; 162 #endif 163 __osLeoAbnormalResume(); 164 } 165 if (info->transferMode == LEO_TRACK_MODE && info->blockNum == 0) { 166 info->blockNum = 1; 167 info->sectorNum = -1; 168 info->block[1].dramAddr = (void *)((u32)info->block[1].dramAddr - info->block[1].sectorSize); 169 #ifdef VERSION_SH 170 blockInfo->errStatus = LEO_ERROR_22; 171 #endif 172 } else { 173 IO_WRITE(PI_STATUS_REG, PI_STATUS_CLR_INTR); 174 __OSGlobalIntMask |= OS_IM_PI; 175 #ifdef VERSION_SH 176 info->cmdType = LEO_CMD_TYPE_2; 177 blockInfo->errStatus = LEO_ERROR_GOOD; 178 #endif 179 } 180 osEPiRawStartDma(__osDiskHandle, OS_READ, LEO_C2_BUFF, blockInfo->C2Addr, blockInfo->sectorSize * 4); 181 #ifdef VERSION_EU 182 info->errStatus = LEO_ERROR_GOOD; 183 #endif 184 return 1; 185 } 186 if (info->sectorNum == -1 && info->transferMode == LEO_TRACK_MODE && info->blockNum == 1) { 187 __OSBlockInfo *bptr = &info->block[0]; 188 if (bptr->C1ErrNum == 0) { 189 if (((u32 *)bptr->C2Addr)[0] | ((u32 *)bptr->C2Addr)[1] | ((u32 *)bptr->C2Addr)[2] | ((u32 *)bptr->C2Addr)[3]) { 190 #ifdef VERSION_EU 191 info->errStatus = LEO_ERROR_6; 192 #else // VERSION_SH 193 bptr->errStatus = LEO_ERROR_24; 194 #endif 195 __osLeoAbnormalResume(); 196 return 1; 197 } 198 } 199 #ifdef VERSION_EU 200 info->errStatus = LEO_ERROR_GOOD; 201 #else // VERSION_SH 202 bptr->errStatus = LEO_ERROR_GOOD; 203 #endif 204 __osLeoResume(); 205 } 206 info->sectorNum++; 207 if (stat & LEO_STATUS_DATA_REQUEST) { 208 if (info->sectorNum > 0x54) { 209 #ifdef VERSION_EU 210 info->errStatus = LEO_ERROR_6; 211 #else // VERSION_SH 212 blockInfo->errStatus = LEO_ERROR_24; 213 #endif 214 __osLeoAbnormalResume(); 215 return 1; 216 } 217 osEPiRawStartDma(__osDiskHandle, 0, LEO_SECTOR_BUFF, blockInfo->dramAddr, blockInfo->sectorSize); 218 #ifdef VERSION_EU 219 info->errStatus = LEO_ERROR_GOOD; 220 #else // VERSION_SH 221 blockInfo->errStatus = LEO_ERROR_GOOD; 222 #endif 223 return 1; 224 } 225 if (info->sectorNum <= 0x54) { 226 #ifdef VERSION_EU 227 info->errStatus = LEO_ERROR_6; 228 #else // VERSION_SH 229 blockInfo->errStatus = LEO_ERROR_24; 230 #endif 231 __osLeoAbnormalResume(); 232 return 1; 233 } 234 return 1; 235 } 236 #ifdef VERSION_EU 237 info->errStatus = LEO_ERROR_75; 238 #else // VERSION_SH 239 blockInfo->errStatus = LEO_ERROR_4; 240 #endif 241 242 __osLeoAbnormalResume(); 243 return 1; 244 } 245 246 static void __osLeoAbnormalResume(void) { 247 __OSTranxInfo *info; 248 u32 pi_stat; 249 info = &__osDiskHandle->transferInfo; 250 WAIT_ON_LEO_IO_BUSY(pi_stat); 251 IO_WRITE(LEO_BM_CTL, info->bmCtlShadow | LEO_BM_CTL_RESET); 252 WAIT_ON_LEO_IO_BUSY(pi_stat); 253 IO_WRITE(LEO_BM_CTL, info->bmCtlShadow); 254 __osLeoResume(); 255 IO_WRITE(PI_STATUS_REG, PI_STATUS_CLR_INTR); 256 __OSGlobalIntMask |= OS_IM_PI; 257 } 258 259 static void __osLeoResume(void) { 260 __OSEventState *es; 261 OSMesgQueue *mq; 262 s32 last; 263 es = &__osEventStateTab[OS_EVENT_PI]; 264 mq = es->messageQueue; 265 if (mq == NULL || MQ_IS_FULL(mq)) { 266 return; 267 } 268 last = (mq->first + mq->validCount) % mq->msgCount; 269 mq->msg[last] = es->message; 270 mq->validCount++; 271 if (mq->mtqueue->next != NULL) { 272 __osEnqueueThread(&__osRunQueue, __osPopThread(&mq->mtqueue)); 273 } 274 }