sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

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 }