Changeset 3751


Ignore:
Timestamp:
12/28/07 21:50:54 (5 years ago)
Author:
andrew
Message:

AR6000 interrupt logic. Fix reset.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/host/qemu-neo1973/hw/ar6000.c

    r3745 r3751  
    2727#include "hw.h" 
    2828#include "net.h" 
     29#include "qemu-timer.h" 
    2930#include "sd.h" 
    3031#include "pcmcia.h" 
     
    945946    struct sdio_s sd; 
    946947    NICInfo *nd; 
     948 
    947949    struct { 
    948950        uint8_t host_int_stat; 
     
    957959        uint8_t err_int_stat_ena; 
    958960        uint8_t cnt_int_stat_ena; 
    959         uint8_t cnt[8]; 
    960         uint32_t cnt_dec[8]; 
     961        uint8_t cnt[4]; 
     962        uint32_t cnt_tx[4]; 
    961963        uint8_t scratch[8]; 
     964        uint8_t wlan_int; 
    962965 
    963966        uint8_t mbox[0x800 * 4]; 
     
    967970        int done; 
    968971    } bmi; 
     972 
     973    QEMUTimer *cnt_irq_update; 
     974 
    969975    uint8_t cis[0]; 
    970976}; 
    971977 
     978static inline void ar6k_hif_intr_update(struct ar6k_s *s) 
     979{ 
     980    qemu_set_irq(s->sd.func_irq[0], 
     981                    !!(s->hif.host_int_stat & s->hif.int_stat_ena)); 
     982} 
     983 
     984static void ar6k_hif_error_intr_update(struct ar6k_s *s) 
     985{ 
     986    uint8_t orig = s->hif.host_int_stat; 
     987 
     988    if (s->hif.error_int_stat & s->hif.err_int_stat_ena) 
     989        s->hif.host_int_stat |= 1 << 7;                 /* STATUS_ERROR */ 
     990    else 
     991        s->hif.host_int_stat &= ~(1 << 7);              /* STATUS_ERROR */ 
     992 
     993    if (orig != s->hif.host_int_stat) 
     994        ar6k_hif_intr_update(s); 
     995} 
     996 
     997static void ar6k_hif_cpu_intr_update(struct ar6k_s *s) 
     998{ 
     999    uint8_t orig = s->hif.host_int_stat; 
     1000 
     1001    if (s->hif.cpu_int_stat & s->hif.cpu_int_stat_ena) 
     1002        s->hif.host_int_stat |= 1 << 6;                 /* STATUS_CPU */ 
     1003    else 
     1004        s->hif.host_int_stat &= ~(1 << 6);              /* STATUS_CPU */ 
     1005 
     1006    if (orig != s->hif.host_int_stat) 
     1007        ar6k_hif_intr_update(s); 
     1008} 
     1009 
     1010static void ar6k_hif_counter_intr_update(struct ar6k_s *s) 
     1011{ 
     1012    uint8_t orig = s->hif.host_int_stat; 
     1013 
     1014    if (s->hif.counter_int_stat & s->hif.cnt_int_stat_ena) 
     1015        s->hif.host_int_stat |= 1 << 4;                 /* STATUS_COUNTER */ 
     1016    else 
     1017        s->hif.host_int_stat &= ~(1 << 4);              /* STATUS_COUNTER */ 
     1018 
     1019    if (orig != s->hif.host_int_stat) 
     1020        ar6k_hif_intr_update(s); 
     1021} 
     1022 
     1023static void ar6k_hif_counter_intr_sched(struct ar6k_s *s) 
     1024{ 
     1025    qemu_mod_timer(s->cnt_irq_update, qemu_get_clock(vm_clock) + 
     1026                    (ticks_per_sec >> 6)); 
     1027} 
     1028 
     1029static void ar6k_hif_cnt_irq_tick(void *opaque) 
     1030{ 
     1031    struct ar6k_s *s = (void *) opaque; 
     1032 
     1033    ar6k_hif_counter_intr_update(s); 
     1034} 
     1035 
    9721036static void ar6k_bmi_reset(struct ar6k_s *s) 
    9731037{ 
    9741038    int i; 
    9751039 
    976     for (i = 0; i < 8; i ++) { 
     1040    for (i = 0; i < 4; i ++) { 
    9771041        s->hif.cnt[i] = 0x00; 
    978         s->hif.cnt_dec[i] = 0xff; 
    979     } 
    980  
    981     for (i = 0; i < 4; i ++) 
     1042        s->hif.cnt_tx[i] = 0xff; 
    9821043        s->hif.mbox_count[i] = 0; 
     1044    } 
    9831045 
    9841046    s->bmi.done = 0; 
     1047 
     1048    s->hif.host_int_stat = 0x00; 
     1049    s->hif.cpu_int_stat = 0x00; 
     1050    s->hif.error_int_stat = 0x00; 
     1051    s->hif.counter_int_stat = 0xf0; 
     1052    s->hif.int_stat_ena = 0x00; 
     1053    s->hif.cpu_int_stat_ena = 0x00; 
     1054    s->hif.err_int_stat_ena = 0x00; 
     1055    s->hif.cnt_int_stat_ena = 0x00; 
     1056 
     1057    ar6k_hif_cpu_intr_update(s); 
     1058    ar6k_hif_error_intr_update(s); 
     1059    ar6k_hif_counter_intr_update(s); 
    9851060} 
    9861061 
     
    10451120    } 
    10461121 
    1047     s->hif.cnt_dec[4] = 0xff; 
    1048     s->hif.cnt[4] = rlen; 
     1122    s->hif.cnt[0] = rlen; 
     1123} 
     1124 
     1125static void ar6k_hif_txcredit_reset(struct ar6k_s *s, int mbox) 
     1126{ 
     1127    s->hif.cnt_tx[mbox] = 0; 
     1128    if (!(s->hif.counter_int_stat & (1 << mbox))) { 
     1129        s->hif.counter_int_stat |= 1 << mbox; 
     1130        ar6k_hif_counter_intr_sched(s); 
     1131    } 
     1132} 
     1133 
     1134static void ar6k_hif_txcredit_grant(struct ar6k_s *s, int mbox) 
     1135{ 
     1136    s->hif.cnt_tx[mbox] = 0xff; 
     1137    if (!(s->hif.counter_int_stat & (1 << (mbox + 4)))) { 
     1138        s->hif.counter_int_stat |= 1 << (mbox + 4); 
     1139        ar6k_hif_counter_intr_sched(s); 
     1140    } 
    10491141} 
    10501142 
     
    10641156#define AR6K_COUNTER_INT_STAT_ENABLE    0x41b 
    10651157#define AR6K_COUNT                      0x420 
    1066 #define AR6K_COUNT_DEC                  0x440 
     1158#define AR6K_COUNT_RESET                0x440 
     1159#define AR6K_COUNT_DEC                  0x450 
    10671160#define AR6K_SCRATCH                    0x460 
    10681161#define AR6K_FIFO_TIMEOUT               0x468 
     
    10901183 
    10911184    switch (addr) { 
     1185    case AR6K_HOST_INT_STAT: 
     1186        if (s->hif.host_int_stat & value) { 
     1187            s->hif.host_int_stat &= ~value; 
     1188            ar6k_hif_intr_update(s); 
     1189        } 
     1190        break; 
     1191    case AR6K_CPU_INT_STAT: 
     1192        if (s->hif.cpu_int_stat & value) { 
     1193            s->hif.cpu_int_stat &= ~value; 
     1194            ar6k_hif_cpu_intr_update(s); 
     1195        } 
     1196        break; 
     1197    case AR6K_ERROR_INT_STAT: 
     1198        if (s->hif.error_int_stat & value) { 
     1199            s->hif.error_int_stat &= ~value; 
     1200            ar6k_hif_error_intr_update(s); 
     1201        } 
     1202        break; 
     1203    case AR6K_COUNTER_INT_STAT: 
     1204        if (s->hif.counter_int_stat & value) { 
     1205            s->hif.counter_int_stat &= ~value; 
     1206            ar6k_hif_counter_intr_update(s); 
     1207        } 
     1208        break; 
    10921209    case AR6K_MBOX_FRAME: 
    10931210        s->hif.mbox_frame = value; 
     
    11091226        break; 
    11101227    case AR6K_INT_STAT_ENABLE: 
    1111         s->hif.int_stat_ena = value; 
     1228        if (s->hif.int_stat_ena ^ value) { 
     1229            s->hif.int_stat_ena = value; 
     1230            ar6k_hif_intr_update(s); 
     1231        } 
    11121232        break; 
    11131233    case AR6K_CPU_INT_STAT_ENABLE: 
    1114         s->hif.cpu_int_stat_ena = value; 
     1234        if (s->hif.cpu_int_stat_ena ^ value) { 
     1235            s->hif.cpu_int_stat_ena = value; 
     1236            ar6k_hif_cpu_intr_update(s); 
     1237        } 
    11151238        break; 
    11161239    case AR6K_ERROR_STAT_ENABLE: 
    1117         s->hif.err_int_stat_ena = value; 
     1240        if (s->hif.err_int_stat_ena ^ value) { 
     1241            s->hif.err_int_stat_ena = value; 
     1242            ar6k_hif_error_intr_update(s); 
     1243        } 
    11181244        break; 
    11191245    case AR6K_COUNTER_INT_STAT_ENABLE: 
    1120         s->hif.cnt_int_stat_ena = value; 
     1246        if (s->hif.cnt_int_stat_ena ^ value) { 
     1247            s->hif.cnt_int_stat_ena = value; 
     1248            ar6k_hif_counter_intr_sched(s); 
     1249        } 
    11211250        break; 
    11221251    case AR6K_SCRATCH ... (AR6K_SCRATCH + 7): 
     
    11281257    case AR6K_LOCAL_BUS_ENDIAN: 
    11291258    case AR6K_LOCAL_BUS: 
     1259        goto bad_reg; 
     1260 
    11301261    case AR6K_INT_WLAN: 
     1262        s->hif.wlan_int = value; 
     1263        if (value) 
     1264            fprintf(stderr, "%s: WLAN interrupt\n", __FUNCTION__); 
     1265        break; 
     1266 
    11311267    case AR6K_WINDOW_DATA: 
    11321268    case AR6K_WRITE_ADDR: 
     
    11341270    case AR6K_SPI_CONFIG: 
    11351271        goto bad_reg; 
     1272 
    11361273    case AR6K_HIF_MBOX_BASE ... AR6K_HIF_MBOX_END: 
    11371274        mbox = (addr - AR6K_HIF_MBOX_BASE) >> 11; 
    11381275        s->hif.mbox[addr - AR6K_HIF_MBOX_BASE] = value; 
    11391276        s->hif.mbox_count[mbox] ++; 
    1140         /* XXX how do we know when a BMI command is executed?  */ 
    1141         if (mbox == 0 && !s->bmi.done) { 
    1142             s->hif.cnt_dec[4] = 0x00; 
    1143             s->hif.cnt[4] = 0x00; 
    1144             if ((addr & 0x7ff) == 0x7ff) { 
     1277        /* XXX how else do we know when a command is executed?  */ 
     1278        if ((addr & 0x7ff) == 0x7ff) { 
     1279            ar6k_hif_txcredit_reset(s, mbox); 
     1280            if (mbox == 0 && !s->bmi.done) { 
    11451281                ar6k_bmi_write(s, s->hif.mbox + (mbox << 11), 
    1146                                 s->hif.mbox_count[0]); 
    1147                 s->hif.mbox_count[mbox] = 0; 
     1282                                s->hif.mbox_count[mbox]); 
     1283            } else { 
     1284                /* TODO */ 
    11481285            } 
     1286            s->hif.mbox_count[mbox] = 0; 
     1287            ar6k_hif_txcredit_grant(s, mbox); 
    11491288        } 
    11501289        break; 
     
    11581297static uint8_t ar6k_hif_read(struct ar6k_s *s, uint32_t addr) 
    11591298{ 
     1299    int mbox = 0; 
     1300 
    11601301    switch (addr) { 
    11611302    case AR6K_HOST_INT_STAT: 
     
    11671308    case AR6K_COUNTER_INT_STAT: 
    11681309        return s->hif.counter_int_stat; 
     1310 
    11691311    case AR6K_MBOX_FRAME: 
    11701312        return s->hif.mbox_frame; 
     1313 
    11711314    case AR6K_RX_LOOKAHEAD_VALID: 
    11721315        return s->hif.rx_la_valid; 
     
    11791322    case AR6K_RX_LOOKAHEAD3: 
    11801323        return s->hif.rx_la[3]; 
     1324 
    11811325    case AR6K_INT_STAT_ENABLE: 
    11821326        return s->hif.int_stat_ena; 
     
    11871331    case AR6K_COUNTER_INT_STAT_ENABLE: 
    11881332        return s->hif.cnt_int_stat_ena; 
    1189     case AR6K_COUNT ... (AR6K_COUNT + 0x7): 
    1190         return s->hif.cnt[addr - AR6K_COUNT]; 
    1191     case AR6K_COUNT_DEC + 0x00: 
    1192     case AR6K_COUNT_DEC + 0x04: 
    1193     case AR6K_COUNT_DEC + 0x08: 
    1194     case AR6K_COUNT_DEC + 0x0c: 
    1195     case AR6K_COUNT_DEC + 0x10: 
    1196     case AR6K_COUNT_DEC + 0x14: 
    1197     case AR6K_COUNT_DEC + 0x18: 
    1198     case AR6K_COUNT_DEC + 0x1c: 
    1199         return s->hif.cnt_dec[(addr - AR6K_COUNT_DEC) >> 2]; 
     1333 
     1334    case (AR6K_COUNT + 0x4) ... (AR6K_COUNT + 0x7): 
     1335        /* XXX What's at (AR6K_COUNT + 0x0) ... (AR6K_COUNT + 0x3)? */ 
     1336        /* FIXME clear some interrupts etc */ 
     1337        return s->hif.cnt[addr - AR6K_COUNT - 4]; 
     1338 
     1339    case AR6K_COUNT_RESET + 0xc: mbox ++; 
     1340    case AR6K_COUNT_RESET + 0x8: mbox ++; 
     1341    case AR6K_COUNT_RESET + 0x4: mbox ++; 
     1342    case AR6K_COUNT_RESET + 0x0: 
     1343        if (s->hif.counter_int_stat & (1 << mbox)) { 
     1344            s->hif.counter_int_stat &= ~(1 << mbox); 
     1345            ar6k_hif_counter_intr_update(s); 
     1346        } 
     1347        return s->hif.cnt_tx[mbox]; 
     1348 
     1349    case AR6K_COUNT_DEC + 0xc: mbox ++; 
     1350    case AR6K_COUNT_DEC + 0x8: mbox ++; 
     1351    case AR6K_COUNT_DEC + 0x4: mbox ++; 
     1352    case AR6K_COUNT_DEC + 0x0: 
     1353        return s->hif.cnt_tx[mbox]; 
     1354 
    12001355    case AR6K_SCRATCH ... (AR6K_SCRATCH + 7): 
    12011356        return s->hif.scratch[addr - AR6K_SCRATCH]; 
     1357 
    12021358    case AR6K_FIFO_TIMEOUT: 
    12031359    case AR6K_FIFO_TIMEOUT_ENABLE: 
     
    12051361    case AR6K_LOCAL_BUS_ENDIAN: 
    12061362    case AR6K_LOCAL_BUS: 
     1363        goto bad_reg; 
     1364 
    12071365    case AR6K_INT_WLAN: 
     1366        return s->hif.wlan_int; 
     1367 
    12081368    case AR6K_WINDOW_DATA: 
    12091369    case AR6K_WRITE_ADDR: 
     
    13271487 
    13281488    s->nd = nd; 
     1489    s->cnt_irq_update = qemu_new_timer(vm_clock, ar6k_hif_cnt_irq_tick, s); 
    13291490    s->sd.reset = (void *) ar6k_reset; 
    13301491    s->sd.fbr[0].stdfn = 0 | sdio_fn_none; 
Note: See TracChangeset for help on using the changeset viewer.