Annotation of qemu/hw/esp.c, revision 1.1.1.12

1.1       root        1: /*
1.1.1.5   root        2:  * QEMU ESP/NCR53C9x emulation
1.1.1.6   root        3:  *
1.1.1.3   root        4:  * Copyright (c) 2005-2006 Fabrice Bellard
1.1.1.6   root        5:  *
1.1       root        6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
1.1.1.7   root       24: 
1.1.1.8   root       25: #include "sysbus.h"
1.1.1.7   root       26: #include "scsi.h"
1.1.1.9   root       27: #include "esp.h"
1.1       root       28: 
                     29: /* debug ESP card */
                     30: //#define DEBUG_ESP
                     31: 
1.1.1.5   root       32: /*
1.1.1.6   root       33:  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
                     34:  * also produced as NCR89C100. See
1.1.1.5   root       35:  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
                     36:  * and
                     37:  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
                     38:  */
                     39: 
1.1       root       40: #ifdef DEBUG_ESP
1.1.1.8   root       41: #define DPRINTF(fmt, ...)                                       \
                     42:     do { printf("ESP: " fmt , ## __VA_ARGS__); } while (0)
1.1       root       43: #else
1.1.1.8   root       44: #define DPRINTF(fmt, ...) do {} while (0)
1.1       root       45: #endif
                     46: 
1.1.1.8   root       47: #define ESP_ERROR(fmt, ...)                                             \
                     48:     do { printf("ESP ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
1.1.1.7   root       49: 
1.1.1.6   root       50: #define ESP_REGS 16
1.1.1.7   root       51: #define TI_BUFSZ 16
1.1.1.5   root       52: 
1.1.1.3   root       53: typedef struct ESPState ESPState;
1.1       root       54: 
1.1.1.3   root       55: struct ESPState {
1.1.1.8   root       56:     SysBusDevice busdev;
1.1.1.7   root       57:     uint32_t it_shift;
1.1.1.6   root       58:     qemu_irq irq;
                     59:     uint8_t rregs[ESP_REGS];
                     60:     uint8_t wregs[ESP_REGS];
1.1.1.5   root       61:     int32_t ti_size;
1.1.1.2   root       62:     uint32_t ti_rptr, ti_wptr;
                     63:     uint8_t ti_buf[TI_BUFSZ];
1.1.1.12! root       64:     uint32_t status;
1.1.1.7   root       65:     uint32_t dma;
1.1.1.9   root       66:     SCSIBus bus;
1.1.1.4   root       67:     SCSIDevice *current_dev;
1.1.1.12! root       68:     SCSIRequest *current_req;
1.1.1.4   root       69:     uint8_t cmdbuf[TI_BUFSZ];
1.1.1.7   root       70:     uint32_t cmdlen;
                     71:     uint32_t do_cmd;
1.1.1.5   root       72: 
                     73:     /* The amount of data left in the current DMA transfer.  */
                     74:     uint32_t dma_left;
                     75:     /* The size of the current DMA transfer.  Zero if no transfer is in
                     76:        progress.  */
                     77:     uint32_t dma_counter;
                     78:     uint8_t *async_buf;
                     79:     uint32_t async_len;
1.1.1.7   root       80: 
1.1.1.10  root       81:     ESPDMAMemoryReadWriteFunc dma_memory_read;
                     82:     ESPDMAMemoryReadWriteFunc dma_memory_write;
1.1.1.5   root       83:     void *dma_opaque;
1.1.1.11  root       84:     int dma_enabled;
                     85:     void (*dma_cb)(ESPState *s);
1.1.1.3   root       86: };
1.1       root       87: 
1.1.1.6   root       88: #define ESP_TCLO   0x0
                     89: #define ESP_TCMID  0x1
                     90: #define ESP_FIFO   0x2
                     91: #define ESP_CMD    0x3
                     92: #define ESP_RSTAT  0x4
                     93: #define ESP_WBUSID 0x4
                     94: #define ESP_RINTR  0x5
                     95: #define ESP_WSEL   0x5
                     96: #define ESP_RSEQ   0x6
                     97: #define ESP_WSYNTP 0x6
                     98: #define ESP_RFLAGS 0x7
                     99: #define ESP_WSYNO  0x7
                    100: #define ESP_CFG1   0x8
                    101: #define ESP_RRES1  0x9
                    102: #define ESP_WCCF   0x9
                    103: #define ESP_RRES2  0xa
                    104: #define ESP_WTEST  0xa
                    105: #define ESP_CFG2   0xb
                    106: #define ESP_CFG3   0xc
                    107: #define ESP_RES3   0xd
                    108: #define ESP_TCHI   0xe
                    109: #define ESP_RES4   0xf
                    110: 
                    111: #define CMD_DMA 0x80
                    112: #define CMD_CMD 0x7f
                    113: 
                    114: #define CMD_NOP      0x00
                    115: #define CMD_FLUSH    0x01
                    116: #define CMD_RESET    0x02
                    117: #define CMD_BUSRESET 0x03
                    118: #define CMD_TI       0x10
                    119: #define CMD_ICCS     0x11
                    120: #define CMD_MSGACC   0x12
1.1.1.9   root      121: #define CMD_PAD      0x18
1.1.1.6   root      122: #define CMD_SATN     0x1a
1.1.1.9   root      123: #define CMD_SEL      0x41
1.1.1.6   root      124: #define CMD_SELATN   0x42
                    125: #define CMD_SELATNS  0x43
                    126: #define CMD_ENSEL    0x44
                    127: 
1.1       root      128: #define STAT_DO 0x00
                    129: #define STAT_DI 0x01
                    130: #define STAT_CD 0x02
                    131: #define STAT_ST 0x03
1.1.1.7   root      132: #define STAT_MO 0x06
                    133: #define STAT_MI 0x07
1.1.1.6   root      134: #define STAT_PIO_MASK 0x06
1.1       root      135: 
                    136: #define STAT_TC 0x10
1.1.1.5   root      137: #define STAT_PE 0x20
                    138: #define STAT_GE 0x40
1.1.1.7   root      139: #define STAT_INT 0x80
                    140: 
                    141: #define BUSID_DID 0x07
1.1       root      142: 
                    143: #define INTR_FC 0x08
                    144: #define INTR_BS 0x10
                    145: #define INTR_DC 0x20
1.1.1.2   root      146: #define INTR_RST 0x80
1.1       root      147: 
                    148: #define SEQ_0 0x0
                    149: #define SEQ_CD 0x4
                    150: 
1.1.1.6   root      151: #define CFG1_RESREPT 0x40
                    152: 
                    153: #define TCHI_FAS100A 0x4
                    154: 
1.1.1.7   root      155: static void esp_raise_irq(ESPState *s)
                    156: {
                    157:     if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
                    158:         s->rregs[ESP_RSTAT] |= STAT_INT;
                    159:         qemu_irq_raise(s->irq);
1.1.1.10  root      160:         DPRINTF("Raise IRQ\n");
1.1.1.7   root      161:     }
                    162: }
                    163: 
                    164: static void esp_lower_irq(ESPState *s)
                    165: {
                    166:     if (s->rregs[ESP_RSTAT] & STAT_INT) {
                    167:         s->rregs[ESP_RSTAT] &= ~STAT_INT;
                    168:         qemu_irq_lower(s->irq);
1.1.1.10  root      169:         DPRINTF("Lower IRQ\n");
1.1.1.7   root      170:     }
                    171: }
                    172: 
1.1.1.11  root      173: static void esp_dma_enable(void *opaque, int irq, int level)
                    174: {
                    175:     DeviceState *d = opaque;
                    176:     ESPState *s = container_of(d, ESPState, busdev.qdev);
                    177: 
                    178:     if (level) {
                    179:         s->dma_enabled = 1;
                    180:         DPRINTF("Raise enable\n");
                    181:         if (s->dma_cb) {
                    182:             s->dma_cb(s);
                    183:             s->dma_cb = NULL;
                    184:         }
                    185:     } else {
                    186:         DPRINTF("Lower enable\n");
                    187:         s->dma_enabled = 0;
                    188:     }
                    189: }
                    190: 
1.1.1.12! root      191: static void esp_request_cancelled(SCSIRequest *req)
        !           192: {
        !           193:     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
        !           194: 
        !           195:     if (req == s->current_req) {
        !           196:         scsi_req_unref(s->current_req);
        !           197:         s->current_req = NULL;
        !           198:         s->current_dev = NULL;
        !           199:     }
        !           200: }
        !           201: 
1.1.1.7   root      202: static uint32_t get_cmd(ESPState *s, uint8_t *buf)
1.1       root      203: {
1.1.1.5   root      204:     uint32_t dmalen;
1.1       root      205:     int target;
                    206: 
1.1.1.7   root      207:     target = s->wregs[ESP_WBUSID] & BUSID_DID;
1.1.1.2   root      208:     if (s->dma) {
1.1.1.7   root      209:         dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
                    210:         s->dma_memory_read(s->dma_opaque, buf, dmalen);
1.1.1.2   root      211:     } else {
1.1.1.7   root      212:         dmalen = s->ti_size;
                    213:         memcpy(buf, s->ti_buf, dmalen);
1.1.1.12! root      214:         buf[0] = buf[2] >> 5;
1.1.1.2   root      215:     }
1.1.1.7   root      216:     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
1.1.1.4   root      217: 
1.1       root      218:     s->ti_size = 0;
1.1.1.2   root      219:     s->ti_rptr = 0;
                    220:     s->ti_wptr = 0;
1.1       root      221: 
1.1.1.12! root      222:     if (s->current_req) {
1.1.1.5   root      223:         /* Started a new command before the old one finished.  Cancel it.  */
1.1.1.12! root      224:         scsi_req_cancel(s->current_req);
1.1.1.5   root      225:         s->async_len = 0;
                    226:     }
                    227: 
1.1.1.9   root      228:     if (target >= ESP_MAX_DEVS || !s->bus.devs[target]) {
1.1.1.4   root      229:         // No such drive
1.1.1.7   root      230:         s->rregs[ESP_RSTAT] = 0;
1.1.1.6   root      231:         s->rregs[ESP_RINTR] = INTR_DC;
                    232:         s->rregs[ESP_RSEQ] = SEQ_0;
1.1.1.7   root      233:         esp_raise_irq(s);
1.1.1.6   root      234:         return 0;
1.1       root      235:     }
1.1.1.9   root      236:     s->current_dev = s->bus.devs[target];
1.1.1.4   root      237:     return dmalen;
                    238: }
                    239: 
1.1.1.9   root      240: static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
1.1.1.4   root      241: {
                    242:     int32_t datalen;
                    243:     int lun;
                    244: 
1.1.1.9   root      245:     DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
                    246:     lun = busid & 7;
1.1.1.12! root      247:     s->current_req = scsi_req_new(s->current_dev, 0, lun, NULL);
        !           248:     datalen = scsi_req_enqueue(s->current_req, buf);
1.1.1.5   root      249:     s->ti_size = datalen;
                    250:     if (datalen != 0) {
1.1.1.7   root      251:         s->rregs[ESP_RSTAT] = STAT_TC;
1.1.1.5   root      252:         s->dma_left = 0;
                    253:         s->dma_counter = 0;
1.1.1.4   root      254:         if (datalen > 0) {
1.1.1.6   root      255:             s->rregs[ESP_RSTAT] |= STAT_DI;
1.1.1.4   root      256:         } else {
1.1.1.6   root      257:             s->rregs[ESP_RSTAT] |= STAT_DO;
1.1.1.2   root      258:         }
1.1.1.12! root      259:         scsi_req_continue(s->current_req);
1.1       root      260:     }
1.1.1.6   root      261:     s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    262:     s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      263:     esp_raise_irq(s);
1.1       root      264: }
                    265: 
1.1.1.9   root      266: static void do_cmd(ESPState *s, uint8_t *buf)
                    267: {
                    268:     uint8_t busid = buf[0];
                    269: 
                    270:     do_busid_cmd(s, &buf[1], busid);
                    271: }
                    272: 
1.1.1.4   root      273: static void handle_satn(ESPState *s)
                    274: {
                    275:     uint8_t buf[32];
                    276:     int len;
                    277: 
1.1.1.11  root      278:     if (!s->dma_enabled) {
                    279:         s->dma_cb = handle_satn;
                    280:         return;
                    281:     }
1.1.1.4   root      282:     len = get_cmd(s, buf);
                    283:     if (len)
                    284:         do_cmd(s, buf);
                    285: }
                    286: 
1.1.1.9   root      287: static void handle_s_without_atn(ESPState *s)
                    288: {
                    289:     uint8_t buf[32];
                    290:     int len;
                    291: 
1.1.1.11  root      292:     if (!s->dma_enabled) {
                    293:         s->dma_cb = handle_s_without_atn;
                    294:         return;
                    295:     }
1.1.1.9   root      296:     len = get_cmd(s, buf);
                    297:     if (len) {
                    298:         do_busid_cmd(s, buf, 0);
                    299:     }
                    300: }
                    301: 
1.1.1.4   root      302: static void handle_satn_stop(ESPState *s)
1.1       root      303: {
1.1.1.11  root      304:     if (!s->dma_enabled) {
                    305:         s->dma_cb = handle_satn_stop;
                    306:         return;
                    307:     }
1.1.1.4   root      308:     s->cmdlen = get_cmd(s, s->cmdbuf);
                    309:     if (s->cmdlen) {
                    310:         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
                    311:         s->do_cmd = 1;
1.1.1.7   root      312:         s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
1.1.1.6   root      313:         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    314:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      315:         esp_raise_irq(s);
1.1.1.4   root      316:     }
                    317: }
1.1       root      318: 
1.1.1.4   root      319: static void write_response(ESPState *s)
                    320: {
1.1.1.12! root      321:     DPRINTF("Transfer status (status=%d)\n", s->status);
        !           322:     s->ti_buf[0] = s->status;
1.1.1.4   root      323:     s->ti_buf[1] = 0;
1.1.1.2   root      324:     if (s->dma) {
1.1.1.7   root      325:         s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
                    326:         s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
1.1.1.6   root      327:         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
                    328:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.2   root      329:     } else {
1.1.1.6   root      330:         s->ti_size = 2;
                    331:         s->ti_rptr = 0;
                    332:         s->ti_wptr = 0;
                    333:         s->rregs[ESP_RFLAGS] = 2;
1.1.1.2   root      334:     }
1.1.1.7   root      335:     esp_raise_irq(s);
1.1.1.5   root      336: }
1.1       root      337: 
1.1.1.5   root      338: static void esp_dma_done(ESPState *s)
                    339: {
1.1.1.7   root      340:     s->rregs[ESP_RSTAT] |= STAT_TC;
1.1.1.6   root      341:     s->rregs[ESP_RINTR] = INTR_BS;
                    342:     s->rregs[ESP_RSEQ] = 0;
                    343:     s->rregs[ESP_RFLAGS] = 0;
                    344:     s->rregs[ESP_TCLO] = 0;
                    345:     s->rregs[ESP_TCMID] = 0;
1.1.1.7   root      346:     esp_raise_irq(s);
1.1       root      347: }
1.1.1.2   root      348: 
1.1.1.5   root      349: static void esp_do_dma(ESPState *s)
                    350: {
                    351:     uint32_t len;
                    352:     int to_device;
                    353: 
                    354:     to_device = (s->ti_size < 0);
                    355:     len = s->dma_left;
                    356:     if (s->do_cmd) {
                    357:         DPRINTF("command len %d + %d\n", s->cmdlen, len);
1.1.1.7   root      358:         s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
1.1.1.5   root      359:         s->ti_size = 0;
                    360:         s->cmdlen = 0;
                    361:         s->do_cmd = 0;
                    362:         do_cmd(s, s->cmdbuf);
                    363:         return;
                    364:     }
                    365:     if (s->async_len == 0) {
                    366:         /* Defer until data is available.  */
                    367:         return;
                    368:     }
                    369:     if (len > s->async_len) {
                    370:         len = s->async_len;
                    371:     }
                    372:     if (to_device) {
1.1.1.7   root      373:         s->dma_memory_read(s->dma_opaque, s->async_buf, len);
1.1.1.5   root      374:     } else {
1.1.1.7   root      375:         s->dma_memory_write(s->dma_opaque, s->async_buf, len);
1.1.1.5   root      376:     }
                    377:     s->dma_left -= len;
                    378:     s->async_buf += len;
                    379:     s->async_len -= len;
                    380:     if (to_device)
                    381:         s->ti_size += len;
                    382:     else
                    383:         s->ti_size -= len;
                    384:     if (s->async_len == 0) {
1.1.1.12! root      385:         scsi_req_continue(s->current_req);
        !           386:         /* If there is still data to be read from the device then
        !           387:            complete the DMA operation immediately.  Otherwise defer
        !           388:            until the scsi layer has completed.  */
        !           389:         if (to_device || s->dma_left != 0 || s->ti_size == 0) {
        !           390:             return;
1.1.1.5   root      391:         }
                    392:     }
1.1.1.12! root      393: 
        !           394:     /* Partially filled a scsi buffer. Complete immediately.  */
        !           395:     esp_dma_done(s);
1.1.1.5   root      396: }
                    397: 
1.1.1.12! root      398: static void esp_command_complete(SCSIRequest *req, uint32_t status)
1.1.1.4   root      399: {
1.1.1.12! root      400:     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
1.1.1.4   root      401: 
1.1.1.12! root      402:     DPRINTF("SCSI Command complete\n");
        !           403:     if (s->ti_size != 0) {
        !           404:         DPRINTF("SCSI command completed unexpectedly\n");
        !           405:     }
        !           406:     s->ti_size = 0;
        !           407:     s->dma_left = 0;
        !           408:     s->async_len = 0;
        !           409:     if (status) {
        !           410:         DPRINTF("Command failed\n");
        !           411:     }
        !           412:     s->status = status;
        !           413:     s->rregs[ESP_RSTAT] = STAT_ST;
        !           414:     esp_dma_done(s);
        !           415:     if (s->current_req) {
        !           416:         scsi_req_unref(s->current_req);
        !           417:         s->current_req = NULL;
1.1.1.5   root      418:         s->current_dev = NULL;
1.1.1.12! root      419:     }
        !           420: }
        !           421: 
        !           422: static void esp_transfer_data(SCSIRequest *req, uint32_t len)
        !           423: {
        !           424:     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
        !           425: 
        !           426:     DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
        !           427:     s->async_len = len;
        !           428:     s->async_buf = scsi_req_get_buf(req);
        !           429:     if (s->dma_left) {
        !           430:         esp_do_dma(s);
        !           431:     } else if (s->dma_counter != 0 && s->ti_size <= 0) {
        !           432:         /* If this was the last part of a DMA transfer then the
        !           433:            completion interrupt is deferred to here.  */
        !           434:         esp_dma_done(s);
1.1.1.5   root      435:     }
1.1.1.4   root      436: }
1.1       root      437: 
                    438: static void handle_ti(ESPState *s)
                    439: {
1.1.1.5   root      440:     uint32_t dmalen, minlen;
1.1       root      441: 
1.1.1.6   root      442:     dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
1.1.1.4   root      443:     if (dmalen==0) {
                    444:       dmalen=0x10000;
                    445:     }
1.1.1.5   root      446:     s->dma_counter = dmalen;
1.1.1.4   root      447: 
                    448:     if (s->do_cmd)
                    449:         minlen = (dmalen < 32) ? dmalen : 32;
1.1.1.5   root      450:     else if (s->ti_size < 0)
                    451:         minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
1.1.1.4   root      452:     else
                    453:         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
                    454:     DPRINTF("Transfer Information len %d\n", minlen);
1.1.1.2   root      455:     if (s->dma) {
1.1.1.5   root      456:         s->dma_left = minlen;
1.1.1.6   root      457:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.5   root      458:         esp_do_dma(s);
1.1.1.4   root      459:     } else if (s->do_cmd) {
                    460:         DPRINTF("command len %d\n", s->cmdlen);
                    461:         s->ti_size = 0;
                    462:         s->cmdlen = 0;
                    463:         s->do_cmd = 0;
                    464:         do_cmd(s, s->cmdbuf);
                    465:         return;
                    466:     }
1.1       root      467: }
                    468: 
1.1.1.10  root      469: static void esp_hard_reset(DeviceState *d)
1.1       root      470: {
1.1.1.9   root      471:     ESPState *s = container_of(d, ESPState, busdev.qdev);
1.1.1.5   root      472: 
1.1.1.6   root      473:     memset(s->rregs, 0, ESP_REGS);
                    474:     memset(s->wregs, 0, ESP_REGS);
                    475:     s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
1.1.1.3   root      476:     s->ti_size = 0;
                    477:     s->ti_rptr = 0;
                    478:     s->ti_wptr = 0;
                    479:     s->dma = 0;
1.1.1.4   root      480:     s->do_cmd = 0;
1.1.1.11  root      481:     s->dma_cb = NULL;
1.1.1.7   root      482: 
                    483:     s->rregs[ESP_CFG1] = 7;
1.1       root      484: }
                    485: 
1.1.1.10  root      486: static void esp_soft_reset(DeviceState *d)
                    487: {
                    488:     ESPState *s = container_of(d, ESPState, busdev.qdev);
                    489: 
                    490:     qemu_irq_lower(s->irq);
                    491:     esp_hard_reset(d);
                    492: }
                    493: 
1.1.1.6   root      494: static void parent_esp_reset(void *opaque, int irq, int level)
                    495: {
1.1.1.10  root      496:     if (level) {
                    497:         esp_soft_reset(opaque);
                    498:     }
1.1.1.6   root      499: }
                    500: 
1.1.1.11  root      501: static void esp_gpio_demux(void *opaque, int irq, int level)
                    502: {
                    503:     switch (irq) {
                    504:     case 0:
                    505:         parent_esp_reset(opaque, irq, level);
                    506:         break;
                    507:     case 1:
                    508:         esp_dma_enable(opaque, irq, level);
                    509:         break;
                    510:     }
                    511: }
                    512: 
1.1       root      513: static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
                    514: {
                    515:     ESPState *s = opaque;
1.1.1.8   root      516:     uint32_t saddr, old_val;
1.1       root      517: 
1.1.1.7   root      518:     saddr = addr >> s->it_shift;
1.1.1.2   root      519:     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
1.1       root      520:     switch (saddr) {
1.1.1.6   root      521:     case ESP_FIFO:
                    522:         if (s->ti_size > 0) {
                    523:             s->ti_size--;
                    524:             if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
1.1.1.7   root      525:                 /* Data out.  */
                    526:                 ESP_ERROR("PIO data read not implemented\n");
1.1.1.6   root      527:                 s->rregs[ESP_FIFO] = 0;
1.1.1.4   root      528:             } else {
1.1.1.6   root      529:                 s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
1.1.1.4   root      530:             }
1.1.1.7   root      531:             esp_raise_irq(s);
1.1.1.6   root      532:         }
                    533:         if (s->ti_size == 0) {
1.1.1.2   root      534:             s->ti_rptr = 0;
                    535:             s->ti_wptr = 0;
                    536:         }
1.1.1.6   root      537:         break;
                    538:     case ESP_RINTR:
1.1.1.8   root      539:         /* Clear sequence step, interrupt register and all status bits
                    540:            except TC */
                    541:         old_val = s->rregs[ESP_RINTR];
                    542:         s->rregs[ESP_RINTR] = 0;
                    543:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
                    544:         s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7   root      545:         esp_lower_irq(s);
1.1.1.8   root      546: 
                    547:         return old_val;
1.1       root      548:     default:
1.1.1.6   root      549:         break;
1.1       root      550:     }
                    551:     return s->rregs[saddr];
                    552: }
                    553: 
                    554: static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
                    555: {
                    556:     ESPState *s = opaque;
                    557:     uint32_t saddr;
                    558: 
1.1.1.7   root      559:     saddr = addr >> s->it_shift;
1.1.1.6   root      560:     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],
                    561:             val);
1.1       root      562:     switch (saddr) {
1.1.1.6   root      563:     case ESP_TCLO:
                    564:     case ESP_TCMID:
                    565:         s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.2   root      566:         break;
1.1.1.6   root      567:     case ESP_FIFO:
1.1.1.4   root      568:         if (s->do_cmd) {
                    569:             s->cmdbuf[s->cmdlen++] = val & 0xff;
1.1.1.7   root      570:         } else if (s->ti_size == TI_BUFSZ - 1) {
                    571:             ESP_ERROR("fifo overrun\n");
1.1.1.4   root      572:         } else {
                    573:             s->ti_size++;
                    574:             s->ti_buf[s->ti_wptr++] = val & 0xff;
                    575:         }
1.1.1.6   root      576:         break;
                    577:     case ESP_CMD:
1.1.1.2   root      578:         s->rregs[saddr] = val;
1.1.1.6   root      579:         if (val & CMD_DMA) {
                    580:             s->dma = 1;
1.1.1.5   root      581:             /* Reload DMA counter.  */
1.1.1.6   root      582:             s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
                    583:             s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
                    584:         } else {
                    585:             s->dma = 0;
                    586:         }
                    587:         switch(val & CMD_CMD) {
                    588:         case CMD_NOP:
                    589:             DPRINTF("NOP (%2.2x)\n", val);
                    590:             break;
                    591:         case CMD_FLUSH:
                    592:             DPRINTF("Flush FIFO (%2.2x)\n", val);
1.1.1.2   root      593:             //s->ti_size = 0;
1.1.1.6   root      594:             s->rregs[ESP_RINTR] = INTR_FC;
                    595:             s->rregs[ESP_RSEQ] = 0;
1.1.1.7   root      596:             s->rregs[ESP_RFLAGS] = 0;
1.1.1.6   root      597:             break;
                    598:         case CMD_RESET:
                    599:             DPRINTF("Chip reset (%2.2x)\n", val);
1.1.1.10  root      600:             esp_soft_reset(&s->busdev.qdev);
1.1.1.6   root      601:             break;
                    602:         case CMD_BUSRESET:
                    603:             DPRINTF("Bus reset (%2.2x)\n", val);
                    604:             s->rregs[ESP_RINTR] = INTR_RST;
                    605:             if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
1.1.1.7   root      606:                 esp_raise_irq(s);
1.1.1.2   root      607:             }
1.1.1.6   root      608:             break;
                    609:         case CMD_TI:
                    610:             handle_ti(s);
                    611:             break;
                    612:         case CMD_ICCS:
                    613:             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
                    614:             write_response(s);
1.1.1.7   root      615:             s->rregs[ESP_RINTR] = INTR_FC;
                    616:             s->rregs[ESP_RSTAT] |= STAT_MI;
1.1.1.6   root      617:             break;
                    618:         case CMD_MSGACC:
                    619:             DPRINTF("Message Accepted (%2.2x)\n", val);
                    620:             s->rregs[ESP_RINTR] = INTR_DC;
                    621:             s->rregs[ESP_RSEQ] = 0;
1.1.1.9   root      622:             s->rregs[ESP_RFLAGS] = 0;
                    623:             esp_raise_irq(s);
                    624:             break;
                    625:         case CMD_PAD:
                    626:             DPRINTF("Transfer padding (%2.2x)\n", val);
                    627:             s->rregs[ESP_RSTAT] = STAT_TC;
                    628:             s->rregs[ESP_RINTR] = INTR_FC;
                    629:             s->rregs[ESP_RSEQ] = 0;
1.1.1.6   root      630:             break;
                    631:         case CMD_SATN:
                    632:             DPRINTF("Set ATN (%2.2x)\n", val);
                    633:             break;
1.1.1.9   root      634:         case CMD_SEL:
                    635:             DPRINTF("Select without ATN (%2.2x)\n", val);
                    636:             handle_s_without_atn(s);
                    637:             break;
1.1.1.6   root      638:         case CMD_SELATN:
1.1.1.9   root      639:             DPRINTF("Select with ATN (%2.2x)\n", val);
1.1.1.6   root      640:             handle_satn(s);
                    641:             break;
                    642:         case CMD_SELATNS:
1.1.1.9   root      643:             DPRINTF("Select with ATN & stop (%2.2x)\n", val);
1.1.1.6   root      644:             handle_satn_stop(s);
                    645:             break;
                    646:         case CMD_ENSEL:
                    647:             DPRINTF("Enable selection (%2.2x)\n", val);
1.1.1.7   root      648:             s->rregs[ESP_RINTR] = 0;
1.1.1.6   root      649:             break;
                    650:         default:
1.1.1.7   root      651:             ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
1.1.1.6   root      652:             break;
                    653:         }
                    654:         break;
                    655:     case ESP_WBUSID ... ESP_WSYNO:
                    656:         break;
                    657:     case ESP_CFG1:
1.1.1.2   root      658:         s->rregs[saddr] = val;
                    659:         break;
1.1.1.6   root      660:     case ESP_WCCF ... ESP_WTEST:
1.1.1.2   root      661:         break;
1.1.1.7   root      662:     case ESP_CFG2 ... ESP_RES4:
1.1.1.2   root      663:         s->rregs[saddr] = val;
                    664:         break;
1.1       root      665:     default:
1.1.1.7   root      666:         ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
                    667:         return;
1.1       root      668:     }
                    669:     s->wregs[saddr] = val;
                    670: }
                    671: 
1.1.1.9   root      672: static CPUReadMemoryFunc * const esp_mem_read[3] = {
1.1       root      673:     esp_mem_readb,
1.1.1.6   root      674:     NULL,
                    675:     NULL,
1.1       root      676: };
                    677: 
1.1.1.9   root      678: static CPUWriteMemoryFunc * const esp_mem_write[3] = {
1.1       root      679:     esp_mem_writeb,
1.1.1.6   root      680:     NULL,
1.1.1.7   root      681:     esp_mem_writeb,
1.1       root      682: };
                    683: 
1.1.1.9   root      684: static const VMStateDescription vmstate_esp = {
                    685:     .name ="esp",
                    686:     .version_id = 3,
                    687:     .minimum_version_id = 3,
                    688:     .minimum_version_id_old = 3,
                    689:     .fields      = (VMStateField []) {
                    690:         VMSTATE_BUFFER(rregs, ESPState),
                    691:         VMSTATE_BUFFER(wregs, ESPState),
                    692:         VMSTATE_INT32(ti_size, ESPState),
                    693:         VMSTATE_UINT32(ti_rptr, ESPState),
                    694:         VMSTATE_UINT32(ti_wptr, ESPState),
                    695:         VMSTATE_BUFFER(ti_buf, ESPState),
1.1.1.12! root      696:         VMSTATE_UINT32(status, ESPState),
1.1.1.9   root      697:         VMSTATE_UINT32(dma, ESPState),
                    698:         VMSTATE_BUFFER(cmdbuf, ESPState),
                    699:         VMSTATE_UINT32(cmdlen, ESPState),
                    700:         VMSTATE_UINT32(do_cmd, ESPState),
                    701:         VMSTATE_UINT32(dma_left, ESPState),
                    702:         VMSTATE_END_OF_LIST()
1.1.1.5   root      703:     }
1.1.1.9   root      704: };
1.1.1.5   root      705: 
1.1.1.8   root      706: void esp_init(target_phys_addr_t espaddr, int it_shift,
1.1.1.10  root      707:               ESPDMAMemoryReadWriteFunc dma_memory_read,
                    708:               ESPDMAMemoryReadWriteFunc dma_memory_write,
1.1.1.11  root      709:               void *dma_opaque, qemu_irq irq, qemu_irq *reset,
                    710:               qemu_irq *dma_enable)
1.1.1.8   root      711: {
                    712:     DeviceState *dev;
                    713:     SysBusDevice *s;
                    714:     ESPState *esp;
                    715: 
                    716:     dev = qdev_create(NULL, "esp");
                    717:     esp = DO_UPCAST(ESPState, busdev.qdev, dev);
                    718:     esp->dma_memory_read = dma_memory_read;
                    719:     esp->dma_memory_write = dma_memory_write;
                    720:     esp->dma_opaque = dma_opaque;
                    721:     esp->it_shift = it_shift;
1.1.1.11  root      722:     /* XXX for now until rc4030 has been changed to use DMA enable signal */
                    723:     esp->dma_enabled = 1;
1.1.1.9   root      724:     qdev_init_nofail(dev);
1.1.1.8   root      725:     s = sysbus_from_qdev(dev);
                    726:     sysbus_connect_irq(s, 0, irq);
                    727:     sysbus_mmio_map(s, 0, espaddr);
1.1.1.9   root      728:     *reset = qdev_get_gpio_in(dev, 0);
1.1.1.11  root      729:     *dma_enable = qdev_get_gpio_in(dev, 1);
1.1.1.8   root      730: }
                    731: 
1.1.1.12! root      732: static const struct SCSIBusOps esp_scsi_ops = {
        !           733:     .transfer_data = esp_transfer_data,
        !           734:     .complete = esp_command_complete,
        !           735:     .cancel = esp_request_cancelled
        !           736: };
        !           737: 
1.1.1.9   root      738: static int esp_init1(SysBusDevice *dev)
1.1       root      739: {
1.1.1.8   root      740:     ESPState *s = FROM_SYSBUS(ESPState, dev);
1.1.1.5   root      741:     int esp_io_memory;
1.1       root      742: 
1.1.1.8   root      743:     sysbus_init_irq(dev, &s->irq);
                    744:     assert(s->it_shift != -1);
1.1       root      745: 
1.1.1.11  root      746:     esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s,
                    747:                                            DEVICE_NATIVE_ENDIAN);
1.1.1.8   root      748:     sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
1.1       root      749: 
1.1.1.11  root      750:     qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
1.1.1.6   root      751: 
1.1.1.12! root      752:     scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, &esp_scsi_ops);
1.1.1.10  root      753:     return scsi_bus_legacy_handle_cmdline(&s->bus);
1.1.1.5   root      754: }
1.1.1.8   root      755: 
1.1.1.9   root      756: static SysBusDeviceInfo esp_info = {
                    757:     .init = esp_init1,
                    758:     .qdev.name  = "esp",
                    759:     .qdev.size  = sizeof(ESPState),
                    760:     .qdev.vmsd  = &vmstate_esp,
1.1.1.10  root      761:     .qdev.reset = esp_hard_reset,
1.1.1.9   root      762:     .qdev.props = (Property[]) {
                    763:         {.name = NULL}
                    764:     }
                    765: };
                    766: 
1.1.1.8   root      767: static void esp_register_devices(void)
                    768: {
1.1.1.9   root      769:     sysbus_register_withprop(&esp_info);
1.1.1.8   root      770: }
                    771: 
                    772: device_init(esp_register_devices)

unix.superglobalmegacorp.com